Как сделать loader для файла

Обновлено: 06.07.2024

Привет, друзья. Бывает такое, что из-за использования тяжелых плагинов и сайт грузиться непозволительно долго. В таких случаях я рекомендую избавляться от них, либо искать менее "тяжелый" аналог. Но иногда - его просто нет. В таком случае можно попробовать использовать прелоадер, чтобы немного развлечь (отвлечь) пользователя. Но не все знают, как подобный функционал реализовать.

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

Как сделать прелоадер для landing page

Прежде чем начать делать preloader, нужно немножко уяснить суть того, как браузер загружает страницу. Не буду расписывать весь цикл, так как у самого довольно абстрактное представление, но важно понять, что в целях экономии времени, браузер грузит (отображает) код поэтапно и не дожидается полной загрузки страницы, а в случае подключения js, так вообще прекращает загрузку, пока не выполнит подключаемый файл. Это значит, что загрузка (отображение) остального контента приостанавливается до полной загрузки js файла. В общем, проблем достаточно, давайте теперь попробуем их решить при помощи прелоадера.

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

  • В самом начале размещаем div c прелоадером
  • Скрываем прелодером содержимое сайта до момента полной загрузки страницы
  • Скрываем прелоадер и показываем страницу

Теперь, сразу после открытия тега body разместим следующий div:

Скорее всего, если у вас проблемы с загрузкой сайта, значит у вас много качественных изображений и различных тяжеловесных скриптов, а значит, вы наверняка используете и jQuery, поэтому для того, чтобы наш preloader исчез после того, как загрузится основное содержимое, воспользуемся следующим скриптом:

Размещайте его где-нибудь после подключения jQuery.

Немного поясню html. LoaderArea - фоновая область, которая перекрывает основной контент. CSS этого дива такой:

Loader - это активная область (сам прелоадер). Так как я решил делать его при помощи только CSS, то у него такие стили:

Исходник прелоадера я взял с Codepeen. Вот ссылки на несколько интересных вариантов:

А вы пользуетесь прелоадереми на своих сайтах. Я вот, впервые его использовал. Какие у вас интересные примеры есть?

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

Если вы так же любопытны, как я, вы наверняка задумывались о том, как работают операционные системы. Здесь я расскажу о некоторых исследованиях и экспериментах, которые я провёл, чтобы лучше понять, как работают вычислительные и операционные системы. После прочтения вы создадите свою загрузочную программу, которая будет работать в любом приложении виртуальных машин, например в Virtual Box.

Эта статья не предназначена для того, чтобы объяснить работу загрузчика во всей его сложности. Этот пример — отправная точка для x86 архитектуры. Для понимания этой статьи требуется базовое знание микропроцессоров и программирования.

Простыми словами загрузчик — это часть программы, загружаемая в рабочую память компьютера после загрузки.

После нажатия кнопки Пуск компьютеру предстоит многое сделать. Запускается и выполняет свою работу прошивка, называемая BIOS (базовая система ввода-вывода). После этого BIOS передаёт управление загрузчику, установленному на любом доступном носителе: USB, жёстком диске, CD и т.д. BIOS последовательно просматривает все носители, проверяя уникальную подпись, которую также называют записью загрузки. Когда она найдена и загружена в память компьютера, начинает работать процессор. Если быть более точным, эта запись располагается по адресу 0x7C00. Сохраните его, он нужен для написания загрузчика.

Главная загрузочная запись MBR — первый сектор, где должен находиться загрузчик

Как упоминалось выше, в процессе инициализации BIOS ищет в первом секторе загрузочного устройства уникальную подпись. Её значение равно 0xAA55 и должно находиться в последних двух байтах первого сектора. И хотя все 512 байт доступны в главной загрузочной записи, мы не можем использовать их все: мы должны вычесть схему и подпись таблицы раздела диска и подпись. Останется только 440 байт. Маловато. Но вы можете решить эту проблему, написав код для загрузки данных из других секторов в памяти.

  • BIOS загружает компьютеры и их периферийные устройства.
  • BIOS ищет загрузочные устройства.
  • Когда BIOS находит подпись 0xAA55 в MBR, он загружает этот сектор в память в позицию 0x7C00 и передаёт управление этой точке входа, то есть начинает выполнение инструкций с точки в памяти 0x7C00.

Код загрузчика на ассемблере:

bits 16 org 0x7c00 boot: mov si, message mov ah,0x0e .loop: lodsb or al,al jz halt int 0x10 jmp .loop halt: cli hlt message: db "Hey! This code is my boot loader operating.",0 times 510 - ($-$$) db 0 dw 0xaa55

Ассемблер необходимо скомпилировать в машинный код. Обратите внимание, что 512 в шестнадцатеричной системе — это 0x200, а последние два байта — 0x55 и 0xAA. Он инвертирован по сравнению с кодом ассемблера выше, что связано с системой порядка хранения, называемой порядком следования байтов. Например, в big-endian системе два байта, требуемых для шестнадцатеричного числа 0x55AA, будут храниться как 0x55AA (если 55 хранится по адресу 0x1FE, AA будет храниться 0x1FF). В little-endian системе это число будет храниться как 0xAA55 (AA по адресу 0x1FE, 55 в 0x1FF).

0000000 be 10 7c b4 0e ac 08 c0 74 04 cd 10 eb f7 fa f4 0000010 48 65 79 21 20 54 68 69 73 20 63 6f 64 65 20 69 0000020 73 20 6d 79 20 62 6f 6f 74 20 6c 6f 61 64 65 72 0000030 20 6f 70 65 72 61 74 69 6e 67 2e 00 00 00 00 00 0000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 00001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa 0000200

Машинный код после компиляции NASM

Я объясню этот код построчно в случае если вам не знаком ассемблер:

1. Если укажем целевой режим процессора, директива BITS укажет, где NASM следует сгенерировать код, предназначенный для работы на процессоре, поддерживающем 16-битный, 32-битный или 64-битный режим. Синтаксис — BITS XX, где XX это 16, 32 или 64.

2. Если укажем адрес начала программы в бинарном файла, директива ORG укажет начальный адрес, по которому NASM будет считать начало программы при её загрузке в память. Когда этот код переводится в машинный, компилятор и компоновщик определяют и организуют все структуры данных, необходимые программе. Для этой цели будет использован начальный адрес.

3. Это просто ярлык. Когда он определён в коде, то ссылается на позицию в памяти, которую вы можете указать. Он используется вместе с командами условного перехода для контроля потока приложения.

После разбора четвёртой строки нам необходимо описать концепцию регистров:

Регистр процессора — блок ячеек памяти, образующий сверхбыструю оперативную память (СОЗУ) внутри процессора. Используется самим процессором и большей частью недоступен программисту: например, при выборке из памяти очередной команды она помещается в регистр команд, к которому программист обратиться не может. Википедия

5. Мы будем использовать видеосервисы BIOS для отображения текста на экране, поэтому сейчас мы настраиваем отображение по своему желанию. Сервис перемещает байт 0x0E в регистр AH.

6. Ещё одна ссылка на метку, позволяющая управлять потоком выполнения. Позднее мы используем её для создания цикла.

7. Эта инструкция загружает байт из операнда-источника в регистр AL. Вспомните четвёртую строку, где регистру SI была задана позиция текстового адреса. Теперь эта инструкция получает символ, хранящийся в ячейке памяти 0x7C10. Важно заметить, что она ведёт себя как массив, и мы указываем на первую позицию, содержащую символ ‘H’, как видно на рисунке ниже. Этот текст будет представлен итеративно по вертикали, и каждый символ будет задаваться каждый раз. Кроме того, второй символ не был представлен снимком, извлечённым из программы IDA. 0x65 в ASCII отображает символ ‘e’:

8. Выполнение логической операции OR между (AL | AL) на первый взгляд кажется бессмысленным, однако это не так. Нам нужно проверить, равен ли результат этой операции нулю, основываясь на логическом булевом значении. После этой операции результат будет, например, [1 | 1 = 1] или [0 | 0 = 0].

9. Переход к метке остановки (строка 12), если результат последней операции OR равен нулю. В первый момент значение AL равно [0x48 = ‘H’] , основываясь на последней инструкции LODSB, помните строку 7? Значит, код не перейдёт к метке остановки в первый раз. Почему так? (0x48 OR 0x48) = 0x48, следовательно он переходит к следующей инструкции на следующей строке. Важно заметить, что инструкция JZ связана не только с инструкцией OR. Существует другой регистр, FLAGS, который наблюдается в процессе операций перехода, то есть результат операции OR хранится в этом регистре FLAG и наблюдается инструкцией JZ.

10. Вызывая прерывание BIOS, инструкция INT 0x10 отображает значение AL на экране. Вспомните строку 5, мы задали значение AH байтом 0x0E. Это комбинация для представления значения AL на экране.

11. Переход к метке loop, которая без всяких условий похожа на инструкцию GOTO в языках высокого уровня.

12. Мы снова на строке 7, LODSB перехватывает контроль. После того, как байт будет перемещён из адреса в памяти в регистр AL, регистр SI инкрементируется. Во второй раз он указывает на адрес 0x7C11 = [0x65 ‘e’], затем на экране отображается символ ‘e’. Этот цикл будет выполняться до тех пор, пока не достигнет адреса 0x7C3B = [0x00 0], и, когда JZ снова выполнится в строке 9, поток будет доведён до метки остановки.

13. Здесь мы заканчиваем наше путешествие. Выполнение останавливают инструкции CLI и HLT.

14. На строке 17 вы видите инструкцию, которая заполняет оставшиеся 510 байтов нулями после чего добавляет подпись загрузочной записи 0xAA55.

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

Для Linux наберите в терминале:

sudo apt-get install nasm qemu

На Mac OS можно использовать homebrew:

brew install nasm qemu

После этого вам нужно создать файл с кодом сборки, представленным в коде загрузчика выше. Давайте назовём этот файл boot.asm и затем запустим команду NASM:

nasm -f bin boot.asm -o boot.bin

Будет создан двоичный файл, который нужно запустить на виртуальной машине. Давайте запустим на QEMU:

В этой статье мы рассмотрим как имея один билд лоадера сделать для него конфигуратор. Тренироваться мы будем на очень известном лоадере robots. Для тех, кто не знает что это такое приведу небольшую цитату от разработчика:

Мы покупаем загрузки, тратим деньги, порою вообще большие суммы, а ведь легко можем получать от этих же загрузок большую отдачу, только если сразу передать на загрузку лоадер Robots. Тут мы получаем и удобную, а главное свою, а не чужую статистику и возможность грузить еще не ограниченное число файлов друзьям, знакомым за один подход, так и сами файлы будут грузиться качественнее. Вы наверняка ощутите отдачу как только начнете, да и добрую часть денег сэкономить можно, зачем лишнее тратить на "недогруженные" загрузки 😉 …

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

Что такое лоадер. Это небольшой файлик, который в обход фаерволов загружает нужный нам файл на машину юзера и незаметно его запускает. Так что грузить файлы с помощью лоадера намного лучше, чем грузить файлы сразу. Так что вещь в хозяйстве незаменимая.

Анализ

Ну что же, приступим. На руках имеем 1 билд лоадера который безвозмездно пожертвовали нам добрые люди. Имя файла «loader.exe», размер

6kb. Натравим на файл любой анализатор (PEiD, DiE, Protection ID) и узнаем, что файл запакован MEW 11 SE 1.2. Это не слишком большая проблема, берём любимый отладчик OllyDbg и вперед. Загружаем в Olly наш файл и оказываемся на точке входа, где видим примерно следующее:

0090B55F >- E9 F04BAFFF JMP loader.00400154

Перейдём по адресу 00400154 и увидим следующий код:

00400154 BE 1CA09000 MOV ESI,loader.0090A01C

00400159 8BDE MOV EBX,ESI

0040015B AD LODS DWORD PTR DS:[ESI]

Теперь листаем код не много вниз, пока не наткнемся на следующие команды:

004001F0 FF53 F4 CALL DWORD PTR DS:[EBX-C]

004001F3 AB STOS DWORD PTR ES:[EDI]

004001F4 85C0 TEST EAX,EAX

004001F6 ^ 75 E5 JNZ SHORT loader.004001DD

004001F8 C3 RETN <- вот сюда нужно поставить breakpoint

Значит ставим breakpoint по адресу 004001F8 и запускаем программу на исполнение. Когда Olly прервётся, в стеке будет примерно следующие:

0012FFC0 00909000 loader.00909000 <- начало криптора

0012FFC4 7C816FF7 RETURN to kernel32.7C816FF7

Вот это нам и надо, теперь будем распаковывать «мега приватный» криптор 🙂 Делаем в Olly F8 (Step over) и перемещаемся на адрес 00909000:

00909000 CE INTO

00909001 9B WAIT

00909002 9F LAHF

00909003 98 CWDE

00909004 98 CWDE

Примитивный однобайтовый мусор у нас перед глазами, применяется он чтобы сбить сигнатурную маску у аверов. В теории это так - есть основной «скелет» команд, которые выполняют основную работу, а между ними внедряется случайное число мусорных команд. Но технология давно устарела и современные аверы справляются с этой задачей. Тем более мусор в данном лоадере выделяется на фоне значащих команд. Ладно, нас это не интересует, надо снять криптор чтобы уже исследовать сам лоадер. В общем, в крипторе особо интересного ничего нету, остановимся лишь на нескольких моментах:

009080E5 0F31 RDTSC // получаем количество тактов

009080E7 2BC3 SUB EAX,EBX // разность между двумя замерами

009080E9 EB 01 JMP SHORT loader.009080EC

009080EB 90 NOP // занопили мусорный байт

009080EC 3D 00000001 CMP EAX,1000000 // если больше 1000000h

009080F1 EB 01 JMP SHORT loader.009080F4

009080F3 90 NOP // занопили мусорный байт

009080F4 - 77 FE JA SHORT loader.009080F4 // то застрянем тут

RDTSC (Read Time Stamp Counter) - ассемблерная инструкция для платформы x86, читающая счётчик TSC (Time Stamp Counter) и возвращающая в регистрах EDX:EAX 64-битное количество тактов с момента последнего сброса процессора. RDTSC поддерживается в процессорах Pentium и старше. Опкод: 0F 31.

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

0090811F /EB 01 JMP SHORT loader.00908122

00908121 |EA E305EB01 EBEB JMP FAR EBEB:01EB05E3

00908128 DF59 85 FISTP WORD PTR DS:[ECX-7B]

0090812B C058 EB 01 RCR BYTE PTR DS:[EAX-15],1

0090812F EA BA000000 00EB JMP FAR EB00:000000BA

Кроме первой команды JMP SHORT loader.00908122 ничего из этого участка кода не понять, но если занопись мусорные байты, то листинг становиться более читабельным:

0090811F /EB 01 JMP SHORT loader.00908122

00908121 |90 NOP

00908122 \E3 05 JECXZ SHORT loader.00908129

00908124 EB 01 JMP SHORT loader.00908127

00908126 90 NOP

00908127 ^ EB DF JMP SHORT loader.00908108

00908129 59 POP ECX

0090812A 85C0 TEST EAX,EAX

0090812C 58 POP EAX

0090812D EB 01 JMP SHORT loader.00908130

0090812F 90 NOP

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

00404996 BB 0000F7BF MOV EBX,BFF70000 // адрес недоступный для записи

0040499B 85C9 TEST ECX,ECX

0040499D 59 POP ECX

0040499E 64:8937 MOV DWORD PTR FS:[EDI],ESI

004049A1 B8 002C2B1F MOV EAX,1F2B2C00 // байты для записи

004049A6 8703 XCHG DWORD PTR DS:[EBX],EAX // ошибка

Лоадер искусственно генерирует исключение и сам же его обрабатывает, такая техника помогает остановить эмулятор отдельный антивирусов, но она, как и все остальное, безвозвратно устарела. Дальше будет ещё исключение, проходим его и наконец перед нами место, которое можно принять за начало лоадера:

00401E78 803D F8464000 00 CMP BYTE PTR DS:[4046F8],0

00401E7F 75 0E JNZ SHORT loader.00401E8F

00401E81 C605 F8464000 01 MOV BYTE PTR DS:[4046F8],1

00401E88 BA 991E4000 MOV EDX,loader.00401E99

00401E8D EB 05 JMP SHORT loader.00401E94

Теперь нужно сдампить файл и привести его в человеческий вид. Полученный дамп будет весить 5
Мб, что ну никак не годиться, берём в руки любой PE-editor и отрезаем всё лишнее. Было:

секция 1: 00001000 00509000 00001000 00509000 C00000E0

секция 2: ТuЫЉ лФ 0050A000 00002000 0050A000 00002000 C00000E0

секция 1: code 00001000 00509000 00001000 00003A00 E00000E0

Ещё, в добавок к этому, надо занулить директорию импорта ImportTable и сделать SizeOfHeaders = 1000h, иначе файл упадёт при запуске. После всех этих манипуляций размер файла стал 18.5
Кб - это уже не 5 Мб, а если запаковать файл PeCompact, то размер будет 6 Кб, что вполне приемлемо для лоадера. Т.к. у нашего лоадера нету импорта, то он не запуститься на win 2000. Для того, чтобы файл нормально запускался и там нужно добавить хотя бы 1 функцию, сделать это можно вручную и ничего сложного в этом
нету.

2500h: 00 00 00 00 00 00 00 00 00 00 00 00 28 25 00 00 . (%..

2510h: 10 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .0.

2520h: 00 00 00 00 00 00 00 00 6B 65 72 6E 65 6C 33 32 . kernel32

2530h: 2E 64 6C 6C 00 00 B7 00 45 78 69 74 50 72 6F 63 .dll. ExitProc

2540h: 65 73 73 00 00 00 00 00 00 00 00 00 00 00 00 00 ess.

И, соответственно, ImportTable address = 2500h и size = 14h.

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

Принцип работы нас не интересует, нам важно сделать конфигуратор.

Основная часть

Немного посмотрев лоадер в Olly я выяснил, что все строки шифруются одной процедурой:

0040141E 55 PUSH EBP // начало

00401486 AC LODS BYTE PTR DS:[ESI] // esi = строка

00401487 84C0 TEST AL,AL // пока символ <> 0

00401489 74 13 JE SHORT dump_.0040149E

0040148B FEC2 INC DL // увеличиваем счётчик

0040148D 8ACA MOV CL,DL

0040148F 80E1 1F AND CL,1F // счётчик AND 1Fh

00401492 80C1 61 ADD CL,61 // счётчик ADD 61h

00401495 FECE DEC DH // уменьшаем счётчик

00401497 32CE XOR CL,DH // ксорим 2 счетчика

00401499 32C1 XOR AL,CL // ксорим символ строки

0040149B AA STOS BYTE PTR ES:[EDI] // записываем в результат

0040149C ^ EB E8 JMP SHORT dump_.00401486

Алгоритм очень простой и обратимый. Т.е. если на вход подать зашифрованную строку, то она расшифруется, а если уже расшифрованную, то соответственно зашифруется. Осталось только найти нужную нам строку. Для обхода фаерволов применяется старый метод с запуском доверенного приложения «svchost.exe» и инъектом в него кода, который скачивает нужный файл. Как я это узнал?
Да для этого надо всего лишь пройтись по лоадеру разбирая каждую инструкцию, ничего сложного в этом нет. В данном случае инъектиться весь образ лоадера. Значит, чтобы вплотную подобраться к нужной нам строке ставим breakpoint на CreateProcessA и запускаем лоадер. Через пару секунд прервёмся на этом месте:

7C802367 >/$ 8BFF MOV EDI,EDI

7C802369 |. 55 PUSH EBP

И в стеке будет следующее:

0012FF30 0040226E /CALL to CreateProcessA

0012FF34 00000000 |ModuleFileName = NULL

0012FF38 004048C2 |CommandLine = "svchost.exe" // доверенное приложение

Перемещаемся дальше, имеем в Olly по адресу ZwCreateThread, и что же мы видим:

7C90D7D2 > 68 19184000 PUSH 401819 // адрес перехватчика

7C90D7D7 C3 RETN

А эта функция, оказывается, перехвачена и всё самое интересное будет происходить по адресу 401819. По-этому идём
туда и ставим breakpoint, жмём F9 (run) в Olly.

Когда прервёмся увидим примерно такой код:

00401819 55 PUSH EBP

0040181A 8BEC MOV EBP,ESP

0040181C 83C4 DC ADD ESP,-24

Листаем вниз, пока не увидим следующие инструкции:

00401959 C786 B8000000 8E1B400>MOV DWORD PTR DS:[ESI+B8], 00401B8E

00401963 FF75 EC PUSH DWORD PTR SS:[EBP-14]

00401966 8F86 AC000000 POP DWORD PTR DS:[ESI+AC]

0040196C 8B35 D4494000 MOV ESI,DWORD PTR DS:[4049D4]

00401972 8B3D CC494000 MOV EDI,DWORD PTR DS:[4049CC] // ZwCreateThread

00401978 A5 MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

00401979 66:A5 MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]

0040197B FF75 F0 PUSH DWORD PTR SS:[EBP-10]

0040197E FF75 20 PUSH DWORD PTR SS:[EBP+20]

00401981 FF75 F4 PUSH DWORD PTR SS:[EBP-C]

00401984 FF75 18 PUSH DWORD PTR SS:[EBP+18]

00401987 FF75 F8 PUSH DWORD PTR SS:[EBP-8]

0040198A FF75 10 PUSH DWORD PTR SS:[EBP+10]

0040198D FF75 0C PUSH DWORD PTR SS:[EBP+C]

00401990 FF75 08 PUSH DWORD PTR SS:[EBP+8]

00401993 FF15 D0494000 CALL DWORD PTR DS:[4049D0] // ZwCreateThread

На этом участке происходит примерно следующее: снимаем перехватчик с функции ZwCreateThread и вызываем оригинальную функцию, перед этим меняем адрес начала нового потока на 00401B8E. Команды по этому адресу будут выполнены в контексте доверенного процесса. Вот то, что нам нужно. Для того, чтобы оказаться по адресу 00401B8E нам потребуется сделать следующее. Ставим breakpoint на адрес 0040197B, прерываемся на нём. Дальше переходим в olly на 00401B8E и нажимаем правую кнопку мыши, в выпавшем меню выбираем «New origin here», т.е. мы передали управление на этот адрес. Помните в начале мелькал адрес 0040141E, это процедура, которая расшифровывает строки, вот теперь ставим breakpoint на её

начало. Прервёмся когда, в стеке будет следующее:

0012F32C 00401619 dump_.00401619

0012F330 00404088 dump_.00404088

0012F334 00404877 dump_.00404877 // вот адрес который нам нужен

Если дойди до конца процедуры

004014A4 61 POPAD

004014A5 C9 LEAVE

004014A6 C2 0400 RETN 4

то по адресу 00404877 будет наша искомая строка:

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

Алгоритм на дельфи с асм вставками будет выглядеть примерно так:

res:array [1..45] of byte;

mov esi,s // помещаем в esi адрес строки

lea edi,res // помещаем в edi адрес выходного буфера

LODS BYTE PTR DS:[ESI] // помещаем в AL символ из нашей строки

JE @@exit // конец строки?

INC DL // эти действия мы разбирали ранее

STOS BYTE PTR ES:[EDI] // помещаем полученный байт в выходной массив

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

Бонус

К статье прилагается распакованный лоадер, готовый конфигуратор, его исходники и скрипты. Всё это доступно для ознакомления, чтобы каждый мог посмотреть, что же за софт продаётся за такие деньги. Распакованный лоадер прекрасно пакуется и криптуется, благодаря этому каждый может попробовать данный софт. Никаких вирусов и т.д. в софте нету.

Использование

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

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

Лоадер – это компонент Android, который через класс LoaderManager связан с жизненным циклом Activity и Fragment. Это позволяет использовать их без опасения, что данные будут утрачены при закрытии приложения или результат вернется не в тот коллбэк. Разберем простейший пример (который хоть и простейший, но требует немало кода, это один из недостатков лоадеров). Создаем класс лоадера (для простоты он не будет грузить данные с сервера, а лишь имитировать загрузку):

В методе loadInBackground() - мы должны загрузить данные Integer - в данном примере это контейнер для данных (int), которые загружает наш лоадер.

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

  • int id - идентификатор лоадера для различения их между собой;
  • Bundle args - класс Bundle, с помощью которого передаем аргументы для создания лоадера;
  • LoaderManager.LoaderCallbacks callback - Callback для создания лоадера и получения от него результата работы:
  • onCreateLoader(int id, Bundle args) - необходимо вернуть нужный лоадер в зависимости от id, используя параметры из Bundle. Вызывается автоматически, при создании лоадера;
  • onLoadFinished(Loader loader, D data) - в параметре D мы получим результат работы лоадера. Вызывается после того, как лоадер загрузит даннные. Для определения этого момента менеджер регистрирует слушатель OnLoadCompleteListener , который прослушивает события;
  • onLoaderReset(Loader loader) - очищаем все данные, чвязанные с данным лоадером.

Создадим экземпляр LoaderCallback для нашего StubLoader’a:

И теперь запускаем лоадер:

Результат: через две секунды после запуска Activity покажется Toast. Теперь, если мы изменим конфигурацию Activity, например, перевернём устройство, то работа лоадера должна начаться заново и Toast должен показаться через 2 секунды. Но он показывается мнгновенно! В чём магия?

Лоадер запускается в методе initLoader класса LoaderManager. Лоадер создается при первом запуске Activity, но при последующих запусках он не пересоздаётся. Вместо этого LoaderManager заменяет экземпляр LoaderCallbacks на новый переданный, и если данные загрузились, они передаются в onLoadFinished.

Таким образом нам не нужно беспокоиться об обновлении данных и создании нового лоадера, но если данные необходимо перезагрузить, можно выполнить restartLoader.

Жизненный цикл лоадера

Порядок работы менеджера загрузчиков (LoaderManager) во время создания активности:

В дополнение к компиляции и упаковке js, webpack также может компилировать и обрабатывать CSS. В этой статье в основном описывается использование style-loader и css-loader для упаковки css.

  • Введение в CSS
  • Используйте style-loader и css-loader для упаковки css
  • Используйте style-loader / url
  • Использовать style-loader / годный к употреблению
  • Использовать конфигурацию параметров style-loader
  • Используйте параметры конфигурации css-loader

Введение в CSS

1. Введение CSS делится на три ситуации:

  • по <style></style> Tag, вы можете написать стиль CSS в теге
  • по <link></link> Импорт тегов в CSS-файлы
  • Используйте атрибут style для определения стиля в элементе html tag

2. Импорт стилей CSS в JS:

  • import “base.css”
  • import Base from “base.css”

Используйте style-loader и css-loader для упаковки css

1、 style-loader

  • функция
    Загрузчик стиля может создать его в html, который должен быть загружен <style></style> Метка, содержание метки - это контент CSS.
  • Установить style-loader
    npm install style-loader --save-dev

2、css-loader

  • функция
    css-загрузчик разрешен в js import Файл CSS представит файл CSS как модуль для файла js.
  • Установить css-загрузчик
    npm install css-loader --save-dev

3. Примеры

  • Введите пустой каталог Test и инициализируйте его для создания файла package.json.
    npm init
  • Создайте каталог и файл src / css / base.css и добавьте следующий код
  • Создайте src / app.js и импортируйте файл base.css как модуль
  • Создайте webpack.config.js и напишите скрипт упаковки

Примечание. Выше написано webpack2, ниже написано webpack1, webpack1 рекомендуется отказаться.


  • Выполнить команду пакета
    webpack
  • Результаты упаковки
    , сгенерированный в каталоге dist app.bundle.js , Откройте этот файл, вы увидите, что CSS был упакован в код JS

4. Проверьте файл пакета


  • Создайте index.html и представьте упакованный app.bundle.js
  • Результаты теста
    Фон страницы становится красным, указывая, что CSS вступает в силу. Откройте браузер и проверьте код страницы, вы увидите, что есть еще <style> Пометьте и запишите содержимое base.css на ярлык.

Используйте style-loader / url

1. Функция

Используйте style-loader для упаковки стилей CSS в js в <style> При использовании style-loader / url теги упакуют введенный в js стиль файла css в файл css и передадут <link> Введение этикетки.

2. Установите файл-загрузчик

Чтобы импортировать файлы, вам нужно использовать файл-загрузчик, npm install file-loader --save-dev

3. Настройте файл webpack.config.js

4. Упакуйте и протестируйте

Выполнить команду пакета webpack , Создает файл CSS в каталоге dist, содержимое файла - это стиль в файле base.css.

Запустите index.html, просмотрите исходный код в браузере, вы увидите, что стиль CSS используется в настоящее время <link> Введен:

5. Примечание

Использование style-loader будет упаковывать CSS в файл CSS и передавать файл CSS <link> Теги вводятся, когда app.js import Когда используются два файла css, два файла css генерируются в каталоге dist при выполнении упаковки, а затем на странице html также появляются два файла css.
Например:


  • Создайте новый файл common.css в каталоге src / css /
  • Представлено в app.js
    import './css/base.css';
    import './css/common.css';
  • Выполнить команду пакета webpack
  • Сгенерируйте два css-файла в каталоге dist и просмотрите в браузере, что вы обнаружите два css-файла.

Использовать style-loader / годный к употреблению

1. Функция

Использование style-loader / useable позволит импортированному модулю css использовать методы use () и unuse (), что нам удобно для работы.

2. Настройте файл webpack.config.js

3. Введите файл base.css в app.js и напишите тестовый код

4. Упакуйте и протестируйте

Выполнить команду пакета webpack Запуск index.html обнаружит, что текущий стиль CSS будет постоянно загружаться и удаляться.

Использовать конфигурацию параметров style-loader

Для работы с загрузчиком стилей вы можете настроить атрибут options. Обычно используемые атрибуты:

  • attrs
  • insertAt
  • insertInto
  • singleton
  • transform

1、attrs

  • функция
    дает <style></style> Тег устанавливает атрибуты, attrs является объектом, а содержимое представлено в виде пар ключ-значение.
  • Настройте webpack.config.js


Результаты теста

2. вставить и вставить в

  • функция
    Вставить стиль CSS в указанную позицию. Значение insertAt является строковым типом, который может быть верхним или нижним, что означает, что верх или конец определенного тега вставлен, а тег является отношением «родитель-потомок»; insertInto означает, что он вставлен в элемент dom.
  • нота,
    Оба селектора тега атрибута реализованы через document.querySelector, поэтому есть две проблемы:
    1) значение свойства должно соответствовать синтаксису document.querySelector;
    2) Браузеры низкого уровня (такие как IE) могут не поддерживать этот API селектора;
  • Примеры
    1) Если для свойства insertAt установлено значение top, стиль CSS будет вставлен в <header></header> Первая строка метки
    настроить webpack.config.js


Результаты теста

2) Если атрибут insertAt имеет значение bottom, стиль CSS будет вставлен в <header></header> Последняя строка метки
настроить webpack.config.js


Результаты теста

3) Используйте insertInto для вставки стиля в элемент с помощью приложения id
настроить webpack.config.js


Результаты теста

4、singleton

  • функция
    использовать только один <style> Теги, которые будут <style> Ярлыки объединены в одну.
  • Типы
    логический тип, true или false
  • Конфигурация webpack.config.js

5、transform

  • функция
    Вы можете получить стиль css для строкового типа в js, а затем преобразовать стиль css и затем вернуть преобразованный стиль css.
  • Конфигурация webpack.config.js
  • css.transform.js
    Создайте css.transform.js в корневом каталоге проекта.

Используйте параметры конфигурации css-loader

Для работы css-загрузчика вы можете настроить атрибут options.

  • importLoader(@import)
  • минимизировать (сжимать ли)
  • модули (включен ли модуль css)

1、importLoader(@import)

  • функция
    включить / отключить обработку @import

2. минимизировать (сжимать ли)

  • функция
    сжимает CSS, например, удаляет пробелы и так далее.
  • Конфигурация webpack.config.js



3. модули (включен ли css-модуль)

  • функция
    Включение атрибута modules импортирует подмодули css.
  • Конфигурация webpack.config.js
  • Позвоните в app.js
  • Добавить код в base.css
  • Добавить код в common.js

Выполнить команду пакета
webpack


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

Изменить имя сгенерированного класса
Используйте localIdentName для настройки и изменения имени сгенерированного класса, [path][name] Текущее имя пути, [local] Текущее имя класса, [hash:base64:5] Относится к 5-битному хэш-значению кодировки base54.


Как показано ниже:

Читайте также: