Русский
Русский
English
Статистика
Реклама

Командная строка

Перевод Что JavaScript-разработчику следует знать о Curl

28.06.2020 14:08:19 | Автор: admin


Доброго времени суток, друзья!

Представляю Вашему вниманию перевод статьи What JavaScript Developers Should Know About Curl автора Valery Karpov.

Curl это популярный инструмент командной строки, часто используемый для отправки HTTP-запросов. Curl поддерживает большое количество протоколов, однако как Node.js-разработчик вы, скорее всего, будете использовать его для отпраки http-запросов к RESTful API.

Документация curl представляет собой перечень из 383 флагов командной строки, поэтому в ней очень трудно найти то, что ищешь. В этой статье я хочу поделиться с вами некоторыми часто используемыми мной шаблонами. Для примеров будет использоваться сервис httpbin.org.

Отправка http-запроса


Для начала убедитесь в том, что у вас установлен curl, выполнив команду curl --version.

$ curl --versioncurl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.1.1 zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1 (+libidn2/2.0.4) nghttp2/1.30.0 librtmp/2.3Release-Date: 2018-01-24Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL 

Для отправки запроса необходимо запустить curl url. Например, для отправки GET-запроса к https://httpbin.org/get?answer=42 следует запустить curl https://httpbin.org/get?answer=42.

$ curl https://httpbin.org/get?answer=42{  "args": {    "answer": "42"  },   "headers": {    "Accept": "*/*",     "Host": "httpbin.org",     "User-Agent": "curl/7.58.0",     "X-Amzn-Trace-Id": "Root=1-5ee8d737-b39c6a466892725bbb52b916"  },   "origin": "69.84.111.39",   "url": "https://httpbin.org/get?answer=42"}

После успешного завершения запроса curl возвращает тело http-ответа. Для того, чтобы заставить curl вернуть весь ответ, включая заголовки, используйте флаг -i.

$ curl -i https://httpbin.org/get?answer=42HTTP/2 200 date: Tue, 16 Jun 2020 14:30:57 GMTcontent-type: application/jsoncontent-length: 801server: istio-envoyaccess-control-allow-origin: *access-control-allow-credentials: truex-envoy-upstream-service-time: 2{  "args": {    "answer": "42"  },   "headers": {    "Accept": "*/*",     "Content-Length": "0",     "Host": "httpbin.org",     "User-Agent": "curl/7.58.0",     "X-Amzn-Trace-Id": "Root=1-5ee8d7a1-cb3954c09299eb9e0dff70a6",     "X-B3-Parentspanid": "dffc55451e64b5fc",     "X-B3-Sampled": "0",     "X-B3-Spanid": "8e233a863fb18b6c",     "X-B3-Traceid": "45bd12a9067fb5c0dffc55451e64b5fc",     "X-Envoy-External-Address": "10.100.91.201",     "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/httpbin-istio/sa/httpbin;Hash=c1ff14671b3e24ee794f9a486570abf8ccc9d622846611d3f91a322db4d480cd;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"  },   "origin": "69.84.111.39,10.100.91.201",   "url": "http://httpbin.org/get?answer=42"}

Это полный http-ответ. Заголовками ответа являются строки от date: до x-envoy-upstream-service-time:.

Загрузка файлов


Wget самый распространенный инструмент для загрузки файлов посредством командной строки. Он входит в комплект большинства диструбутивов Linux. Однако в OSX его нет.

Команда wget url аналогична команде curl -OL url. Опция это опция --remote-name, которая говорит curl сохранить тело ответа в локальном файле. Опция -L говорит curl следовать перенаправлениям.

Например, ниже представлено изображение с Unsplash, его URL https://images.unsplash.com/photo-1506812574058-fc75fa93fead.



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

$ curl -OL https://images.unsplash.com/photo-1506812574058-fc75fa93fead  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed100 12.1M  100 12.1M    0     0  3927k      0  0:00:03  0:00:03 --:--:-- 3927k

Опция -O говорит curl использовать строку после последнего / в качестве имени файла. В приведенном примере изображение будет сохранено в текущей директории с именем photo-1506812574058-fc75fa93fead. Для определения имени файла используйте опцию (строчная буква о).

$ curl -o miami-beach.jpg https://images.unsplash.com/photo-1506812574058-fc75fa93fead  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed100 12.1M  100 12.1M    0     0  6083k      0  0:00:02  0:00:02 --:--:-- 6083k$ ls -l miami-beach-jpg-rw-rw-r-- 1 val val 12788445 Jun 16 11:03 miami-beach.jpg

Отправка авторизованного запроса


Заголовок авторизации используется для включения в запрос данных для авторизации при обращении к RESTful API. Для добавления указанных данных необходимо использовать флаг -H. Например, если ваш ключ интерфейса (API key) my-secret-token, вы можете включить его в http-запрос следующим образом:

$ curl -H "Authorization: my-secret-token" https://httpbin.org/get{  "args": {},   "headers": {    "Accept": "*/*",     "Authorization": "my-secret-token",     "Host": "httpbin.org",     "User-Agent": "curl/7.58.0",     "X-Amzn-Trace-Id": "Root=1-5ee8e1a5-a3aa30e0765a7980b04ca4a0"  },   "origin": "69.84.111.39",   "url": "https://httpbin.org/get"}

Обратите внимание, что httpbin.org возвращает заголовки http-запроса в теле ответа в свойстве headers.

Curl также поддерживает авторизацию по-умолчанию посредством флага -u. В следующем примере мы отправляем запрос с именем пользователя user и паролем pass:

$ curl -i -u "user:pass" https://httpbin.org/basic-auth/user/passHTTP/2 200 date: Tue, 16 Jun 2020 15:18:45 GMTcontent-type: application/jsoncontent-length: 47server: istio-envoyaccess-control-allow-origin: *access-control-allow-credentials: truex-envoy-upstream-service-time: 1{  "authenticated": true,   "user": "user"}

Вот что происходит при отправке неправильного имени пользователя или пароля:

$ curl -i -u "user:wrongpass" https://httpbin.org/basic-auth/user/passHTTP/2 401 date: Tue, 16 Jun 2020 15:18:51 GMTcontent-length: 0server: istio-envoywww-authenticate: Basic realm="Fake Realm"access-control-allow-origin: *access-control-allow-credentials: truex-envoy-upstream-service-time: 12

Отправка POST-запроса, содержащего JSON


Флаг -X говорит curl, какой метод следует использовать: PUT, POST и т.д. По-умолчанию curl использует метод GET, поэтому писать curl -X GET не нужно.

Флаг -X часто используется совместно с флагом -d, позволяющим добавить тело запроса. В следующем примере показано как отправить POST-запрос, содержащий некоторый json:

$ curl -X POST -d '{"answer":42}' https://httpbin.org/post{  "args": {},   "data": "",   "files": {},   "form": {    "{\"answer\":42}": ""  },   "headers": {    "Accept": "*/*",     "Content-Length": "13",     "Content-Type": "application/x-www-form-urlencoded",     "Host": "httpbin.org",     "User-Agent": "curl/7.58.0",     "X-Amzn-Trace-Id": "Root=1-5ee8e3fd-8437029087be44707bd15320",     "X-B3-Parentspanid": "2a739cfc42d28236",     "X-B3-Sampled": "0",     "X-B3-Spanid": "8bdf030613bb9c8d",     "X-B3-Traceid": "75d84f317abad5232a739cfc42d28236",     "X-Envoy-External-Address": "10.100.91.201",     "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/httpbin-istio/sa/httpbin;Hash=ea8c3d70befa0d73aa0f07fdb74ec4700d42a72889a04630741193548f1a7ae1;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"  },   "json": null,   "origin": "69.84.111.39,10.100.91.201",   "url": "http://httpbin.org/post"}

Обратите внимание, что по-умолчанию значением заголовка Content-Type является application/x-www-form-urlencoded. Для json это является неверным, поэтому для определения Content-Type следует использовать флаг -H:

$ curl -X POST -d '{"answer":42}' -H "Content-Type: application/json" https://httpbin.org/post{  "args": {},   "data": "{\"answer\":42}",   "files": {},   "form": {},   "headers": {    "Accept": "*/*",     "Content-Length": "13",     "Content-Type": "application/json",     "Host": "httpbin.org",     "User-Agent": "curl/7.58.0",     "X-Amzn-Trace-Id": "Root=1-5ee8e45e-ad875af4f83efd4379b86c34",     "X-B3-Parentspanid": "5f4f33d1c5ea13aa",     "X-B3-Sampled": "0",     "X-B3-Spanid": "a062c9bf2ebfd4bd",     "X-B3-Traceid": "44aa8d62412ae34d5f4f33d1c5ea13aa",     "X-Envoy-External-Address": "10.100.86.47",     "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/httpbin-istio/sa/httpbin;Hash=2f0b3331fe4d512975b4b82583a55dd5d1196023d0dfce9e0abed246991c5b67;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"  },   "json": {    "answer": 42  },   "origin": "69.84.111.39,10.100.86.47",   "url": "http://httpbin.org/post"}

Отправка PUT-запроса, содержащего JSON-файл


Флаг -d также поддерживает отправку данных из локальных файлов.

Например, представим, что у нас есть файл data.js, содержащий такие данные:

{"answer": 42}

Для отправки PUT-запроса с этим файлом в качестве тела запроса вы можете присвоить флагу -d значение @data.json. Префикс @ говорит curl загрузить тело запроса из файла data.json:

$ curl -X PUT -d '@data.json' -H "Content-Type: application/json" https://httpbin.org/put{  "args": {},   "data": "{\"answer\":42}",   "files": {},   "form": {},   "headers": {    "Accept": "*/*",     "Content-Length": "13",     "Content-Type": "application/json",     "Host": "httpbin.org",     "User-Agent": "curl/7.58.0",     "X-Amzn-Trace-Id": "Root=1-5ee8e745-37c4ef06326b7b4354a16b94",     "X-B3-Parentspanid": "a4f8f91f4f1b051e",     "X-B3-Sampled": "0",     "X-B3-Spanid": "a018b1a3fcebdc68",     "X-B3-Traceid": "7b48b01dc3f632eea4f8f91f4f1b051e",     "X-Envoy-External-Address": "10.100.91.201",     "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/httpbin-istio/sa/httpbin;Hash=6035260d9d551af6c1907270653214e8d3195abbdd19078c1c84fd9a4106f260;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"  },   "json": {    "answer": 42  },   "origin": "69.84.111.39,10.100.91.201",   "url": "http://httpbin.org/put"}

Заключение


Резюмируя, вот опции curl, которые я нахожу самыми полезными:

  • -X определяет метод запроса, например, curl -X POST url
  • -d определяет тело запроса в виде строки в PUT и POST-запросах. Используйте @ для извлечения данных из файла
  • -H определяет заголовок запроса, например, curl -H "Authorization: my-secret-token" url
  • -u аутентификационные данные для стандартной авторизации
  • -O сохраняет тело запроса в файл
  • -i показывает полный ответ, включая заголовки

Curl полезный инструмент взаимодействия с API посредством командной строки, независимо от того, сторонний это API или API, который вы разрабатываете. Для быстрого тестирования curl подходит лучше, чем Axios в Node.js или настройка запроса в Postman, если вы знакомы с их синтаксисом.

Благодарю за потраченное время. Надеюсь, оно было потрачено не зря.
Подробнее..

Сниппет, расширение для VSCode и CLI. Часть 1

04.12.2020 14:04:54 | Автор: admin


Доброго времени суток, друзья!

В процессе разработки Современного стартового HTML-шаблона я задумался о расширении возможностей его использования. На тот момент варианты его применения ограничивались клонированием репозитория и скачиванием архива. Так появились HTML-сниппет и расширение для Microsoft Visual Studio Code HTML Template, а также интерфейс командной строки create-modern-template. Конечно, указанные инструменты далеки от совершенства и я буду их дорабатывать по мере сил и возможностей. Однако, в процессе их создания я узнал несколько интересных вещей, которыми и хочу с вами поделиться.

В этой части мы рассмотрим сниппет и расширение, а CLI в следующей.

Если вас интересует лишь исходный код, вот ссылка на репозиторий.

Сниппет (Snippet)


Что такое сниппет? Если коротко, сниппет это заготовка, которую использует редактор для автозаполнения (автодополнения кода).

В VSCode встроен Emmet (официальный сайт, Emmet in Visual Studio Code), который использует многочисленные HTML, CSS и JS-сниппеты для помощи в написании кода. Набираем в редакторе (в .html) !, нажимаем Tab или Enter, получаем готовую html5-разметку. Набираем nav>ul>li*3>a.link>img, нажимаем Tab, получаем:

<nav>    <ul>      <li><a href="" class="link"><img src="" alt=""></a></li>      <li><a href="" class="link"><img src="" alt=""></a></li>      <li><a href="" class="link"><img src="" alt=""></a></li>    </ul>  </nav>

и т.д.

Кроме встроенных, VSCode предусматривает возможность использования пользовательских сниппетов. Для их создания необходимо перейти в File -> Preferences -> User Snippets (или нажать на кнопку Manage в левом нижнем углу и выбрать User Snippets). Настройки для каждого языка хранятся в соответствующем JSON-файле (для HTML в html.json, для JavaScript в javascript.json и т.д.).

Потренируемся создавать JS-сниппеты. Находим файл javascript.json и открываем его.



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

Начнем с чего-нибудь простого. Создадим сниппет для console.log(). Вот как он выглядит:

"Print to console": {  "prefix": "log",  "body": "console.log($0)",  "description": "Create console.log()"},

  • Print to console ключ объекта, название сниппета (обязательно)
  • prefix сокращение для сниппета (обязательно)
  • body сам сниппет (обязательно)
  • $число положение курсора после создания сниппета; $1 первое положение, $2 второе и т.д., $0 последнее положение (опционально)
  • description описание сниппета (опционально)

Сохраняем файл. Набираем log в скрипте, нажимаем Tab или Enter, получаем console.log() с курсором между скобками.

Создадим сниппет для цикла for-of:

"For-of loop": {  "prefix": "fo",  "body": [    "for (const ${1:item} of ${2:arr}) {",    "\t$0",    "}"  ]},

  • Сниппеты, состоящие из нескольких строк, создаются с помощью массива
  • ${число: значение}; ${1:item} означает первое положение курсора со значением item по умолчанию; данное значение выделяется после создания сниппета, а также после перехода к следующему положению курсора для быстрого редактирования
  • \t один отступ (величина оступа определяется соответствующими настройками редактора или, как в моем случае, расширения Prettier), \t\t два отступа и т.д.

Набираем в скрипте fo, нажимаем Tab или Enter, получаем:

for (const item of arr) {}

с выделенным item. Нажимаем Tab, выделяется arr. Еще раз нажимаем Tab, переходим на вторую строку.

Вот еще несколько примеров:

"For-in loop": {  "prefix": "fi",  "body": [    "for (const ${1:key} in ${2:obj}) {",    "\t$0",    "}"  ]},"Get one element": {  "prefix": "qs",  "body": "const $1 = ${2:document}.querySelector('$0')"},"Get all elements": {  "prefix": "qsa",  "body": "const $1 = [...${2:document}.querySelectorAll('$0')]"},"Add listener": {  "prefix": "al",  "body": [    "${1:document}.addEventListener('${2:click}', (${3:{ target }}) => {",    "\t$0",    "})"  ]},"Async function": {  "prefix": "af",  "body": [    "const $1 = async ($2) => {",    "\ttry {",    "\t\tconst response = await fetch($3)",    "\t\tconst data = await res.json()",    "\t\t$0",    "\t} catch (err) {",    "\t\tconsole.error(err)",    "\t}",    "}"  ]}

HTML-сниппеты строятся по такому же принципу. Вот как выглядит HTML Template:

{  "HTML Template": {    "prefix": "html",    "body": [      "<!DOCTYPE html>",      "<html",      "\tlang='en'",      "\tdir='ltr'",      "\titemscope",      "\titemtype='https://schema.org/WebPage'",      "\tprefix='og: http://ogp.me/ns#'",      ">",      "\t<head>",      "\t\t<meta charset='UTF-8' />",      "\t\t<meta name='viewport' content='width=device-width, initial-scale=1' />",      "",      "\t\t<title>$1</title>",      "",      "\t\t<meta name='referrer' content='origin' />",      "\t\t<link rel='canonical' href='$0' />",      "\t\t<link rel='icon' type='image/png' href='./icons/64x64.png' />",      "\t\t<link rel='manifest' href='./manifest.json' />",      "",      "\t\t<!-- Security -->",      "\t\t<meta http-equiv='X-Content-Type-Options' content='nosniff' />",      "\t\t<meta http-equiv='X-XSS-Protection' content='1; mode=block' />",      "",      "\t\t<meta name='author' content='$3' />",      "\t\t<meta name='description' content='$2' />",      "\t\t<meta name='keywords' content='$4' />",      "",      "\t\t<meta itemprop='name' content='$1' />",      "\t\t<meta itemprop='description' content='$2' />",      "\t\t<meta itemprop='image' content='./icons/128x128.png' />",      "",      "\t\t<!-- Microsoft -->",      "\t\t<meta http-equiv='x-ua-compatible' content='ie=edge' />",      "\t\t<meta name='application-name' content='$1' />",      "\t\t<meta name='msapplication-tooltip' content='$2' />",      "\t\t<meta name='msapplication-starturl' content='/' />",      "\t\t<meta name='msapplication-config' content='browserconfig.xml' />",      "",      "\t\t<!-- Facebook -->",      "\t\t<meta property='og:type' content='website' />",      "\t\t<meta property='og:url' content='$0' />",      "\t\t<meta property='og:title' content='$1' />",      "\t\t<meta property='og:image' content='./icons/256x256.png' />",      "\t\t<meta property='og:site_name' content='$1' />",      "\t\t<meta property='og:description' content='$2' />",      "\t\t<meta property='og:locale' content='en_US' />",      "",      "\t\t<!-- Twitter -->",      "\t\t<meta name='twitter:title' content='$1' />",      "\t\t<meta name='twitter:description' content='$2' />",      "\t\t<meta name='twitter:url' content='$0' />",      "\t\t<meta name='twitter:image' content='./icons/128x128.png' />",      "",      "\t\t<!-- IOS -->",      "\t\t<meta name='apple-mobile-web-app-title' content='$1' />",      "\t\t<meta name='apple-mobile-web-app-capable' content='yes' />",      "\t\t<meta name='apple-mobile-web-app-status-bar-style' content='#222' />",      "\t\t<link rel='apple-touch-icon' href='./icons/256x256.png' />",      "",      "\t\t<!-- Android -->",      "\t\t<meta name='theme-color' content='#eee' />",      "\t\t<meta name='mobile-web-app-capable' content='yes' />",      "",      "\t\t<!-- Google Verification Tag -->",      "",      "\t\t<!-- Global site tag (gtag.js) - Google Analytics -->",      "",      "\t\t<!-- Global site tag (gtag.js) - Google Analytics -->",      "",      "\t\t<!-- Yandex Verification Tag -->",      "",      "\t\t<!-- Yandex.Metrika counter -->",      "",      "\t\t<!-- Mail Verification Tag -->",      "",      "\t\t<!-- JSON-LD -->",      "\t\t<script type='application/ld+json'>",      "\t\t\t{",      "\t\t\t\t'@context': 'http://schema.org/',",      "\t\t\t\t'@type': 'WebPage',",      "\t\t\t\t'name': '$1',",      "\t\t\t\t'image': [",      "\t\t\t\t\t'$0icons/512x512.png'",      "\t\t\t\t],",      "\t\t\t\t'author': {",      "\t\t\t\t\t'@type': 'Person',",      "\t\t\t\t\t'name': '$3'",      "\t\t\t\t},",      "\t\t\t\t'datePublished': '2020-11-20',",      "\t\t\t\t'description': '$2',",      "\t\t\t\t'keywords': '$4'",      "\t\t\t}",      "\t\t</script>",      "",      "\t\t<!-- Google Fonts -->",      "",      "\t\t<style>",      "\t\t\t/* Critical CSS */",      "\t\t</style>",      "",      "\t\t<link rel='preload' href='./css/style.css' as='style'>",      "\t\t<link rel='stylesheet' href='./css/style.css' />",      "",      "<link rel='preload' href='./script.js' as='script'>",      "\t</head>",      "\t<body>",      "\t\t<!-- HTML5 -->",      "\t\t<header>",      "\t\t\t<h1>$1</h1>",      "\t\t\t<nav>",      "\t\t\t\t<a href='#' target='_blank' rel='noopener'>Link 1</a>",      "\t\t\t\t<a href='#' target='_blank' rel='noopener'>Link 2</a>",      "\t\t\t</nav>",      "\t\t</header>",      "",      "\t\t<main></main>",      "",      "\t\t<footer>",      "\t\t\t<p> 2020. All rights reserved</p>",      "\t\t</footer>",      "",      "\t\t<script src='./script.js' type='module'></script>",      "\t</body>",      "</html>"    ],    "description": "Create Modern HTML Template"  }}

Набираем html, нажимаем Tab или Enter, получаем разметку. Положения курсора определены в следующем порядке: название приложения (title), описание (description), автор (author), ключевые слова (keywords), адрес (url).

Расширение (Extension)


На сайте VSCode имеется отличная документация по созданию расширений.

Мы создадим два варианта расширения: в форме сниппетов и в форме CLI. Второй вариант опубликуем в Visual Studio Marketplace.

Примеры расширений в форме сниппетов:


Расширения в форме CLI менее популярны, вероятно, по той причине, что существуют настоящие CLI.

Расширение в форме сниппетов

Для разработки расширений для VSCode, нам, кроме Node.js и Git, потребуется еще парочка библиотек, точнее, одна библиотека и плагин, а именно: yeoman и generator-code. Устанавливаем их глобально:

npm i -g yo generator-code// илиyarn global add yo generator-code

Выполняем команду yo code, выбираем New Code Snippets, отвечаем на вопросы.



Осталось скопировать созданный нами ранее HTML-сниппет в файл snippets/snippets.code-snippets (файлы сниппетов также могут иметь расширение json), отредактировать package.json и README.md, и можно публиковать расширение в маркетплейсе. Как видите, все очень просто. Слишком просто, подумал я, и решил создать расширение в форме CLI.

Расширение в форме CLI

Снова выполняем команду yo code. На этот раз выбираем New Extension (TypeScript) (не бойтесь, TypeScript в нашем коде почти не будет, а там, где будет, я дам необходимые разъяснения), отвечаем на вопросы.



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

cd htmltemplatecode .

Нажимаем F5 или на кнопку Run (Ctrl/Cmd+Shift+D) слева и кнопку Start Debugging сверху. Иногда при запуске можно получить ошибку. В этом случае отменяем запуск (Cancel) и повторяем процедуру.

В открывшемся редакторе нажимаем View -> Command Palette (Ctrl/Cmd+Shift+P), набираем hello и выбираем Hello World.



Получаем информационное сообщение от VSCode и соответствующее сообщение (поздравление) в консоли.



Из всех файлов, имеющихся в проекте, нас интересуют package.json и src/extension.ts. Директорию src/test и файл vsc-extension-quickstart.md можно удалить.

Заглянем в extension.ts (комментарии удалены для удобочитаемости):

// импорт функционала VSCodeimport * as vscode from 'vscode'// функция, вызываемая при активации расширенияexport function activate(context: vscode.ExtensionContext) {  // сообщение, выводимое в консоль редактора,  // в котором запущена отладка расширения  console.log('Congratulations, your extension "htmltemplate" is now active!')  // функционал расширения  // команда - это свойство расширения  // htmltemplate - название расширения  // helloWorld - название команды  let disposable = vscode.commands.registerCommand(    'htmltemplate.helloWorld',    () => {      // информационное сообщение, отображаемое в редакторе      // при успешном выполнении команды      vscode.window.showInformationMessage('Hello World from htmltemplate!')    }  )  // регистрация команды  // судя по всему, здесь реализован паттерн проектирования "Подписка/Уведомление",  // один из вариантов паттерна "Наблюдатель"  context.subscriptions.push(disposable)}// функция, вызываемая при деактивации расширенияexport function deactivate() {}

Важный момент: 'расширение.команда' в extension.ts должно совпадать со значениями полей activationEvents и command в package.json:

"activationEvents": [  "onCommand:htmltemplate.helloWorld"],"contributes": {  "commands": [    {      "command": "htmltemplate.helloWorld",      "title": "Hello World"    }  ]},

  • commands список команд
  • activationEvents функции, вызываемые при выполнении команд

Приступаем к разработке расширения.

Мы хотим, чтобы наше расширение по функционалу напоминало create-react-app или vue-cli, т.е. по команде create создавало проект, содержащий все необходимые файлы, в целевой директории.

Для начала отредактируем package.json:

"displayName": "HTML Template","activationEvents": [  "onCommand:htmltemplate.create"],"contributes": {  "commands": [    {      "command": "htmltemplate.create",      "title": "Create Template"    }  ]},

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

Создаем файлы проекта в виде ES6-модулей (VSCode по умолчанию использует ES6-модули (export/import), но поддерживает и CommonJS-модули (module.exports/require)): index.html.js, css/style.css.js, script.js и т.д. Содержимое файлов экспортируется по умолчанию:

// index.html.jsexport default `<!DOCTYPE html><html  lang="en"  dir="ltr"  itemscope  itemtype="http://personeltest.ru/aways/schema.org/WebPage"  prefix="og: http://ogp.me/ns#">  ...</html>`

Обратите внимание, что при таком подходе все изображения (в нашем случае, иконки) должны быть закодированы в Base64: вот один из подходящих онлайн-инструментов. Наличие строки data:image/png;base64, в начале преобразованного файла принципиального значение не имеет.

Для копирования (записи) файлов мы будем использовать fs-extra. Метод outputFile данной библиотеки делает томе самое, что и встроенный Node.js-метод writeFile, но также создает директорию для записываемого файла при ее отсутствии: например, если мы указали создать css/style.css, а директории css не существует, outputFile создаст ее и запишет туда style.css (writeFile при отсутствии директории выбросит исключение).

Файл extension.ts выглядит следующим образом:

import * as vscode from 'vscode'// импорт библиотеки fs-extraconst fs = require('fs-extra')const path = require('path')// импорт файлов проекта, точнее, содержимого этих файловimport indexHTML from './components/index.html.js'import styleCSS from './components/css/style.css.js'import scriptJS from './components/script.js'import icon64 from './components/icons/icon64.js'// ...export function activate(context: vscode.ExtensionContext) {  console.log('Congratulations, your extension "htmltemplate" is now active!')  let disposable = vscode.commands.registerCommand(    'htmltemplate.create',    () => {      // мы хотим, чтобы файлы проекта хранились в директории html-template      // filename: string указывает TypeScript-компилятору,      // что типом аргумента, передаваемого функции,      // должна быть строка      const folder = (filename: string) =>        path.join(vscode.workspace.rootPath, `html-template/${filename}`)      // массив с контентом файлов      // files: string[] означает, что значением переменной files является массив строк      const files: string[] = [        indexHTML,        styleCSS,        scriptJS,        icon64,        ...      ]      // массив с названиями файлов      // обратите внимание, что индексы контента и названий файлов должны совпадать      const fileNames: string[] = [        'index.html',        'css/style.css',        'script.js',        'server.js',        'icons/64x64.png',        ...      ]      ;(async () => {        try {          // перебираем массив с контентом          for (let i = 0; i < files.length; i++) {            // метод outputFile принимает два обязательных и один опциональный параметр:            // путь к файлу (его название), содержимое файла и кодировку (по умолчанию UTF-8)            // если название файла включает png,            // значит, мы имеем дело с Base64-изображением:            // указываем соответствующую кодировку            if (fileNames[i].includes('png')) {              await fs.outputFile(folder(fileNames[i]), files[i], 'base64')            // иначе, используем кодировку по умолчанию            } else {              await fs.outputFile(folder(fileNames[i]), files[i])            }          }          // информационное сообщение об успехе операции          return vscode.window.showInformationMessage(            'All files created successfully'          )        } catch {          // сообщение об ошибке          return vscode.window.showErrorMessage('Failed to create files')        }      })()    }  )  context.subscriptions.push(disposable)}export function deactivate() {}

Для того, чтобы TypeScript не обращал внимания на отсутствие типов импортируемых файлов-модулей, создадим src/global.d.ts следующего содержания:

declare module '*'

Протестируем расширение. Открываем его в редакторе:

cd htmltemplatecode .

Запускаем отладку (F5). Переходим в целевую директорию (test-dir, например) и выполняем команду create в Command Palette.



Получаем информационное сообщение об успешном создании файлов. Ура!



Публикация расширения в Visual Studio Marketplace

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

  • Создать аккаунт в маркетплейсе (запомните значение поля publisher)
  • Глобально установить библиотеку vsce

Редактируем package.json:

{  "name": "htmltemplate",  "displayName": "HTML Template",  "description": "Modern HTML Starter Template",  "version": "1.0.0",  "publisher": "puslisher-name",  "license": "MIT",  "keywords": [    "html",    "html5",    "css",    "css3",    "javascript",    "js"  ],  "icon": "build/128x128.png",  "author": {    "name": "Author Name @githubusername"  },  "repository": {    "type": "git",    "url": "https://github.com/username/dirname"  },  "engines": {    "vscode": "^1.51.0"  },  "categories": [    "Snippets"  ],  "activationEvents": [    "onCommand:htmltemplate.create"  ],  "main": "./dist/extension.js",  "contributes": {    "commands": [      {        "command": "htmltemplate.create",        "title": "Create Template"      }    ]  },  ...}

Редактируем README.md.

Выполняем команду vsce package в директории расширения для создания публикуемого пакета с расширением vsix. Получаем файл htmltemplate-1.0.0.vsix.

На странице управления расширениями маркетплейса нажимаем кнопку New extension и выбираем Visual Studio Code. Переносим или загружаем в модальное окно VSIX-файл. Ждем завершения проверки.



После того, как рядом с номером версии появилась зеленая галочка, расширение становится доступным для установки в VSCode.



Для обновления расширения необходимо изменить номер версии в package.json, сгенерировать VSIX-файл и загрузить его в маркетплейс, нажав на кнопку More actions и выбрав Update.

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

В следующей части мы создадим полноценный интерфейс командной строки сначала с помощью фреймворка от Heroku oclif, затем без него. Наш Node.js-CLI будет сильно отличаться от расширения, в нем будет присутствовать некоторая визуализация, возможность опциональной инициализации git и установки зависимостей.

Надеюсь, вы нашли для себя что-нибудь интересное. Благодарю за внимание.
Подробнее..

Полезные материалы для разработчика

19.03.2021 12:22:16 | Автор: admin

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

Выпускнику и преподавателю Computer Science Center, Равилю Галееву, пришла идея собрать такие инструменты и технологии в один курс и познакомить студентов с ними. За пример такого курса были взяты The Missing Semester of Your CS Education от MIT, Software Carpentry и cs50.

В этом посте мы собрали видеолекции курса Практический минимум и материалы к занятиям. Благодарим Равиля за подборку!

Содержание

Введение в Linux

Командная строка Linux

Система контроля версий git

Языки разметки и XML

Регулярные выражения

Взаимодействие с сетью

Протокол HTTP

Контейнеризация

Архитектура приложений

Тестирование приложений

Опасность в приложениях

Билд-системы

Кодировки, даты, локали

Дебаг

Набор в Computer Science Center 2021

Введение в Linux

  • Буквально пара слов о том, что такое ядро

  • Набор исторических фактов (от Unix к Linux)

  • Файловая система

  • Пользователи

  • Файлы

  • Процессы

  • Unix way

Слайды

Статьи

Wikipedia History of Unix

Книги

Видео

Курсы

Командная строка Linux

  • bash как REPL

  • Unix way

  • Шебанг

  • make

Слайды

Статьи

Книги

Ian Miell Learn Bash the Hard Way

Видео

Слайды/Презентации

Bash-скрипты из реального мира

Система контроля версий git

  • git

    • commit

    • branch

    • merge

  • git flow

  • github

Слайды

Статьи

Книги

  • Scott Chacon and Ben Straub Pro Git

Видео

Потренироваться

Языки разметки и XML

  • groff

  • LaTex

  • XML, JSON, YAML

  • Markdown, AsciiDoc

  • GraphViz, PlantUML

Слайды

Статьи

Книги

К. В. Воронцов LATEX в примерах

Видео

Слайды и другие материалы

Markdown cheatsheets

Разное

Регулярные выражения

  • Регулярки

  • grep

  • sed

  • awk

Слайды

Статьи

Видео

Слайды и другие материалы

Взаимодействие с сетью

  • Разбираемся как работает посылка пакетов

  • Рассматриваем простейшие утилиты работы с сетью

  • Знакомимся с DNS, CDN, VPN и другими словами на три буквы

  • Пишем сервер на сокетах

Слайды

Материалы

Протокол HTTP

  • HTTP

  • REST

Слайды

Статьи

Видео

Разное

Контейнеризация

  • chroot

  • Docker

  • Docker compose

Слайды

Статьи

Видео

Курсы

Разное

Архитектура приложений

  • ООП

  • Паттерны

  • Многослойная архитектура

Слайды

Статьи

Книги

Курсы

Видео

Тестирование приложений

  • Тестирование

  • Логгирование

Слайды 1

Слайды 2

Статьи

Видео

Опасность в приложениях

  • Хеширование, контрольные суммы

  • Авторизация vs Аутентификация; JWT

  • Обмен ключами Диффи-Хеллман

  • RSA

  • TLS

  • Двухфакторная аутентификация

Слайды

Статьи

Видео

Книги

Билд-системы

  • от make к TravisCI

  • dockerhub

Слайды

Статьи

Видео

Разное

Anatomy of a Continuous Integration and Delivery (CICD) Pipeline

Кодировки, даты, локали

Разбираемся, почему /dev/random печатает краказябры

Слайды

Статьи

Видео

Дебаг

  • Исключения

  • Дебаг

Слайды

Статьи

Книги

Видео

Курсы

Кирилл Кринкин Основы программирования для Linux

Разное


Делитесь в комментариях своими рекомендациями материалов, которые пригодились вам.

Набор в Computer Science Center 2021

Помимо лекций и материалов студентам CS центра на курсе доступны домашние задания. Если вы хотите проходить ещё больше курсов по разным направлениям, приходите поступать.

CS центр это вечерние курсы по математике и программированию. Занятия проходят в Санкт-Петербурге и в Новосибирске. Жители других городов могут поступить на обучение в удалённом формате.

Чтобы поступить:

заполните анкету на сайте до 10 апреля,

решите задания онлайн-теста до 11 апреля,

участвуйте в онлайн-экзамене в конце апреля-начале мая,

пройдите собеседование в мае-июне.

Для тех, кто успешно справится со вступительными испытаниями, занятия начнутся в сентябре. Будьте готовы тратить на учёбу хотя бы 15 часов в неделю в течение двух или трёх лет. Если вы увлечены компьютерными науками или программированием, хотите развиваться в этих областях, любите учиться, то осваивать курсы и работать над проектами будет интересно и полезно.

Задать вопросы про набор можно в телеграм канале или по почте info@compscicenter.ru.

Подробнее..

Из песочницы На сон грядущий или таймер выключения Windows из командной строки

12.11.2020 04:14:57 | Автор: admin
Ценность этой статьи скорее не в самом решении, а в напоминании как можно быстро решать простые задачи.

Но если Вам нужно простое решение пожалуйста:

Сохраните в CMD эти строки и после запуска через 20 минут (1200 секунд) компьютер перейдет в спящий режим. Итого программа заняла 73 байт:
ping 127.0.0.1 -n 1201 > nulrundll32 powrprof.dll,SetSuspendState 0,1,0

Но если Вам нужно именно выключить, то всё будет еще короче, а именно 47 байт. Просто вторая строка будет выглядеть:
shutdown -s -t 00

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

В большинстве своем всё новое это хорошо забытое старое.


Сначала рассмотрим что делают эти строки:

Пингуем IP адрес который всегда доступен (разве что Ваш firewall настроен с выдумкой). Интервал по умолчанию 1000 мс = 1 секунда. Ключ -n задает количество повторений 20 минут х 60 секунд = 1200 + 1 (т.к. первый пинг возвращается менее чем через 1 мс). А конструкция > nul говорит интерпретатору что стандартный вывод будет направляться в nul дабы избавиться от ненужного вывода на экран.
ping 127.0.0.1 -n 1201 > nul

Происходит вызов программы rundll32.exe, которая позволяет выполнить подпрограмму из динамической библиотеки. В данном случае SetSuspendState с нужными нам параметрами. Подробное описание в MSDN.
rundll32 powrprof.dll,SetSuspendState 0,1,0

Следует заметить, что если у вас включен гибридный режим сна (Hibernate), то войдет он именно в этот режим. Отключить его можно запустив от имени администратора следующее:
powercfg -hibernate off

Под спойлером еще несколько применений для примера...
Запуск моего любимого интернет радио через Winamp в отдельном потоке.
start winamp http://cast.loungefm.com.ua:8000/acoustic128

Заблокировать рабочую станцию (WIN + L).
rundll32.exe User32.dll,LockWorkStation

Гибридный режим сна (Hibernate).
rundll32.exe PowrProf.dll,SetSuspendState

Перезагрузка.
shutdown.exe -r -t 00

Старая шутка с включением режима мыши для левши (меняются левая и правая кнопка мыши).
rundll32 user32.dll,SwapMouseButton

Отменить шутку с мышкой можно вызвав диалог настройки мыши и отключив эту функцию.
rundll32 shell32.dll,Control_RunDLL main.cpl,@0,1

Переместить курсор в левый верхний угол.
rundll32 user,SetCursorPos

Расположить все не свернутые окна каскадом.
rundll32 user,CascadeChildWindows

Расположить все не свернутые окна по вертикали.
rundll32 user,TileChildWindows

Еще много интересного можно найти на просторах интернета и придумать, вспоминая документацию по WinAPI функциям.

Есть всем известное выражение которое многим нравится:


Лень двигатель прогресса.

Немного истории:

Еще в далёком 2003 году для выключения ПК по таймеру на скорую руку писалась простенькая программка. Писал сам, ибо знакомых программистов и доступа к интернету в то время у меня не было. Уверен, что много таких же домашних программистов, которые купив или нарезав на болванки MSDN изучали программирование под Windows ночи напролёт. По случаю написания статьи отрыл ее в старом архиве на родительском ПК. Выглядела она незатейливо, но задачу свою выполняла. Как оказалось, даже сейчас ей пользуются несколько моих знакомых.
image
На чём она была написана уже и не помню (VC, VB, Delphi или Assembler). Размер ее был тоже не большим, но все же 16 166 против 47 байт не идут ни в какое сравнение.
И когда пару дней назад мне понадобился такой же функционал я полез искать похожий софт. Каково же было моё разочарование, когда я нашел кучу программ в среднем от 1,1 Мб до огромных монстров 15,2 Мб размером. Естественно совесть мне не позволила даже в песочнице запустить эту ересь. Понимая что мне нужна задержка выполнения в 20 минут и вызов одной лишь процедуры я вспомнил про rundll32.exe, полез в инет и не ошибся. В итоге решение было найдено за 1 минуту.

Мораль:


Зачастую для решения простых задач нам не нужен сторонний софт. Достаточно просто зайти в поисковик и найти простое решение задачи, которое в 98,785% уже есть в свободном доступе. Конечно же нужно упомянуть и другой путь, для настоящих ИТ-шников, включить воображение, зайти в мануалы MSDN и воспользоваться готовым функционалом ОС. Согласитесь, приятно пользоваться простыми и элегантными решениями, но вдвойне приятнее когда до их решения ты дошел своим умом.

Как и обещалось ранее ссылки:
Скрипты таймеров выключения, запуска радио и перехода в спящий режим radio_sleep_scripts.zip
Вдруг будет интересна моя старая поделка ExitXP.exe


Надеюсь мой первый пост Вам понравился. Буду рад замечаниям и предложениям касательно статьи. Хотелось бы увидеть Ваши интересные решения похожих задач в комментариях. Спасибо что уделили время и прочли до конца.
Подробнее..

Перевод Находим и устраняем уязвимости бинарных файлов в Linux с утилитой checksec и компилятором gcc

12.06.2021 16:15:59 | Автор: admin

Изображение: Internet Archive Book Images. Modified by Opensource.com. CC BY-SA 4.0

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

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

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

  • как использовать утилиту checksec для поиска уязвимостей;
  • как использовать компилятор gcc для устранения найденных уязвимостей.

Установка checksec


Для Fedora OS и других систем на базе RPM:

$ sudo dnf install checksec

Для систем на базе Debian используйте apt.

Быстрый старт с checksec


Утилита сhecksec состоит из единственного скриптового файла, который, впрочем, довольно большой. Благодаря такой прозрачности вы можете узнать, какие системные команды для поиска уязвимостей в бинарных файлах выполняются под капотом:

$ file /usr/bin/checksec/usr/bin/checksec: Bourne-Again shell script, ASCII text executable, with very long lines$ wc -l /usr/bin/checksec2111 /usr/bin/checksec

Давайте запустим checksec для утилиты просмотра содержимого каталогов (ls):

$ checksec --file=/usr/bin/ls<strong>RELRO      STACK CANARY   NX      PIE       RPATH   RUNPATH   Symbols    FORTIFY Fortified    Fortifiable  FILE</strong>Full RELRO   Canary found   NX enabled  PIE enabled   No RPATH  No RUNPATH  No Symbols    Yes  5    17       /usr/bin/ls

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

Первая строка это шапка таблицы, в которой перечислены различные свойства безопасности RELRO, STACK CANARY, NX и так далее. Вторая строка показывает значения этих свойств для бинарного файла утилиты ls.

Hello, бинарник!


Я скомпилирую бинарный файл из простейшего кода на языке С:

#include <stdio.h>int main(){printf(Hello World\n);return 0;}

Обратите внимание, что пока я не передал компилятору ни одного флага, за исключением -o (он не относится к делу, а просто говорит, куда выводить результат компиляции):

$ gcc hello.c -o hello$ file hellohello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, for GNU/Linux 3.2.0, not stripped$ ./helloHello World

Теперь запущу утилиту checksec для моего бинарника. Некоторые свойства отличаются от свойств

ls (для него я запускал утилиту выше):$ checksec --file=./hello<strong>RELRO      STACK CANARY   NX      PIE       RPATH   RUNPATH   Symbols     FORTIFY Fortified    Fortifiable   FILE</strong>Partial RELRO  No canary found  NX enabled  No PIE     No RPATH  No RUNPATH  85) Symbols    No  0    0./hello

Checksec позволяет использовать различные форматы вывода, которые вы можете указать с помощью опции --output. Я выберу формат JSON и сделаю вывод более наглядным с помощью утилиты jq:

$ checksec --file=./hello --output=json | jq{./hello: {relro: partial,canary: no,nx: yes,pie: no,rpath: no,runpath: no,symbols: yes,fortify_source: no,fortified: 0,fortify-able: 0}}

Анализ (checksec) и устранение (gcc) уязвимостей


Созданный выше бинарный файл имеет несколько свойств, определяющих, скажем так, степень его уязвимости. Я сравню свойства этого файла со свойствами бинарника ls (тоже указаны выше) и объясню, как это сделать с помощью утилиты checksec.

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

1. Отладочные символы


Начну с простого. Во время компиляции в бинарный файл включаются определённые символы. Эти символы используются при разработке программного обеспечения: они нужны для отладки и исправления ошибок.

Отладочные символы обычно удаляются из той версии бинарника, которую разработчики выпускают для широкого использования. Это никак не влияет на работу программы. Такая очистка (она обозначена словом strip) часто выполняется для экономии места, так как файл становится легче после удаления символов. А в проприетарном программном обеспечении эти символы часто удаляют ещё и потому, что у злоумышленников есть возможность прочитать их в двоичном формате и использовать в своих целях.

Сhecksec показывает, что отладочные символы присутствуют в моём бинарнике, но их нет в файле ls.

$ checksec --file=/bin/ls --output=json | jq | grep symbolssymbols: no,$ checksec --file=./hello --output=json | jq | grep symbolssymbols: yes,


То же самое может показать запуск команды file. Символы не удалены (not stripped).

$ file hellohello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, for GNU/Linux 3.2.0, <strong>not stripped</strong>

Как работает checksec


Запустим эту команду с опцией --debug:

$ checksec --debug --file=./hello

Так как утилита checksec это один длинный скрипт, то для его изучения можно использовать функции Bash. Выведем команды, которые запускает скрипт для моего файла hello:

$ bash -x /usr/bin/checksec --file=./hello

Особое внимание обратите на echo_message вывод сообщения о том, содержит ли бинарник отладочные символы:

+ readelf -W --symbols ./hello+ grep -q '\.symtab'+ echo_message '\033[31m96) Symbols\t\033[m ' Symbols, ' symbols=yes' 'symbols:yes,'

Утилита checksec использует для чтения двоичного файла команду readelf со специальным флагом --symbols. Она выводит все отладочные символы, которые содержатся в бинарнике.

$ readelf -W --symbols ./hello

Из содержимого раздела .symtab можно узнать количество найденных символов:

$ readelf -W --symbols ./hello | grep -i symtab

Как удалить отладочные символы после компиляции


В этом нам поможет утилита strip.

$ gcc hello.c -o hello$$ file hellohello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=322037496cf6a2029dcdcf68649a4ebc63780138, for GNU/Linux 3.2.0, <strong>not stripped</strong>$$ strip hello$$ file hellohello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=322037496cf6a2029dcdcf68649a4ebc63780138, for GNU/Linux 3.2.0, <strong>stripped</strong>

Как удалить отладочные символы во время компиляции


При компиляции используйте флаг -s:

$ gcc -s hello.c -o hello$$ file hellohello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=247de82a8ad84e7d8f20751ce79ea9e0cf4bd263, for GNU/Linux 3.2.0, <strong>stripped</strong>

Убедиться, что символы удалены, можно и с помощью утилиты checksec:

$ checksec --file=./hello --output=json | jq | grep symbolssymbols: no,

2. Canary


Canary (осведомители) это секретные значения, которые хранятся в стеке между буфером и управляющими данными. Они используются для защиты от атаки переполнения буфера: если эти значения оказываются изменены, то стоит бить тревогу. Когда приложение запускается, для него создаётся свой стек. В данном случае это просто структура данных с операциями push и pop. Злоумышленник может подготовить вредоносные данные и записать их в стек. В этом случае буфер может быть переполнен, а стек повреждён. В дальнейшем это приведёт к сбою работы программы. Анализ значений canary позволяет быстро понять, что произошёл взлом и принять меры.

$ checksec --file=/bin/ls --output=json | jq | grep canarycanary: yes,$$ checksec --file=./hello --output=json | jq | grep canarycanary: no,$Чтобы проверить, включен ли механизм canary, скрипт checksec запускает следующую команду:$ readelf -W -s ./hello | grep -E '__stack_chk_fail|__intel_security_cookie'

Включаем canary


Для этого при компиляции используем флаг -stack-protector-all:

$ gcc -fstack-protector-all hello.c -o hello$ checksec --file=./hello --output=json | jq | grep canarycanary: yes,

Вот теперь сhecksec может с чистой совестью сообщить нам, что механизм canary включён:

$ readelf -W -s ./hello | grep -E '__stack_chk_fail|__intel_security_cookie'2: 0000000000000000   0 FUNC  GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (3)83: 0000000000000000   0 FUNC  GLOBAL DEFAULT UND __stack_chk_fail@@GLIBC_2.4$

3. PIE


Включённое свойство PIE позволяет произвольно размещать в памяти исполняемый код независимо от его абсолютного адреса:

PIE (Position Independent Executable) исполняемый позиционно-независимый код. Возможность предсказать, где и какие области памяти находятся в адресном пространстве процесса играет на руку взломщикам. Пользовательские программы загружаются и выполняются с предопределённого адреса виртуальной памяти процесса, если они не скомпилированы с опцией PIE. Использование PIE позволяет операционной системе загружать секции исполняемого кода в произвольные участки памяти, что существенно усложняет взлом.

$ checksec --file=/bin/ls --output=json | jq | grep piepie: yes,$ checksec --file=./hello --output=json | jq | grep piepie: no,

Часто свойство PIE включают только при компиляции библиотек. В выводе ниже hello помечен как LSB executable, а файл стандартной библиотеки libc (.so) как LSB shared object:

$ file hellohello: ELF 64-bit <strong>LSB executable</strong>, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=014b8966ba43e3ae47fab5acae051e208ec9074c, for GNU/Linux 3.2.0, not stripped$ file /lib64/libc-2.32.so/lib64/libc-2.32.so: ELF 64-bit <strong>LSB shared object</strong>, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4a7fb374097fb927fb93d35ef98ba89262d0c4a4, for GNU/Linux 3.2.0, not stripped

Checksec получает эту информацию следующим образом:

$ readelf -W -h ./hello | grep EXECType:               EXEC (Executable file)

Если вы запустите эту же команду для библиотеки, то вместо EXEC увидите DYN:

$ readelf -W -h /lib64/libc-2.32.so | grep DYNType:               DYN (Shared object file)

Включаем PIE


При компиляции программы нужно указать следующие флаги:

$ gcc -pie -fpie hello.c -o hello

Чтобы убедиться, что свойство PIE включено, выполним такую команду:

$ checksec --file=./hello --output=json | jq | grep piepie: yes,$

Теперь у нашего бинарного файла (hello) тип сменится с EXEC на DYN:

$ file hellohello: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=bb039adf2530d97e02f534a94f0f668cd540f940, for GNU/Linux 3.2.0, not stripped$ readelf -W -h ./hello | grep DYNType:               DYN (Shared object file)

4. NX


Средства операционной системы и процессора позволяют гибко настраивать права доступа к страницам виртуальной памяти. Включив свойство NX (No Execute), мы можем запретить воспринимать данные в качестве инструкций процессора. Часто при атаках переполнения буфера злоумышленники помещают код в стек, а затем пытаются его выполнить. Однако, если запретить выполнение кода в этих сегментах памяти, можно предотвратить такие атаки. При обычной компиляции с использованием gcc это свойство включено по умолчанию:

$ checksec --file=/bin/ls --output=json | jq | grep nxnx: yes,$ checksec --file=./hello --output=json | jq | grep nxnx: yes,

Чтобы получить информацию о свойстве NX, checksec вновь использует команду readelf. В данном случае RW означает, что стек доступен для чтения и записи. Но так как в этой комбинации отсутствует символ E, на выполнение кода из этого стека стоит запрет:

$ readelf -W -l ./hello | grep GNU_STACKGNU_STACK   0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10

Отключение NX


Отключать свойство NX не рекомендуется, но сделать это можно так:

$ gcc -z execstack hello.c -o hello$ checksec --file=./hello --output=json | jq | grep nxnx: no,

После компиляции мы увидим, что права доступа к стеку изменились на RWE:

$ readelf -W -l ./hello | grep GNU_STACKGNU_STACK   0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10

5. RELRO


В динамически слинкованных бинарниках для вызова функций из библиотек используется специальная таблица GOT (Global Offset Table). К этой таблице обращаются бинарные файлы формата ELF (Executable Linkable Format). Когда защита RELRO (Relocation Read-Only) включена, таблица GOT становится доступной только для чтения. Это позволяет защититься от некоторых видов атак, изменяющих записи таблицы:

$ checksec --file=/bin/ls --output=json | jq | grep relrorelro: full,$ checksec --file=./hello --output=json | jq | grep relrorelro: partial,

В данном случае включено только одно из свойств RELRO, поэтому checksec выводит значение partial. Для отображения настроек сhecksec использует команду readelf.

$ readelf -W -l ./hello | grep GNU_RELROGNU_RELRO   0x002e10 0x0000000000403e10 0x0000000000403e10 0x0001f0 0x0001f0 R  0x1$ readelf -W -d ./hello | grep BIND_NOW

Включаем полную защиту (FULL RELRO)


Для этого при компиляции нужно использовать соответствующие флаги:

$ gcc -Wl,-z,relro,-z,now hello.c -o hello$ checksec --file=./hello --output=json | jq | grep relrorelro: full,

Всё, теперь наш бинарник получил почётное звание FULL RELRO:

$ readelf -W -l ./hello | grep GNU_RELROGNU_RELRO   0x002dd0 0x0000000000403dd0 0x0000000000403dd0 0x000230 0x000230 R  0x1$ readelf -W -d ./hello | grep BIND_NOW0x0000000000000018 (BIND_NOW) 

Другие возможности checksec


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

Проверка нескольких файлов


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

$ checksec --dir=/usr/bin

Проверка процессов


Утилита checksec также позволяет анализировать безопасность процессов. Следующая команда отображает свойства всех запущенных программ в вашей системе (для этого нужно использовать опцию --proc-all):

$ checksec --proc-all

Вы также можете выбрать для проверки один процесс, указав его имя:

$ checksec --proc=bash

Проверка ядра


Аналогично вы можете анализировать уязвимости в ядре вашей системы.

$ checksec --kernel

Предупреждён значит вооружён


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



Облачные серверы от Маклауд быстрые и безопасные.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Подробнее..

Simctl управление симуляторами Apple через терминал

15.06.2020 00:20:27 | Автор: admin
Всем привет! Меня зовут Паша Лесюк, я работаю мобильным тестировщиком в компании Циан. В этой статье я расскажу о возможностях управления яблочными симуляторами из командной строки.


simctl утилита командной строки для взаимодействия с симуляторами. Она очень похожа на ADB для Android, устанавливается вместе со средой разработки Xcode и используется вместе с xcrun (Xcode-раннер командной строки). Двоичный файл программы можно найти по пути:

/Applications/Xcode.app/Contents/Developer/usr/bin/simctl

Содержание
Работа с объектами устройств
Просмотр списка доступных команд и информации по ним
Просмотр списка доступных устройств, сред выполнения, устройств и пар устройств
Создание нового устройства
Запуск устройства
Апгрейд устройства
Клонирование устройства
Очистка данных и настроек устройства
Переименование устройства
Вывод переменных среды устройства
Проверка состояния загрузки устройства
Выключение устройства
Удаление устройств

Работа с контентом устройств
Снятие скриншота и видео с устройства
Добавление медиа на устройство
Открытие URL на устройстве
Управление сертификатами устройства
Установка приложения на устройство
Запуск приложения на устройстве
Предоставление, отзыв и сброс разрешений приложения
Отображение информации о приложении
Отображение пути к контейнерам установленного приложения
Закрытие приложения на устройстве
Удаление приложения с устройства
Симуляция отправки пуш-уведомления
Изменение и очистка статус-бара устройства
Установка темной или светлой темы

Работа с логами и внутренними механизмами устройств
Выполнение указанной операции на устройстве
Включение и отключение подробного логирования на устройстве
Отображение логов с устройства
Сбор диагностической информации и логов

Заключение
Включение и отключение полноэкранного режима окна симулятора
Включение и отключение отображения нажатий на устройстве

Работа с объектами устройств


Просмотр списка доступных команд и информации по ним


Команда simctl без подкоманд выводит в консоль список всех доступных подкоманд (далее будет использоваться термин команда).

$ xcrun simctl

Для просмотра подробной информации по команде нужно использовать команду help с названием искомой команды.

$ xcrun simctl help list

Просмотр списка доступных устройств, сред выполнения, устройств и пар устройств


Команда list выводит список всех установленных устройств и окружений. Рядом с каждым устройством будет отображен UDID (уникальный идентификатор устройства), который можно прокидывать в некоторые подкоманды simctl.

$ xcrun simctl list

Пример UDID:

4599F586-F482-4E9C-92A7-8AC4EF348BD9

Список можно фильтровать по заголовкам: devices, devicetypes, runtimes, pairs.

$ xcrun simctl list devices== Devices ==-- iOS 11.0 --    iPhone 7 (422566D6-AD4C-40E5-AC64-233043A00814) (Shutdown)-- iOS 13.4 --    iPhone 8 (CB87B315-F01A-41AA-9C85-6FE24E5A66B9) (Shutdown)

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

$ xcrun simctl list devices available

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

$ xcrun simctl list devicetypes 12.9== Device Types ==iPad Pro (12.9-inch) (com.apple.CoreSimulator.SimDeviceType.iPad-Pro)iPad Pro (12.9-inch) (2nd generation) (com.apple.CoreSimulator.SimDeviceType.iPad-Pro--12-9-inch---2nd-generation-)iPad Pro (12.9-inch) (3rd generation) (com.apple.CoreSimulator.SimDeviceType.iPad-Pro--12-9-inch---3rd-generation-)iPad Pro (12.9-inch) (4th generation) (com.apple.CoreSimulator.SimDeviceType.iPad-Pro--12-9-inch---4th-generation-)

Можно вывести более подробную информацию списка c помощью параметра -v.

$ xcrun simctl list -v devices== Devices ==-- iOS 11.0 (15A8401) [/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 11.0.simruntime] --    iPhone 7 (7B68E927-161C-440C-AABE-654CD96E8694) (Shutdown)-- iOS 13.3 (17C45) [/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime] --    iPhone 8 (F3909F6E-E227-4BD7-939F-D3D05B1B8AAD) (Shutdown)

Можно вывести информацию в формате JSON с помощью параметра -j или --json.

$ xcrun simctl list -j -v devices{    "devices" : {    "com.apple.CoreSimulator.SimRuntime.iOS-13-3" : [        {        "dataPath" : "\/Users\/pavel\/Library\/Developer\/CoreSimulator\/Devices\/9EA47EEB-F19F-44EE-9854-EA06BEB8FBD1\/data",        "logPath" : "\/Users\/pavel\/Library\/Logs\/CoreSimulator\/9EA47EEB-F19F-44EE-9854-EA06BEB8FBD1",        "udid" : "9EA47EEB-F19F-44EE-9854-EA06BEB8FBD1",        "isAvailable" : true,        "deviceTypeIdentifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-7-Plus",        "state" : "Shutdown",        "name" : "iPhone-7-Plus"        },        {        "dataPath" : "\/Users\/pavel\/Library\/Developer\/CoreSimulator\/Devices\/F3909F6E-E227-4BD7-939F-D3D05B1B8AAD\/data",        "logPath" : "\/Users\/pavel\/Library\/Logs\/CoreSimulator\/F3909F6E-E227-4BD7-939F-D3D05B1B8AAD",        "udid" : "F3909F6E-E227-4BD7-939F-D3D05B1B8AAD",        "isAvailable" : true,        "deviceTypeIdentifier" : "com.apple.CoreSimulator.SimDeviceType.iPhone-8",        "state" : "Shutdown",        "name" : "iPhone 8"        }    ],    ...

Создание нового устройства


Для создания нового симулятора используется команда create, после которой указываются имя устройства, его тип и среда (эти данные есть в выводе команды list). После выполнения команды отобразится UDID созданного симулятора.

$ xcrun simctl create iPhone-7-Plus com.apple.CoreSimulator.SimDeviceType.iPhone-7-Plus com.apple.CoreSimulator.SimRuntime.iOS-13-49EA47EEB-F19F-44EE-9854-EA06BEB8FBD1

Запуск устройства


Команда boot запускает устройство с указанным UDID, делая его доступным для взаимодействия.

$ xcrun simctl boot CB87B315-F01A-41AA-9C85-6FE24E5A66B9

После запуска устройства можно передавать команду booted вместо UDID. Если запущено несколько устройств, то simctl выберет одно из них.

Чтобы увидеть симулятор в действии нужно запустить приложение Simulator.

$ open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/

Апгрейд устройства


Команда upgrade позволяет повысить версию среды устройства до необходимой.

$ xcrun simctl upgrade 422566D6-AD4C-40E5-AC64-233043A00814 com.apple.CoreSimulator.SimRuntime.iOS-13-4

Клонирование устройства


Команда clone позволяет клонировать существующее устройство, копируя его тип и среду.

$ xcrun simctl clone booted NewPhone

Очистка данных и настроек устройства


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

$ xcrun simctl erase booted

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

$ xcrun simctl erase all

Переименование устройства


Изменить имя устройства можно с помощью команды rename.

$ xcrun simctl rename booted MyiPhone

Вывод переменных среды устройства


Команда getenv позволяет выводить значения переменных среды устройства. Например, встроенная переменная симулятора SIMULATOR_SHARED_RESOURCES_DIRECTORY указывает на путь, где хранятся данные симулятора.

$ xcrun simctl getenv booted SIMULATOR_SHARED_RESOURCES_DIRECTORY/Users/pavel/Library/Developer/CoreSimulator/Devices/F3909F6E-E227-4BD7-939F-D3D05B1B8AAD/data

Проверка состояния загрузки устройства


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

  • -b загружает указанный симулятор, если он не загружен.
  • -d отображает информацию о миграции данных.
  • -c постоянно отслеживает состояние загрузки и выключения.

$ xcrun simctl bootstatus booted$ xcrun simctl bootstatus booted -c

Выключение устройства


Когда работа с симулятором закончена, можно выключить его, используя команду shutdown.

$ xcrun simctl shutdown booted

Для выключения всех симуляторов используется команда shutdown all.

$ xcrun simctl shutdown all

Удаление устройств


В ходе работы с симуляторами может накапливаться большое количество старых устройств, многие из которых могут быть недоступны для последних версий iOS. Для их удаления используется команда delete unavailable.

$ xcrun simctl delete unavailable

Для удаления конкретного симулятора используется команда delete.

$ xcrun simctl delete booted

Для удаления всех устройств используется команда delete all.

$ xcrun simctl delete all

Работа с контентом устройств


Снятие скриншота и видео с устройства


Можно просто использовать шорткат 4, навести курсором на окно симулятора, нажать пробел и сделать скриншот. Но тогда на скриншоте кроме самого экрана будут видны рамки симулятора.
Для снятия скриншота только экрана используется команда io в связке со screenshot. Можно сохранять изображения в формате .png, .tiff, .bmp, .gif и .jpeg.

$ xcrun simctl io booted screenshot ~/Pictures/app-screenshot.png


Аналогично, можно просто использовать шорткат S в открытом приложении Simulator, скриншот окна сохранится на рабочем столе.

Также можно использовать команду io в связке с recordVideo для записи видео взаимодействия с экраном симулятора. Можно сохранять видео в формате .mov, .h264, .mp4 и .fmp4.

$ xcrun simctl io booted recordVideo ~/Movies/app-preview.mp4

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

Добавление медиа на устройство


Команда addmedia используется для добавления фото или видео на симулятор.

$ xcrun simctl addmedia booted ~/Pictures/test.png$ xcrun simctl addmedia booted ~/Pictures/test.gif$ xcrun simctl addmedia booted ~/Pictures/test.mp4

Также можно просто перетащить файл из Finder в окно симулятора.

Открытие URL на устройстве


Команда openurl открывает указанный URL на симуляторе.

$ xcrun simctl openurl booted "https://www.google.com/"

Также может использоваться кастомная схема, ассоциированная с нативным приложением.

$ xcrun simctl openurl booted maps://

Управление сертификатами устройства


Команда keychain позволяет добавлять сертификаты в доверенное корневое хранилище или keychain, а также сбрасывать keychain.

$ xcrun simctl keychain booted add-root-cert ~/my-selfsigned.cer$ xcrun simctl keychain booted add-cert ~/my-selfsigned.cer$ xcrun simctl keychain booted reset

Установка приложения на устройство


Можно легко установить приложение на симулятор если известен путь к файлу .app. Для этого используется команда install.

$ xcrun simctl install booted ~/Циан.app

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

Перечень opensource-приложений для iOS можно найти тут.

Запуск приложения на устройстве


Запуск приложения осуществляется с помощью команды launch и указанием bundle ID.

$ xcrun simctl launch booted ru.cian.mobile

Как узнать bundle ID описано тут.

Предоставление, отзыв и сброс разрешений приложения


Команда privacy может предоставлять, отзывать и сбрасывать разрешения приложения.

$ xcrun simctl privacy <device> <action> <service> <bundle ID>

Значения action (действия) могут быть следующие:

  • grant предоставляет доступ к сервису. Неободим bundle ID.
  • revoke запрещает доступ к сервису. Необходим bundle ID.
  • reset сбрасывает доступ к сервису. bundle ID опционален.

Значения service (службы) могут быть следующие:

  • all применяет действие ко всем службам.
  • calendar предоставляеть доступ к календарю.
  • contacts-limited предоставляет доступ к основной контактной информации.
  • contacts предоставляет полный доступ к контактной информации.
  • location предоставляет доступ к службам определения местоположения при использовании приложения.
  • location-always предоставляет доступ к службам определения местоположения в любое время.
  • photos-add предоставляет доступ на добавление фотографий в библиотеку фотографий.
  • photos предоставляет полный доступ к библиотеке фотографий.
  • media-library предоставляет доступ к медиа-библиотеке.
  • microphone предоставляет доступ к микрофону.
  • motion предоставляет доступ к фитнес-данным.
  • reminders предоставляет доступ к напоминаниям.
  • siri предоставляет возможность использовать приложение вместе с Siri.

Пример использования:

$ xcrun simctl privacy booted grant photos ru.cian.mobile$ xcrun simctl privacy booted grant location ru.cian.mobile$ xcrun simctl privacy booted revoke all ru.cian.mobile

На данный момент не все сервисы доступны для настройки. Отсутствуют уведомления, здоровье, Bluetooth и Face ID.

Отображение информации о приложении


Команда appinfo выводит информацию о приложении.

$ xcrun simctl appinfo booted ru.cian.mobile

Формат отображения информации следующий:

{    ApplicationType = User;    Bundle = <PATH_TO_APP_FILE>;    BundleContainer = <PATH_TO_APP_FILE_FOLDER>;    CFBundleDisplayName = "Циан";    CFBundleExecutable = "Циан";    CFBundleIdentifier = "ru.cian.mobile";    CFBundleName = "Циан";    CFBundleVersion = 1;    DataContainer = <PATH_TO_DATA_FOLDER>;    GroupContainers =     {        <GROUP_CONTAINER_NAME> = <PATH_TO_GROUP_CONTAINER_FOLDER>;    };    Path = <PATH_TO_APP_FILE>;    SBAppTags =     (    );}

Отображение пути к контейнерам установленного приложения


Можно вывести путь к контейнерам приложения через команду get_app_container с указанием bundle ID. У команды есть несколько опций для указания типа контейнера:

  • app указывает на расположение самого приложения и используется по умолчанию.

$ xcrun simctl get_app_container booted ru.cian.mobile$ xcrun simctl get_app_container booted ru.cian.mobile app

  • data указывает на расположение данных приложения.

$ xcrun simctl get_app_container booted ru.cian.mobile data

  • groups указывает на расположение группы приложений. Если групп несколько, то нужно использовать имя искомой группы.

$ xcrun simctl get_app_container booted ru.cian.mobile groups$ xcrun simctl get_app_container booted ru.cian.mobile group.ru.cian.mobile.widget

Закрытие приложения на устройстве


Закрытие приложения осуществляется с помощью команды terminate и указанием bundle ID.

$ xcrun simctl launch terminate ru.cian.mobile

Удаление приложения с устройства


Можно удалить приложение с симулятора с помощью команды uninstall, используя bundle ID.

$ xcrun simctl uninstall booted ru.cian.mobile

Симуляция отправки пуш-уведомления


Для отправки пуша нужно подготовить файл, который должен содержать структуру в формате JSON и сохранить его с расширением .apns (Apple Push Notification service):

{    "aps": {        "alert": {            "title": "Tester on Steroids",            "body": "About mobile apps testing"        },        "badge": 3,        "sound": "default"    }}

Затем нужно дать разрешение на отправку приложению уведомлений. После этого нужно выполнить команду push с указанием устройства, bundle ID и пути до файла .apns.

$ xcrun simctl push booted ru.cian.mobile ~/Documents/mocks/push.apns

Если добавить в файл параметр "Simulator Target Bundle", то необходимость указывать каждый раз bundle ID отпадает.

{    "aps": {        "alert": {            "title": "Tester on Steroids",            "body": "About mobile apps testing"        },        "badge": 3,        "sound": "default"    },    "Simulator Target Bundle": "ru.cian.mobile"}

$ xcrun simctl push booted ~/Documents/mocks/push.apns

Также, если указан параметр "Simulator Target Bundle", то файл можно просто перетащить в окно симулятора.

Изменение и очистка статус-бара устройства


У команды status_bar есть три подкоманды:

  • override принимает параметры для элементов статус-бара и меняет их в зависимости от значений.

$ xcrun simctl status_bar booted override --time 10:30 --dataNetwork wifi --wifiMode active --wifiBars 2 --cellularMode active --cellularBars 3 --operatorName @tester_on_steroids --batteryState charging --batteryLevel 75

  • list выводит значения перезаписанных параметров.

$ simctl status_bar booted listCurrent Status Bar Overrides:=============================Time: 10:30DataNetworkType: 1Cell Mode: 3, Cell Bars: 3Operator Name: @tester_on_steroidsBattery State: 1, Battery Level: 75, Not Charging: 1

  • clear очищает перезаписанный статуc-бар.

$ simctl status_bar booted clear

Установка темной или светлой темы


Данная опция доступна для симуляторов с iOS от 13.0 и выше. C помощью команды ui appearance можно поменять тему устройства на темную или светлую.

$ xcrun simctl ui booted appearance dark$ xcrun simctl ui booted appearance light

Работа с логами и внутренними механизмами устройств


Выполнение указанной операции на устройстве


Команда spawn создает указанный процесс на симуляторе.

$ xcrun simctl spawn booted defaults write ru.cian.mobile ResetDatabase -bool YES

Здесь используется интерфейс defaults, в котором флагу ResetDatabase устанавливается значение YES. Это удобный способ менять пользовательские настройки до запуска приложения.

Включение и отключение подробного логирования на устройстве


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

$ simctl logverbose booted enable$ simctl logverbose booted disable

Отображение логов с устройства


В iOS существует пять уровней логов:

  1. Default. Используется для сбора информации о вещах, которые могут привести к сбою.
  2. Info. Полезная, но необязательная информация для устранения ошибок.
  3. Debug. Информация, которая может быть полезна во время разработки или устранения конкретной проблемы. Отслеживание debug-логов предназначено для использования на стадии разработки, а не на стадии эксплуатации программы конечными пользователями.
  4. Error. Используется для сбора информации об ошибках процесса.
  5. Fault. Используется для сбора информации об ошибках системного уровня или мульти-процессов.

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

$ xcrun simctl spawn booted log stream

По умолчанию вывод логов будет включать в себя уровни default, error и fault. Для использования уровней info и debug нужно использовать аргумент --level. --level=info будет отображать уровни по умолчанию, а так же info. --level=debug будет отображать уровни по умолчанию, а так же info и debug.

$ xcrun simctl spawn booted log stream --level=info$ xcrun simctl spawn booted log stream --level=debug

Также можно фильтровать логи. Например, по конкретному приложению или по типу ивентов и сообщений.

$ xcrun simctl spawn booted log stream --predicate 'processImagePath endswith "Циан"'$ xcrun simctl spawn booted log stream --predicate 'eventMessage contains "error" and messageType == info'

Чтобы выключить вывод логов нужно нажать C в окне терминала.

C помощью операции log collect можно сделать дамп журнала логов.

$ xcrun simctl spawn booted log collect

Сбор диагностической информации и логов


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

$ xcrun simctl diagnose

Журнал будет включать в себя:

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

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

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

Заключение


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

Включение и отключение полноэкранного режима окна симулятора


Позволяет использовать окно симулятора в полноэкранном режиме macOS. Например, можно открыть отдельный рабочий стол с Xcode и симулятором.

defaults write com.apple.iphonesimulator AllowFullscreenMode 1defaults write com.apple.iphonesimulator AllowFullscreenMode 0

Включение и отключение отображения нажатий на устройстве


Отображает тапы на симуляторе. Удобно при записи видео.

defaults write com.apple.iphonesimulator ShowSingleTouches 1defaults write com.apple.iphonesimulator ShowSingleTouches 0



P.S.
Если вам интересна тема тестирования, то приглашаю вас подписаться на мой блог в телеграме.
Подробнее..

Всего лишь меняем модель эмулятора Android устройства

22.01.2021 16:14:24 | Автор: admin

Пролог

Казалось бы, на первый взгляд весьма простая задача. Некоторые читатели могли еще в те бородатые времена лазить по всяким 4пда, рутить свой сенсорный самсунг, менять содержимое файла build.prop и показывать наивным ламерам свой iPhone 15+ Max Pro. Однако, как оказалось, и как оно часто бывает, не все так просто и здесь есть свои подводные камни. Статья призвана помочь простым работягам избежать все кочки да ямы на пути к своей цели!

Дисклеймер

Сразу предупрежу, что люблю писать подобные статьи довольно подробно, не ради объема и многобукав, а ради максимального погружения в проблему и способ ее решения. Обратите внимание, что я работаю на macOS, поэтому все команды в терминале будут ориентированы под данную ОС. Также, следует отметить, что проворачиваювсе это для API 30, то есть для самого последнего на момент написания статьи. Как говорят интернеты, сложности по этой теме начались с API 29.

Зачем это нужно?

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

Ради контекста вкратце расскажу зачем это понадобилось мне. Я получил .apk с багом где-то внутри приложения. Однако пройти дальше первого экрана в этом приложении я не смог. Дело в том, что при запуске, с сервера приходит список разрешенных для запуска устройств и ни мой народный Ксяоми, ни мой эмулятор в этот список не входит. Вот и додумался поменять имя модели устройства на одно из разрешенных. Рутить свой личный телефон не хотелось, поэтому решил шаманить с эмулятором.

Экран не пустивший меня дальшеЭкран не пустивший меня дальше

Достаем build.prop

Как уже говорилось в начале статьи, за имя производителя и модель устройства отвечает системный файл build.prop, который находится в корне устройства в папке system/. Однако при попытке просмотреть его, не говоря уже о редактирование, мы получим отказ в доступе:

Для решения этой проблемы необходимо в терминале обратиться к adb и запросить root права следующей командой: adb root. И вот и первый подводный камень, а именно вывод следующего сообщения: adbd cannot run as root in production builds. Это из-за того что при создании эмулятора мы выбрали вариант с установленными Google сервисами:

Простое решение - создать эмулятор без установленных Google сервисов, после чего повторить команду adb root. После чего в консоле должно появится сообщение: restarting adbd as root что говорит об успешном проведении операции. Естественно если с самого начала у вас был эмулятор без Google сервисов, то скорее всего с adb root и выше описанной проблемой вы не столкнулись.

Отлично, теперь мы видим содержимое файла build.prop:

Редактируем build.prop

Сохраним файл build.prop в любое удобное место для дальнейшего редактирования выделенной красным области на скриншоте выше. Я сохранил прямо на рабочий стол:

Вносим необходимые изменения. Просмотрев логи запросов и ответов предоставленного мне .apk я нашел приходящий с сервера список разрешенных устройств. То есть, для моих целей нужно поменять два значения на PIXEL 3A XL (как вы поняли, здесь вы можете указывать необходимую именно вам модель):

Сохраняем изменения и заливаем файл обратно на эмулятор. Делается это при помощи команды adb push (кстати, скачать файл с эмулятора можно при помощи adb pull если у вас вдруг аллергия на GUI).

Вводим команду в терминал: adb push build.prop system/

И получаем ошибку:

adb: error: failed to copy 'build.prop' to 'system/build.prop': remote couldn't create file: Read-only file system

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

Запускаем эмулятор с доступом на перезапись системных файлов

Для этого нужно выполнить следующую команду в терминале (чтобы скорее всего получить еще одну ошибку):

emulator -avd Pixel3XLAPI30 -writable-system -no-snapshot -nocache

итак здесь Pixel3XLAPI30 - это название нашего эмулятора который мы будем запускать в режиме записи, получить это имя можно выполнив команду emulator -list-avds

-writable-system - собственно тот самый флаг и виновник торжества.

-no-snapshot -nocache - просто советую ввести чтобы избавиться от любого возможного мусора, который может помешать нашему плану-капкану.

После у нас либо запуститься эмулятор (несколько секунд запускается, так что если тупит то так и должно быть) либо получаем ошибку следующего типа:

PANIC: Missing emulator engine program for 'x86' CPU.

БЕЗ ПАНИКИ! Не удивительно, что интернет уже решал подобную проблему.

Что бы и нам порешать с этим нужно в файле .bash-profile (или если у вас zsh то в файле .zshenv) находящийся в корне вашего профиля macOS, добавить дополнительные пути. Вот как это выглядит у меня:

export ANDROIDHOME=~/Library/Android/sdk

есть такая переменная ANDROIDHOME и с ее участием редактируем переменную PATH:

export PATH=$ANDROIDHOME/emulator:$ANDROIDHOME/tools:$PATH

Чтобы изменения вступили в силу перезапускаем терминал (или вводим source ~/.bash_profile) (или source ~/.zshenv). Результат можно проверить выполнив команду echo $PATH и убедиться что в переменной PATH появился добавленный нами путь.

Пробуем запустить эмулятор еще раз.

emulator -avd Pixel3XLAPI30 -writable-system -no-snapshot -nocache

Теперь он должен был успешно запустится.

Активируем доступ на перезапись системных файлов

Из описания флага -writable-system:

-writable-system make system & vendor image writable after 'adb remount'

делаем вывод что теперь нам нужно выполнить adb remount. Для этого открываем новое окно терминала и выполняем сначала команду adb root, что бы adb remount сработало.

После adb remount, будет сообщение что эмулятор нужно перезапустить. Сделать это можно командой adb reboot. Но и здесь не все так просто. Очередной подводный камень об который мы разбили еще один ноготь на пальцах ног. Если сделатьadb reboot то все просто напросто зависает НАВСЕГДА. Настолько навсегда, что придется удалять эмулятор и создавать его заново. Интернет и с этим столкнулся и даже баг создали на гуглов. И благо нашлось решение. Чтобы эмулятор не зависал нужно добавить пару команд до adb remount.

Итак по порядку:

  1. Делаем adb root

  2. Теперь делаем adb shell avbctl disable-verification

  3. Если вы вдруг остались в shell то введите exit

  4. Перезагружаем эмуляторadb reboot и ждем

  5. Снова делаем adb root

  6. И вот теперь можно делать adb remount

Ура! Теперь мы можем записывать файлы в системную папку нашего эмулятора. Можем пушнуть наш отредактированный build.prop файл: adb push build.prop system/. Сделаем adb reboot и убеждаемся что ничего не поменялось Имя модели не изменилось...

Редактируем правильный build.prop

Вернемся к началу и заметим, что значения ro.product.product.name и ro.product.product.model не соответствует тому, что отображается в настройках устройства. Изучив структуру системных папок я заметил, что существует несколько файлов build.prop, которые располагаются в папках: system, system_ext, vendor и product. Эмпирическим методом я скачивал, редактировал и пушил обратно каждый из этих файлов. В конце концов ключевым оказался файл в папке product. Отредактировав его я наконец-то смог изменить название модели эмулятора устройства!

Подводим итоги

Наконец-то я смогу запустить приложение и воспроизвести баг. Подумал я

Теперь я уперся в то, что запускаю приложение якобы с рутованого девайса (ну да есть такой грешок). И дело даже не в команде adb root, ведь команда adb unroot не помогла. Что ж, опускать руки уже поздно, придется что-то придумать.

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

Данной статьей я стремился собрать как можно больше проблем по этому вопросу и изложить все в форме step-by-step. Спасибо за ваше внимание и очень надеюсь, что статья оказалась полезной!

Подробнее..

Как обойти проверку на Рутинг устройства обхитрив библиотеку RootBeer?

25.01.2021 14:08:49 | Автор: admin

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

Дисклеймер

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

Как до этого дошло?

Мне выслали .apk файл приложения. Где-то внутри приложения есть баг, который мне нужно воспроизвести. Но пройти вглубь приложения у меня не получается. Мое устройство не проходит проверку на рутованность.

Экран, который меня не пропускаетЭкран, который меня не пропускает

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

Что будем делать?

Первое, что пришло мне в голову, так это попробовать выполнить декомпиляцию и поправить кое-где код, а потом собрать все обратно. Основное сомнение по поводу такого подхода вызывало то что, у меня не нативное android-приложение, а flutter-приложение. То есть как такового основного кода приложения в виде байт-кода в .apk найти не получится. Или получится? И нужен ли мне код самого приложения?

Небольшое отступление о том, как во флаттере запускается нативный код, то есть родной код для Android или iOS платформы. Например, перед flutter-разработчиком стоит задача: не давать возможность работать с приложением на рутованном устройстве. Аналогом андроид root-устройства является jailbreak для iOS. Для проверки на рутованность или jailbreak необходимо воспользоваться нативными средствами обеих платформ. Для этого разработчик пишет плагин, который вызывает соответствующие нативные методы в зависимости от платформы на которой запущено приложение.

Таким образом, я сделал вывод, что в имеющемся .apk файле есть как минимум 2 интересующих меня места в виде байт-кода. Первое место - это нативная часть приложения, которая слушает команды из flutter части приложения, чтобы вызвать соответствующие нативные методы. И второе место - это собственно и есть эти самые нативные методы, а в данном случае - библиотека для проверки на рутованность устройства.

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

Смотрим байт-код .apk

Итак, посмотрим на внутренности .apk. Для этого можно воспользоваться инструментом, предоставляемый Android Studio. В меню выбираем Build -> Analyze APK В окне выбора файла находим интересующий нас .apk.

Весь скомпилированный байт-код хранится в файле classes.dex. Выберем его и взглянем на его содержимое. В первую очередь нас интересуют не файлы java или androidx, а именно файлы приложения. Поэтому выбираем первый package в структуре файлов android проекта, в моем случае это папка com. Из любопытства к содержимому каждой из папок я затригерился на слово rootbeer. Погуглив в гугле оказалось, что это весьма популярная библиотека для проверки устройства на предмет рутованности.

Исследовав документацию и исходники библиотеки стало ясно о том, как пользоваться библиотекой и где располагается ключевой метод isRooted().

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

Судя по исходникам библиотеки, нужный мне файл должен находится рядом с классом RootBeerNative, и как мы видим тут таких, два a и b. Эмпирическим методом я понял, что это файл b. Правый клик по файлу b и в выпадающем меню выбираем Show Bytecode.

К сожалению, имена всех методов обфусцированы. Снова обращаясь к исходному файлу на github становится ясно, что метод isRooted() находится на строке 42. Побегав по файлу с байт-кодом мне удалось найти этот метод. Только теперь он называется a() и почему-то начинает работу с .line 43. Вот этот метод я и буду редактировать. Но не так быстро, К сожалению здесь только Read-only доступ.

Редактируем содержимое classes.dex

Для этого придется декомпилировать весь .apk при помощи популярного инструмента apktool. Работать с ним довольно просто. После его установки нам понадобятся всего 2 команды:

apktool d appname.apk, которая декомпилирует указанный .apk и apktool b directory_with_app, которая соберет .apk обратно (в указанной directory_with_app должен располагаться файл apktool.yml).

Итак, выполняю декомпиляцию при помощи команды в терминале: apktool d app.apk

После выполнения команды появляется папка с файлами приложения. Нас интересует папка smali. Smali - это язык которым описан байт-код (вот классная статья по основам smali). Именно эта папка и есть содержимое файла classes.dex. К только что выполненной команде можно добавить параметр --skip-sources или просто -s тогда вместо папки smali мы увидим тот самый файл classes.dex.

Далее, в папке smali находим интересующий и уже известный нам файл b.smali:

Открываем его любым текстовым редактором и переходим к месту, где располагается метод isRooted():

Содержимое файла b.smali
.method public a()Z    .locals 1    .line 43    invoke-virtual {p0}, Lcom/scottyab/rootbeer/b;->c()Z    move-result v0    if-nez v0, :cond_1    invoke-virtual {p0}, Lcom/scottyab/rootbeer/b;->d()Z    move-result v0    if-nez v0, :cond_1    const-string v0, "su"    invoke-virtual {p0, v0}, Lcom/scottyab/rootbeer/b;->a(Ljava/lang/String;)Z    move-result v0    if-nez v0, :cond_1    const-string v0, "busybox"    .line 44    invoke-virtual {p0, v0}, Lcom/scottyab/rootbeer/b;->a(Ljava/lang/String;)Z    move-result v0    if-nez v0, :cond_1    invoke-virtual {p0}, Lcom/scottyab/rootbeer/b;->f()Z    move-result v0    if-nez v0, :cond_1    invoke-virtual {p0}, Lcom/scottyab/rootbeer/b;->g()Z    move-result v0    if-nez v0, :cond_1    .line 45    invoke-virtual {p0}, Lcom/scottyab/rootbeer/b;->b()Z    move-result v0    if-nez v0, :cond_1    invoke-virtual {p0}, Lcom/scottyab/rootbeer/b;->h()Z    move-result v0    if-nez v0, :cond_1    invoke-virtual {p0}, Lcom/scottyab/rootbeer/b;->j()Z    move-result v0    if-nez v0, :cond_1    invoke-virtual {p0}, Lcom/scottyab/rootbeer/b;->e()Z    move-result v0    if-eqz v0, :cond_0    goto :goto_0    :cond_0    const/4 v0, 0x0    goto :goto_1    :cond_1    :goto_0    const/4 v0, 0x1    :goto_1    return v0.end method

Можем сравнить его с неповторимым оригиналом:

Очень похожи. Итак, нас интересует return, то есть самый конец метод. Видим, что метод возвращает некоторое значение константы v0, значение которой определяется на основе выполнивших в методе условий. Нам это не подходит. Нам всегда нужно возвращать false или же как это будет в smali 0x0. Для этого добавим свою констант v1 со значением 0x0. Сделаем это прямо над return:

:goto_1const/4 v1, 0x0return v1

И конечно же заменим в return v0 на v1. Поднимемся в самое начало метода и изменим значение .locals с 1 на 2 потому, что так надо. Сохраняем изменения в файле и закрываем редактор.

Собираем .apk обратно

Для этого воспользуемся командой apktool b app, где app - папка с приложением, в котором мы редактировали smali файл. После завершения команды, в папке app появиться директория dist. Здесь и расположен наш заново собранный .apk. Однако при попытке установить его мы получим следующую ошибку:

The APK failed to install.Error: INSTALLPARSEFAILEDNOCERTIFICATES: Failed collecting certificates for /data/app/vmdl164530405.tmp/base.apk: Failed to collect certificates from /data/app/vmdl164530405.tmp/base.apk: Attempt to get length of null array

Это из-за того, что после пересборки нужно еще и переподписать приложение. Для этого нам понадобиться любой keystore файл. Или можно создать новый при помощи команды:

keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

Подписать ключом приложение можно при помощи одного из двух инструментов: apksigner или jarsigner.

Я выбрал jarsigner используя следующую команду:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore keystore app.apk cp_key

В этой команде мы указываем путь к keystore, путь к .apk, который хотим подписать и имя ключа (alias) из указанного keystore. После, вводим пароль от keystore и приложение успешно подписано.

Однако и это еще не все, теперь при попытке установить .apk мы будем получать другую ошибку:

The APK failed to install.Error: INSTALL_FAILED_INVALID_APK: Failed to extract native libraries, res=-2

Это потому, что после подписи приложения нужно выполнить оптимизацию .apk файла при помощи инструмента zipalign.

Для выполнения оптимизации нужно ввести следующую команду: ~/Library/Android/sdk/build-tools/30.0.3/zipalign -v -f -p 4 app.apk rdy.apk

30.0.3 - я выбрал самую последнюю версию на момент написания статьи. После завершения команды на выходе получаем файл rdy.apk, который можно успешно установить! Проверим, получилось ли обойти проверку на рутованность устройства:

И да, это успех!

Заключение

Вызов принят - вот, что я подумал получив этот .apk. И считаю это маленькой победой. Данной статьей я стремился описать не просто инструкцию о том, как расковырять приложение или свои способности по типу "смотрите как могу". Этой статьей я хочу сказать (и напомнить тем, кто стал забывать) что большинство проблем решаемы, нужно только копать, копать и еще раз копать, не опускать руки и результат обязательно будет удовлетворительным. Даже если, в конце концов, баг я так и не обнаружил, я очень рад что расширил свой кругозор и в дальнейшем смогу взяться за более сложные задачи! Спасибо за внимание, обязательно буду писать еще про подобные танцы с бубном!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru