Воодушевлён Obsidian ! Просто воодушевлён. Крутейшая программа.
Obsidian с темой Minimal в варианте Solarized
Софт для написания и ведения текстовых заметок для меня — это очень важная часть моей жизни. Важнейшая. Надо что-то сохранить, чтобы потом быстро найти? Записал в заметки. Часто требующаяся информация, реквизиты и тп? Записал в заметки. Надо написать сценарий на Youtube или текст поста? Конечно, в заметки.
Накидать туториал по настройке какой-то штуки? Привет, заметки. Написать партнёрам схему интеграции с нами? Заметки, расшарить ссылку, готово.
Пользовался долго Evernote, потом Notion, но, как минимум, пользоваться ими сейчас в РФ небезопасно, так как ты не владеешь своими данными, можно проснуться однажды и прочесть новость, что Evernote/Notion/кто угодно принял решение остановить работу с россиянами и заодно удалить к херам собачьим все их данные, потому что как бы ну а чо нет. Рыбаков рассказывал (и у меня нет причин ему не верить), как люди потеряли доступ к своим моделям и чертежам в САПРах, которые лежали в корпоративных облаках. Вжух и результаты многолетней работы испарились:)
Obsidian. Как я попал в кроличью нору или моя система работы с заметками
Поэтому сейчас надо хранить важные данные локально. Заметки — Markdown файлы, для синхронизации которых можно использовать, например, git или Syncthing . Такие файлы можно писать и читать в любом текстовом редакторе, абсолютно любом.
Но — хочется ведь удобно. Чтобы эстетически приятно. Чтобы шрифты кириллические и английские нормально работали и тп.
И я вчера потратил много времени, перебирая разные варианты. Typora, iA Writer, Zettlr, Bear, Ulysses и много других. Лучший вариант с гигантским отрывом — Obsidian . Вообще эта программа позиционируется для ведения картотеки по модной нынче методологии Zettelkasten, но это всё опционально. У Obsidian просто есть всё нужное лично мне и оно отлично работает.
Фичи
Vim-mode включается просто из настроек без плагинов:)
Источник: dzen.ru
Воспитание Obsidian — вашего персонального информационного менеджера
Методик повышения личной эффективности хоть пруд пруди. Как по мне, основная проблема с ними в том, что нужно работать самому. Совершенно нормальное стремление — избежать приложения усилий. Пускай хорошая методика и есть тот рычаг, коим обещают сдвинуть Землю, но физика знает, что всю-всю работу делать всё равно нам самим.
Основной вопрос, терзавший меня в вопросе выбора персонального информационного менеджера заключался в том, что он будет делать вместо меня. Задача была не самая лёгкая. За короткий срок разобраться в новой области — организовать конспекты, классифицировать справочники и литературу по теме. Море открытых вкладок браузера (всё очень нужное, оно не должно скрыться из глаз), pdf-файлы, заботливо присланные новыми коллегами… С этим всем в голове я познакомился с программой Obsidian, которая пообещала стать A second brain, for you, forever.
Productivity | Zettelkasten в Obsidian
Преодолевая скепсис
В прошлом посте Markdown в науке я рассмотрел некоторые pro et contra использования Markdown-формата записей для исследователей. Вкратце ещё раз перечислю: простой текст, легко читаемый без всяких дополнительных программ, широкое распространение и поддержка, возможность использования готовых фрагментов для наполнения сайтов и создания презентаций.
База знаний (в терминологии Obsidian — vault, хранилище) это просто папка на диске, куда вы складываете Markdown-заметки, мультимедиафайлы, иллюстрации и уже созданные кем-то книги и статьи (pdf). Всё, что имеет отношение к делу, вы просто перетаскиваете в окно программы и оно окажется в этой самой папке.
Скопированный из статьи Википедии абзац с форматированием и ссылками автоматически преобразуется в Markdown.
Начать сбор материалов очень просто — копируем с веб-страниц (разметка и ссылки сохраняются), перетаскиваем файлы и подписываем свои комментарии к тому, что образуется. Программа бесплатная, есть под разные платформы — Linux, Windows, Mac OS.
Вот так выглядит Obsidian.
Добавляем порядок
«В этой базе собраны знания о том, что есть квантовая точка». Вот и первый термин. Запишем его в квадратных скобках
В этой базе собраны знания о том, что есть [[квантовая точка]]
Obsidian распознает термин в двойных квадратных скобках как внутреннюю ссылку, в противоположность стандартной внешней ссылке Markdown-текста.
%% Внутренняя ссылка %% [[README]] %% Внешняя ссылка %% [README](https://github.com/malykhin-sergei/obsidian-howto#readme) %% Встраивание документа %% 
Встраивание документа — killer feature Obsidian.
На этих трёх китах основывается вся магия Obsidian. Связи между заметками, связи с внешним миром и встраивание. Помимо привычных гипертекстовых ссылок, т.е. связей от текущего места просмотра, Obsidian показывает в панели Backlinks, с каких страниц есть ссылки на данную.
Вряд ли сейчас можно удивить кого-либо возможностью инкрементного поиска (вкратце: вы набираете начало термина — программа выдает список знакомых ей вариантов продолжения). Он в наличии и многоуровневые хештеги Obsidian с ним прекрасно сочетаются.
Последний, но важный момент. Не бойтесь пробовать! Если вы переименуете заметку (приложенный ресурс), перетащите её в другую папку (с помощью панели File explorer программы) — все связанные ссылки обновятся сами. Не нравится структура, что по-быстрому была накидана поздним вечером? Нет проблем, перетаскивайте, переименовывайте как душе угодно.
Редактирование и возможности
Кроме того, что Markdown заметки редактируются, в том числе и визуально (WYSIWYG-принцип), в списке ниже представлено, что понимает и умеет делать программа из коробки.
- многоуровневые хештеги #справка/химия/нано ;
- таблицы и иллюстрации;
- математические формулы MathJax;
- встраивание мультимедиа;
- подсветка синтаксиса программ;
- диаграммы Mermaid.
Редактор Obsidian — бимодальный. Это означает, что пока вы находитесь в режиме редактирования, вы видите Markdown-разметку. С квадратными скобками и некоторыми другими вспомогательными символами, о коих напишу после. Переключившись в режим просмотра (Ctrl-e) мы видим оформленную страницу, со ссылкой квантовая точка. Ссылка ещё никуда не ведёт, но один клик — и мы редактируем новую заметку с названием квантовая точка.
Возможности редактора хорошо изучаются на примерах. Выберете Open another vault (кнопка слева), выберете Obsidian help . Здесь online help. Увидите что-то понравившееся из оформления, переключаетесь в режим редактирования, изучайте как оно сделано и копируете к себе.
В качестве небольшой шпаргалки я создал демонстрационное хранилище, доступное для скачивания. В нем описаны конкретные детали, чтобы помочь новичкам: как легче завести таблицу (онлайн-инструменты), примеры диаграмм и формул.
На что не стоит рассчитывать с Obsidian
В мире полно различных wiki-движков с разными возможностями, диалектов Markdown и редакторов. Лучшее применение Obsidian в настоящий момент это wiki-заметки для себя. Порог вхождения минимальный для людей не специализирующихся строго в IT. Итак, вам подойдет программа, если:
- заметки ведутся для себя
- нет понятия о том, как устанавливать и настраивать wiki-движки и/или плагины к ним
- Markdown-разметка для вас вещь новая
- не требуется экспорт в другие форматы (экспорт в PDF пока работает нестабильно)
Обучаем вашего помощника
Почему Obsidian удобен в деле освоения новых знаний? Он реализует необходимую функциональность для применения ментальной техники Zettelkasten. О ней уже всё рассказано в посте Zettelkasten: как один немецкий учёный стал невероятно продуктивным, так что я не буду повторяться. Думаю, что метод Zettelkasten просто (нет, кого я обманываю, это не так просто) позволяет бороться с прокрастинацией. Это пагубная иррациональная склонность откладывать дело под любыми предлогами и ничего не делать.
Совет простой: пишите краткие заметки (атомарность изложения важна), переходите от темы к теме, выстраивайте связи. Пускай логическая нестройность не беспокоит — всегда можно поправить её потом. Каждая заметка станет своего рода нейроном будущей нейросети, обрастет синапсами и через какое-то время… Ваш помощник обретет разум, станет работать вместе с вами.
Во всяком случае, именно этим объяснял полезность своей системы её создатель — Никлас Луман. Доказательства убедительные — он написал более 70 книг и 400 статей, причём сам. В его время не было персонального компьютера и интернет. Он изобрел свой вариант гиперссылок, читайте о нем подробнее тут и на LessWrong.
Это кажется удивительным, что его обученная нейросеть работает на карточках в ящичках, но, даже такое возможно. Ведь есть и Нейронная сеть на спичечных коробках. Сколько понадобится заметок написать, пока она заговорит? Скорее всего, очень много, может тысячи, всё же оно стоит того. Прокрастинация будет повержена.
Облачные серверы от Маклауд быстрые и безопасные.
Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!
Источник: habr.com
Исследуем защиту Obsidium
Данная защита появилась достаточно недавно, поэтому найти программу стороннего разработчика для исследования мне не удалось.
Да и зачем, учитывая, что исполняемый файл защищен этой же защитой. Лично я думаю, что нигде нельзя увидеть защиту во всей красе, кроме как на программном продукте этого же разработчика.
Tools: Soft-Ice, HIEW, Lord PE, Import Reconstructor.
Obsidium использует вот такие приколы для затруднения анализа:
- Независимо от того, сколько секций было до этого, но после обработки их становиться 5 с затертыми именами (не
затёрто только название секции .rsrc). - Запакованные ресурсы.
- Своеобразные переходники в импорте.
- Управление на функции из внешних dll передается обычно на 3-ю от начала инструкцию.
- Вызовы GetTickCount для замера времени выполнения некоторых участков.
- Определяет наличие отладчика 3 уровня, чтобы он трогал Soft-Ice я не заметил.
- Обнаружение драйвера revirgin’а: CreateFileA(“\.RvtracerDevice0”).
- Relocation образа исполняемого файла, а не только
dll. - Динамическая распаковка.
- Собственные API.
- Вставка в некоторые места программы ложных инструкций, с последующей обработкой этих исключений.З
- абирает к себе несколько начальных байт из
OEP. - Большое количество мусорных инструкций.
Кстати, хочу заметить, что работу с dll данная защита пока не поддерживает.
Небольшое введение
Практически все производимые операции obsidium реализует на основе нескольких функций, которые записаны вот в такую структуру:
Смешение | Описание |
+0 | Базовый адрес, по которому находится новый образ исполняемого файла. |
+20 | Вызывает процедуру, CRC имени которой ей передана в качестве параметра. |
+24 | Определяет длину инструкции, адрес на которую передан в качестве параметра. |
+30 | Считает контрольную сумму строки переданной в параметре. |
+39 | Старый базовый адрес исполняемого файла(до обработки защитой) |
+40 | Ищет адрес функции, по CRC имени. |
+44 | Ищет адрес начала образа библиотеки. |
+48 | Базовый адрес библиотеки kernel32.dll |
+4C | Базовый адрес библиотеки user32.dll |
+50 | Размер образа исполняемого файла. |
+68 | Используя релоки, производит настройку кода на новый базовый адрес. |
+С8 | Полная распаковка необходимого участка. |
Сразу хочу заметить, что здесь представлены описания не всех полей структуры, да и те, которые помещены, могут быть не совсем правильными, т.к. я заходил не во все из них и о некоторых судил, только путем анализа входных и выходных данных, хотя учитывая, что я еще не видел ни одной программы защищенной им,
думаю этих сведений вполне достаточно.
Небольшое примечание: немного забегу вперед, но вот что я заметил
— Obsidium несколько видоизменяет релоки таким образом, что он использует их не только для настройки на новый базовый адрес, но и для дописывания некоторого кода. Например, у меня при динамической расшифровке один кусок расшифровывался неправильно без релоков, а с релоками в программе появились специально вставленные инструкции, вызывающие ошибки, которые обрабатывает сама защита.
Снятие дампа
Итак, при распаковке происходят следующие вещи:
- Выделяется 1-й раз место под переходники для импорта и другую необходимую информацию для защиты.
- Выделяется 2-й раз место для хранения промежуточных данных.
- Выделяется 3-й раз место для образа исполняемого файла.
- Производиться конечная распаковка файла.
- Настройка кода исполняемого файла с учетом нового базового адреса.
- Выделяется 4-й раз место (для чего я так и не понял).
- Удаляется выделенное на 2 этапе место.
Также хочу заметить, что все место, выделяемое защитой для работы исполняемого файла легко выделить, т.к. на этих участках стоит атрибут
Read+Write+Execute.
Итак, ставим бряк на VirtualAlloc (bpx VirtualAlloc+3) и ждем, когда вызов произойдет в 3 раз, потом выходим и топаем до тех пор, пока новый выделенный участок не заполниться данными (у меня он почти всегда находился по адресу 009С0000). Если попутно вы будете обходить все вызовы [ebx+68], то получите данные без использования релоков. Вызов функции [ebx+68] полезен тем, что он дает возможность узнать какие бывшие секции, куда “проецируются”. Узнать это можно посмотрев на передаваемые ей параметры, один из них — это смещение относительно базового адреса и размер. В итоге получаем:
№ | Смещение | Размер |
1 | 1000 | C1000 |
2 | C2000 | C200 |
3 | D3000 | 200 |
Поиск OEP и спертых байт
Найти предположительную OEP можно, если после дампа забить все байтом СС и в SI поставить бряк на int 3(bpint 3). Но это только предположительно, т.к. есть еще те байты, которые защита забрал к себе и до них
придется топать самостоятельно. Желательно предварительно поставить бряк на VirtualFree (bpx VirtualFree+3). Выход к OEP выглядит следующим образом:
seg000:007F5C08 mov byte ptr [ebp+eax+40C228h], 0E9h ; ‘щ’
seg000:007F5C16 mov edx, [ebp+40C334h]
seg000:007F5C21 add edx, [esi]
seg000:007F5C26 lea ecx, [ebp+eax+40C22Dh]
seg000:007F5C32 sub edx, ecx
seg000:007F5C38 mov [ebp+eax+40C229h], edx
seg000:007F5C44 popa
seg000:007F5C4A popf
// —————————Далее идут украденные байты
————————— //
seg000:007F5C53 mov eax, ds:0A8208Bh
seg000:007F5C5B shl eax, 2
seg000:007F5C64 mov ds:0A8208Fh, eax
seg000:007F5C6C push edx
seg000:007F5C71 push 0
seg000:007F5C79 jmp near ptr 9C144Ah ;
дальнейшее выполнение программы
(Для хорошей читабельности мусор и постоянные jmp удалены).
Импорт тут представляет собой достаточно занимательное зрелище.
Вставляются переходники, которые выглядят вот так:
seg000:007F3E60 pusha
seg000:007F3E61 mov ax, 0 ; смещение в этом Thunck’е
seg000:007F3E65 mov dl, 0 ; Thunck
seg000:007F3E67 jmp loc_7F314C
Потом выполняется функция, которая и выполняет все работу. Эта функция берет из специально таблички атрибут данной функции и в зависимости от него решает, что дальше делать с этой функцией. Всего возможно 4 варианта:
- Это API Obsidium’а.
- В табличке храниться CRC имени функции.
- В табличке храниться по XOR’нный адрес функции.
- Адрес функции храниться не в этой табличке и функция вызывается несколько по-другому.
- Функции, значение которых не меняется на протяжении всего времени выполнения программы.
Интересный момент, что Obsidium заполняет в IAT на 1 больше ячеек, таким образом если IAT нескольких библиотек шли подряд, то после обработки их Obsidium’ом ImpRec распознает только одну большую IAT. Так же интересным моментом является то, что защита использует нечто вроде «кэширования», т.е. в связи с тем, что операция поиска адреса функции по CRC её имени может занимать достаточно много времени, то чтобы не вызывать эту функцию несколько раз он берет и записывает адрес искомой функции вместо адреса переходника. Я функции, относящиеся ко 2 и 3-му типу, восстанавливал путем написания плагина к ImpRec’ку, который просто создавал приблизительно такую конструкцию
nop
call reducer
nop
ret
где reducer – это текущий переходник, потом вызывал её и после её обработки получал, вместо reducer относительный адрес системной функции.
Конечно, пришлось несколько подредактировать процедуру, находящуюся по адресу 7F314C, т.к. она проверяла, принадлежит ли вызывающий код исполняемому файлу.
seg000:007F314C call $+5
seg000:007F3155 pop ebx
seg000:007F315C mov ebp, ebx
seg000:007F3161 sub ebp, 411BD2h
seg000:007F316D mov ebx, [ebx-0E9h]
seg000:007F317E call $+5
seg000:007F3187 add dword ptr [esp], 20h ; ‘ ‘
seg000:007F318B mov ecx, [ebp+411BC9h]
seg000:007F3194 call ecx ; последняя инструкция функции AddAtom
seg000:007F319C retn
…
seg000:007F31A3 mov esi, [ebx+28h]
seg000:007F31A6 movzx edx, dl
seg000:007F31A9 movzx eax, ax
seg000:007F31AC shl edx, 3
seg000:007F31AF mov ecx, edx
seg000:007F31B1 shl edx, 1
seg000:007F31B3 add ecx, edx
seg000:007F31B5 lea edi, [esi+ecx+4]
seg000:007F31B9 cmp dword ptr [edi], 0
seg000:007F31BC jz loc_7F334E
seg000:007F31C2 add esi, [edi+10h]
seg000:007F31C5 lea esi, [esi+eax*8]
seg000:007F31C8 movzx eax, word ptr [esi]
seg000:007F31CB cmp eax, 40h ; API Obsiduim’а ?
seg000:007F31CE jz loc_7F3264
seg000:007F31D4 cmp eax, 4 ; по xor’ная функция?
seg000:007F31D7 jz short loc_7F3238
seg000:007F31D9 cmp eax, 1
seg000:007F31DC jz short loc_7F320D
seg000:007F31DE movzx eax, word ptr [esi+2] ; в таблице храниться CRC
…
А по адресу 457А55 идет вызов функции, которая производит запись реального адреса функции в call вызвавший наш переходник.
00457F55 50 push eax
00457F56 51 push ecx
00457А57 FFD2 call edx ; вызов приведенной ниже функции
…
seg000:007F5214 mov edx, [ebx]
seg000:007F521B cmp eax, edx
seg000:007F5220 jb loc_7F5354 ; забиваем прыжок
seg000:007F522A add edx, [ebx+50h]
seg000:007F5232 cmp eax, edx
seg000:007F5239 jnb loc_7F5354 ; забиваем прыжок
seg000:007F5248 cmp word ptr [eax-6], 15FFh
seg000:007F5251 jnz short loc_7F52BF
.
seg000:007F52C2 cmp byte ptr [eax-5], 0E8h
seg000:007F52CB jnz loc_7F5354
seg000:007F52D7 mov edx, eax
seg000:007F52DC add edx, [eax-4]
seg000:007F52E8 mov ecx, [esi+172h]
seg000:007F52F3 add ecx, [ebx]
seg000:007F52F8 cmp edx, ecx
seg000:007F52FF jb short loc_7F5354 ; забиваем прыжок
seg000:007F5305 add ecx, [esi+176h]
seg000:007F530B cmp edx, ecx
seg000:007F5311 jnb short loc_7F5354 ; забиваем прыжок
seg000:007F531D cmp word ptr [edx], 25FFh
seg000:007F5328 jnz short loc_7F5354 ; забиваем прыжок
seg000:007F5333 mov edx, [ebp+0Ch]
seg000:007F5339 mov byte ptr [eax-5], 0E8h
seg000:007F5343 sub edx, eax
seg000:007F5348 mov [eax-4], edx
seg000:007F5357 pop ebx
seg000:007F5358 pop esi
seg000:007F5359 leave
seg000:007F535A retn 8
Теперь пару слов о функциях, значение которых не меняется на протяжении всего времени выполнения программы
(GetVersion, GetCommandLineA, GetCurrentProcessId). Они имеют переходники вида:
mov eax,some_value
ret
Для их восстановления достаточно просто по очереди вызвать эти функций и проверить на равенство результата значению, помещаемому в
eax. Таким образом, мы восстановили почти всю таблицу импорта, кроме функции VirtualQuery, т.к. она единственная обрабатывается 4 способом.
Получаем восстановленный импорт(API Obsidium’а пока оставим в покое) и переходим к сборке исполняемого файла с нормальным PE-заголовком.
Я взял PE-заголовок у старого exe’шника и стал добавлять секции. Размеры и RVA могут отличаться от тех, которые мы получили выше, потому что я ставил для себя цель получить для начала работающий исполняемый файл, из-за этого я специально увеличил размер дабы исключить появления дыр между секциями, т.к. разные версии Windows на это по разному реагируют.
1. Первая у нас будет кодовая секция.
Имя: .text
RVA = 1000
Size = C1000
2. Вторая это секция с данными:
Имя: .data
RVA = C2000
Size = E00
3. Так как программа написана на Borland C++ Builder, то третья это tls секция:
Имя: .tls
RVA = D000
Size = 5000
Так же не забудьте перенести из старого исполняемого файла TLS структуру настроив её предварительно на новое местоположение.
4. Четвёртая секция будет с полученным ранее импортом.
5. Пятая секция с ресурсами. В связи с тем, что ресурсы зашифрованы, то берем
и дампим запущенный процесс, и применяем к нему утилиту Resource Rebuilder by Dr.Golova, чтобы получить новую секцию с расшифрованными ресурсами, перестроенными под новый базовый адрес.
6. Необязательная шестая секция с релоками. Релоки в первоначальном виде можно найти в участке памяти, который защита выделяет в первый раз (обычно в районе адреса 7E0000) по характерным байтам: 00 00 10 00 00 10 02 00 00
Динамическое шифрование
Итак, полученный исполняемый файл все равно не запускается. Причиной тому является динамическое шифрование. Если посмотреть, где происходит ошибка, то можно заметить:
009C20AE push 00000517
009C20B3 call dword ptr [004010A9] ; расшифровка
.
мусор
.
009C25D0 push 00000517
009C25D5 call dword ptr [004010AD] ; обратно зашифровываем
Хочу заметить, что между этими двумя вызовами как раз 517h байт. Теперь просто делаем дамп этого участка после расшифровки и вставляем в наш дамп. Вызовы функция для шифрования теперь можно забить nop’ами.
Таких участков я нашел 7 штук. Вот они:
1. 9C20B9 — 517
2. 9C38FE — 30B
3. 9C54AB — 17
4. 9C5FB6 — D5
5. 9C668E — 8E
6. 9C6ACB — 10
7. 9E874B — 5E
Эмуляция API
В принципе с API ничего сложного нет, просто нужно найти место, чтобы вставить код, эмулирующий работу этих функций. Названия API в порядке их следования в старой таблице импорта:
- getRegInfo – возвращает в зависимости от 1-го параметра, на кого зарегистрирована программа.
- isRegistered – возвращает true, если программа зарегистрирована.
- CheckRegCode(в документации я её не нашел) – проверяет регистрационный код(вызывается только 1 раз при вводе регистрационного кода).
Послесловие
Защита оказалась достаточно интересная, единственное, что меня удивило, так это то, что мне удалось получить практически полнофункциональную программу (практически, потому что я мог что-то не заметить) без генерирования лицензии, а учитывая, что там используется шифрование с открытым ключом, то это было бы очень серьезным (если не непреодолимым) препятствием к получению полнофункциональной программы.
Источник: xakep.ru