Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер

в 21:10, , рубрики: github, sim-карты, Блог компании ua-hosting.company, информационная безопасность, конференции, Программирование

Меня зовут Эрик Батлер, а это Карл Кошер, и мы хотим поговорить с Вами о чтении, создании, загрузке и использовании кода на SIM-картах. Этот проект стартовал в прошлом году, когда я узнал о мероприятии Tourcamp 2012, лагере хакеров на побережье штата Вашингтон, таком выездном DEFCON'е. Никаких отелей, жизнь в палатках на открытом воздухе, это был уже второй лагерь, первый мне очень понравился, я пригласил друзей и мы решили туда отправиться. Это мероприятие посвящалось запуску сети GSM в нескольких районах США, и моей задачей было добыть для этого несколько SIM-карт.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 1

Я ничего не знал о том, что из себя представляют SIM-карты, поэтому мне пришлось изучить вопрос и выяснить следующее:

  • SIM, или Subscriber Identification Module – это модуль идентификации абонента мобильной связи;
  • на SIM-карте есть ключ идентификации IMSI и симметричный ключ Ki;
  • в неё встроен модуль безопасности, который не позволяет ни извлечь, ни клонировать ключи;
  • они используются операторами связи GSM, а в настоящее время и LTE (сеть Verizon стандарта 4G);
  • могут также запускать приложения.

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

Спустя десятилетие всё поменялось коренным образом. На сегодня сим-карта является крохотным карманным компьютером, который Вы не можете контролировать. Однако многие принципы работы середины 90-х годов сохранились до сих пор, и я попытался понять, как это всё работает. У меня была отличная возможность поиграть с сим-картами в лагере, и я подумал, что было бы хорошо приобрести карты, которые запускают приложения.

Это было нелёгкой задачей, потому что существует множество операторов, которые хотят продать примерно 500 тысяч таких карт, но нам нужно было всего 500 штук. Большая часть операторов принуждает подписывать соглашение о неразглашении конфиденциальной информации NDA, чего нам не хотелось делать, потому что мы собирались рассказать всё, что узнали бы при изучении таких карт.

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

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 2

У них имелся собственный процессор AVR, не такой, как Arduino, с 64 КБ памяти и крохотным 6 КБ объёмом RAM. Они назывались JavaCard и работали с частотой от 20 до 30 МГц, так что эти мини-компьютеры имели свои ограничения.

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

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 3

Так мы раздали больше 400 из наших 500 карт, и каждый получал свой собственный мобильный номер. Наша экспериментальная сеть обладала такими возможностями:

  • все звонки и текстовые сообщения были бесплатными;
  • люди за пределами лагеря могли позвонить Вам на мобильный телефон, используя префикс 1-337-422-4364 перед вашим номером;
  • Вы могли создать свой собственный кодировщик SMS с помощью нашего API, размещенного на сайте gsm.shadytel.com;
  • сим-карта поддерживала программное обеспечение JavaCard v.2.1.1. и апплеты STK и можно было узнать о создании своих собственных апплетов на том же сайте;
  • для вызова службы 911 необходимо было использовать другую сеть, так как наша Shadytel не поддерживала такой звонок.

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

Рассмотрим, что позволяли приложения, или апплеты, которые мы запрограммировали на сим-картах.

Они запускались на процессоре сим-карты, независимо от телефона, так что он даже «не видел», что происходит, и в зависимости от используемой операционной системы напрямую соединялись с BaseBand (в случае с iPhone). Приложения могли быть дистанционно установлены на карту в режиме «тихой установки» с помощью носителя. Что такое «носитель», я объясню чуть позже. На сегодня большинство носителей SIM-карт поддерживают такие приложения.

Наши карты поддерживали работу нескольких приложений, которые выбирались с помощью AID и управлялись стандартным приложением выбора карт Card Manager.

По сути, поддержка GSM «SIM» является просто приложением на физической карте с интегральной микросхемой (UICC).

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 4

Вот что наши апплеты умели делать:

  • выполнять обычные функции сотовых телефонов с использованием программного интерфейса ОС – показывать текст, меню, проигрывать рингтоны, читать входящие сообщения;
  • работать с современными «умными» телефонами (и с «неумными» тоже);
  • загружать URL;
  • отсылать SMS, инициировать звонки и сервисы обмена данными;
  • принимать и осуществлять такие события, как соединение и разъединение звонков, и осуществлять ещё около 200 функций, доступных обычным сим-картам;
  • взаимодействовать с остальными SIM-картами;
  • выполнять на телефоне произвольные АТ-команды для управления GSM модемом.

Я покажу Вам несколько примеров, как выглядит экран смартфонов при использовании наших карт. Здесь изображены функции мобильного банкинга, не особо распространённые в США, но широко используемые во всём мире.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 5

А сейчас Карл расскажет, как работают наши приложения.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 6

Мы использовали следующие технологии:

  • SmartCard – физическое соединение между SIM-картой и телефоном, такое же, как используют любые смарт-карты;
  • Java Card – программирование на языке Java для смарт-карт, которое является простейшим способом написания приложений, оно появилось ещё в начале 90-х годов;
  • SIM Toolkit (STK) API – интерфейс взаимодействия между приложениями и интерфейсом операционной системы смартфона, который позволяет карте «говорить» с телефоном, принимая от него и передавая ему события;
  • GlobalPlatform – стандарт для загрузки и управления приложениями на сим-карте, разработанный создателями системы VISA.

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

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 7

Особенностью смарт-карт является неизвлекаемость ключей и процедура шифровки-дешифровки, благодаря чему Вы можете пользоваться такими персональными данными, как пароли и логины для доступа к банковской системе, цифровые подписи, доступом к спутниковому телевидению. За это отвечает параметр CLS. Далее следуют инструкции по обработке информации INS. Пакеты APDU представляют собой поток байтов, которые описываются параметрами P1 и P2, и дополнительные записи, такие как длина передачи данных LC, сами данные и расширение длины LE.

На следующем слайде Вы видите JavaCard. Это Java и одновременно не совсем Java, потому что здесь нет никакого мусора, нет букв, строк, многомерных массивов. Если Вам повезёт, Вы сможете найти несколько целочисленных типов данных int. Строение этих карт является чрезвычайно простым. Само собой, что здесь нет стандартных API, типа файлов или тем, можно избавиться от верификации, но существуют некоторые исключения. Образцы и классы переменных сохраняются в памяти EEPROM, которая имеет лимитированное количество циклов записи, примерно 500 тысяч. Поэтому, в зависимости от типа карты, Вы можете иметь проблемы с обновлением этих переменных.

Я расскажу, как мы создавали свои приложения для смарт-карт. Существует несколько специализированных коммерческих интегрированных сред разработки IDE, но можно обойтись и без них, так как во-первых, мы хотели сделать наши приложения максимально открытыми для всех, а во-вторых, эти коммерческие инструменты стоят около $3000.

Из Oracle мы загрузили бесплатный редактор Java Card Development Kit. Если Вы используете Eclipse, необходимо удалить с карты стандартную систему библиотек JRE (Java Runtime) и добавить библиотеку Java Card, которая поможет описывать классы и тому подобное. Кроме того, мы сами написали несколько программ для облегчения работы.

Приложение STK функционирует следующим образом:

  • приложение загружается на карту;
  • приложение регистрирует само себя с помощью SIM Toolkit API;
  • телефон информирует STK о его возможностях, а STK информирует телефон о зарегистрированном приложении.

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

Вот как выглядит наш код.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 8

Java позволяет устанавливать класс карты двумя стандартными методами: это создание и регистрация класса с помощью Java Runtime и установка класса с помощью инструментария SIM-карты. Последний метод используется, когда некое событие необходимо перенести на карту из телефона.

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

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 9

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

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 10

Далее мы программно описали процедуру саморегистрации приложения с помощью SIM Toolkit, процесс выбора программы в меню телефона, отражение подсказок на экране и прочий функционал. Мы постарались прописать всё по максимуму как смогли, выглядит оно кошмарно, зато работает. Полное описание программы приведено на нашем сайте, так что Вам не нужно запоминать то, что показано на этих слайдах. Сейчас наш доклад продолжит Эрик.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 11

Проще всего использовать старую версию кодировки Java 1.1 и версию совместимости кодов 1.3. После того, как Вы создали файлы класса, Вы должны перекодировать их для Java Card. Для этого используется конвертер, имеющийся в нашем SDK. Также понадобятся некоторые ID-приложения (большинство буквально на одну минуту), директория экспорта API и так далее. Эти файлы должны быть понятны ОС телефона, поэтому они сделаны в формате .jar.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 12

Мы также разработали специальную программу Makefiles, которая доступна на сайте http://simhacks.github.io/. Конвертер выдаёт CAP-файл, который представляет собой Zip-архив компонентов CAP (код Java Card).

Одним из важных вопросов, на которые нужно было ответить перед началом работы над проектом, был вопрос, как взаимодействовать с сим-картой. Нам нужен был карт-ридер. Они бывают двух типов: для подсоединения к порту PCSC (PC/Smart Card API) и подсоединяемые к серийному порту Serial. Первые обычно универсальны, поэтому нужно иметь переходник для работы с сим-картой стандартного размера, а вторые намного меньше и используются именно для сим-карт.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 13

Функционально между нет никакой разницы, но вариант PCSC удобнее в использовании. Он использует официальное программное обеспечение, разработанное специально для API и облегчающее работу с компьютером. Кроме этого, имеется много открытых приложений для работы с сим-картами, которые проще использовать с вариантом PCSC. Все карт-ридеры одинаковые, поэтому я использовал самый дешёвый SCR3500, купленный на eBay за $8.

Итак, мы написали этот ужасно выглядящий код, затем обработали его компилятором Java и конвертировали в CAP-файл. Далее мы попытались разместить его на сим-карте, для чего воспользовались популярной программой GPShell Tool, но у нас ничего не получилось. Продавец SIM-карт посоветовал нам другую программу с простым и удобным интерфейсом, которую нигде нельзя было найти, а затем пообещал нам продать её за $600, хотя у него этой программы тоже не было.

Поэтому мы использовали программу под названием SIM Alliance Loader, на слайде ниже показано её окно. Мы использовали первую версию этой программы, но сейчас уже доступна вторая версия. SIM Alliance является группой, которая разрабатывает ПО для работы с сим-картами. Программа SIM Alliance Loader представляет собой адаптацию Java приложения для Windows и предназначены для экспертов, которые понимают, что делают.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 14

Но если Вы разбираетесь в вопросе, перенос приложения на сим-карту займёт буквально пару минут. Однако учитывая то, что у нас было около тысячи карт, которые мы хотели подготовить для Tourcamp, такая технология записи заняла бы слишком много времени, поэтому мы решили использовать нечто более продуктивное. Поэтому мы обратились к Global Platform – стандарту для загрузки, установки и управления приложениями на Java Card. В зависимости от приложения, это программное обеспечение позволяет использовать протоколы и команды, а также осуществляет шифрование и аутентификацию. Оно также позволяет выполнять некоторые внешние процедуры без участия сим-карты, например, верифицировать бинарные коды наших апплетов.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 15

В процессе работы выяснилось, что все приложения загружаются и проходят авторизацию в приложении Issuer Security Domain (ISD) — системе аутентификации Global Platform. На практике это означает, что Вы не можете загрузить на карту приложение, если не разработали его собственноручно, но существуют исключения, описанные в работе Карстена Ноула.

На чистых сим-картах Global Platform приложение ISD имеется по умолчанию, доступ же к нему наших карт обеспечить намного труднее, потому что на них по умолчанию установлено приложение GSM и нет даже возможности получить доступ к приложению Global Platform. Кратко опишу процедуру установки нашего приложения на сим-карту.

Процесс состоит из двух этапов: команды ЗАГРУЗКИ (загрузка массива бинарных кодов) и команды УСТАНОВКИ (создание экземпляра приложения на сим-карте). Единичные CAP-компоненты объединяются вместе и посылаются на карту блоками с помощью команды ЗАГРУЗКА. Существует три вида Application ID (AID), участвующих в этом процессе:

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

В результате CAP-файл разархивируется, данные извлекаются и записываются на сим-карту. Единственным способом «общения» приложения Global Platform с нашей SIM-картой является механизм передачи данных «по воздуху», то есть с помощью SMS-сообщений. В действительности мы не отсылали традиционные SMS, а просто генерировали команды на карте с помощью SMS пакетов.

Это был длительный и достаточно трудоёмкий процесс. Для стандарта GSM 03.48 он заключался в использовании оболочки CAT (AoC2), позволяющей производить с картой нужные нам действия. На первой стадии процесса она включает в себя загрузку SMS PP (D1), которая, в свою очередь, состоит из идентификации устройства и пакета данных транспортного протокола SMS TPDU.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 16

SMS TPDU включает в себя заголовок и данные пользователя. Данные пользователя также включают в себя заголовок, пакет команд, подзаголовок (параметры безопасности, выбор приложения). Он, в свою очередь, использует TAR ID размером 3 байта (удивляюсь, как PowerPoint выдержал подобную ерунду). На этом лимит внутренних данных исчерпывается, а в самом конце списка имеется тот самый APDU, который так нужен нашей Global Platform. Таким образом, весь этот громоздкий механизм служит для пересылки крохотного массива данных.

В случае, если Вы не хотите поступать таким образом, имеется ещё один механизм для удалённой пересылки APDU на сим-карту. Он требует использования сотовой связи для отправки SMS с командами установки, для чего нужна аутентификация в сети. Однако Карстен Ноул описывает способ, когда ошибки шифрования позволяют добыть ключи симметричного алгоритма шифрования DES методом brute-force, то есть без аутентификации в сети.

Загрузочный скрипт Shadysim написан на Python и работает в среде OSX, Linux и Windows. На следующем слайде показано, как он выглядит. Загрузка производится с помощью ПК, к которому подключён карт-ридер с сим-картой.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 17

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

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 18

Здесь задаётся главный класс карты, резервируется физическая и оперативная память, определяется размер текстового меню, которое будет показываться на экране смартфона, записывается команда для запуска Toolkit и так далее. Можно ввести ещё какие-либо параметры с использованием hex-кода. Наконец, вводится список приложений с параметром – t, который позволяет обновлять телефонную книгу.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 19

Как нам узнать, что наше приложение работает? Про это Вам расскажет Эрик.

Следующий слайд показывает, как выглядит работающее приложение. Слева показан скрин экрана с работой программы на Python, в середине изображено меню настроек iPhone с пунктом SIM Appliсations и иконка нашей программы на вкладке Приложения для смартфонов под управлением Android.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 20

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

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

Если код не работает, всю процедуру необходимо повторить. Как можно ускорить и облегчить эту процедуру?

Для этого можно использовать эмулятор Android для сим-карт. Существует открытый ресурс SEEK, представляющий собой SDK для Android. Он включает в себя патчи для получения доступа к сим-карте или SD-карте через USB PCSC карт-ридер и предотвращает конфликт несовместимости SIM-карты при подключении к компьютеру и телефону. Вы запускаете эмулятор Android на компьютере и тестируете свою карту без использования смартфона.

Можно ли использовать смартфон в качестве карт-ридера? На этот вопрос ответит Карл.

Дело в том, что большинство радио-интерфейсов не позволяют напрямую общаться с сим-картой. Решить эту проблему можно с помощью протокола удалённого доступа к сим-карте Remote SIM Access Protocol. Этот метод существует в Европе под названием «удалённый доступ к сим-карте через Bluetooth». Это профиль со встроенной функцией аутентификации. Он нуждается в написании приложения, которое может отправлять и принимать APDU. Однако этот способ в некоторых случаях способен превратить Ваш смартфон в «кирпич», поэтому не стоит устанавливать данный профиль на все смартфоны подряд.

Хочу познакомить Вас с будущими направлениями наших разработок. Набор STK является отличным инструментом, однако имеет ограничения в использовании. Отсюда возникает вопрос, возможно ли создание SMS-ботнета? Ведь сим-карты предназначены для связи через сотовую сеть и не нуждаются в операционных системах для обмена информацией, поэтому существует возможность объединить их в общую сеть.

Широкие возможности открывает также интеграция Android-приложений с апплетами SIM-карт, например, хранение защищённых приватных ключей SSH для авторизации на сим-карте и безопасные операции с электронной валютой BitCoin. У нас есть идея использовать приложения Android для технологии OTA – «обновление программ по воздуху», применяя для этого SMS-пакеты.

Ещё одним направлением является совершенствование функций NFS, про это вам расскажет Эрик.

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 21

Например, с помощью однопроводного протокола SWP можно будет устанавливать прямое соединение между сим-картой и NFS-контроллером. Это означает, что Ваша сим-карта сможет работать без помощи операционной системы телефона напрямую, так же, как работают банковские карты VISA или MasterCard.

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

Сим-карта также может служить для восстановления потерянного контроля над магазином мобильных приложений. Использование сим-карт как элемента безопасности возможно благодаря следующим свойствам:

Конференция DEFCON 21. “Секретная жизнь SIM карт”. Эрик Батлер, Карл Кошер - 22

  • на сегодня процессор сим-карты расположен внутри большинства мобильных устройств под управлением Android;
  • сим-карта обычно является частью NFS контроллера;
  • элемент безопасности использует ту же технологию, что и сим-карты;
  • сим-карта может использоваться электронным кошельком Google Wallet.

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

При желании Вы можете скачать наше приложение на сайте http://simhacks.github.io/, для его работы Вам понадобятся определённые устройства стоимостью не больше $20, например, карт-ридер. Там же Вы можете найти слайды этой презентации, скрипты для апплетов, программу Makefiles для Java Card, патчи для эмулятора Android и ещё множество полезных вещей.

Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас оформив заказ или порекомендовав знакомым, 30% скидка для пользователей Хабра на уникальный аналог entry-level серверов, который был придуман нами для Вас: Вся правда о VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps от $20 или как правильно делить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).

Dell R730xd в 2 раза дешевле? Только у нас 2 х Intel Dodeca-Core Xeon E5-2650v4 128GB DDR4 6x480GB SSD 1Gbps 100 ТВ от $249 в Нидерландах и США! Читайте о том Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?

Автор: HostingManager

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js