↑ ↑ ↓ ↓ ← → ← → B A Start

Подпольный рынок кардеров. Перевод книги «Kingpin»

На хабре вышла серия постов с переводом книги Kingpin, читать которую с экрана ноутбука мне совершенно не удобно, и единственным логичным решением стал перевод книги в PDF для чтения на планшете.

Кевин Поулсен, редактор журнала WIRED, а в детстве blackhat хакер Dark Dante, написал книгу про «одного своего знакомого».

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

Задавшись такой идеей я перевел все посты в отдельные markdown файлы, внес все уточнения из комментариев к постам. А завершающим этапом прогнал все файлы через Яндекс.Спеллер для исправления грубых орфографических ошибок.

Теперь имея материал для работы, сел и написал скрипт на питоне, собирающий из этого набора файлов единый PDF файл. Вначале markdown файлы конвертируем в соответствующие им html страницы.

CHAPTERS = sorted([os.path.join(APP_PATH, f) for f in glob(CHAPTERS_PATH)])

md = Markdown(output_format="html5")

for chapter in CHAPTERS:
    html = md.reset().convert(open(chapter, 'r').read().decode('utf-8'))
    outhtml = TEMPLATE % html

    filename = os.path.splitext(os.path.basename(chapter))[0] + '.html'
    filepath = os.path.join(HTML_PATH, filename)

    with open(filepath, 'w') as f:
        f.write(outhtml.encode('utf-8'))

А на втором этапе установив в систему wkhtmltopdf и библиотеку python-pdfkit собираем из этого набора файлов готовый PDF.

htmlfiles = [os.path.join(HTML_PATH, f) for f in os.listdir(HTML_PATH) if f.endswith('.html')]

options = {
    'page-size': 'B5', # A5
    'margin-top': '0.75in',
    'margin-right': '0.75in',
    'margin-bottom': '0.75in',
    'margin-left': '0.75in',
    'encoding': 'UTF-8',
    'no-outline': None,
    'no-background': None,
}

pdfkit.from_file(htmlfiles, 'kingpin_ru.pdf', options=options, cover='static/cover.html')

Ссылку на готовый скрипт, а также все markdown файлы я выложил на Github. А приготовить PDF в домашних условиях можно выполнив:

git clone https://github.com/dotzero/Kingpin.git
cd Kingpin
pip install -r requirements.txt
python build_pdf.py

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

git clone https://github.com/dotzero/Kingpin.git
cd Kingpin
pip install -r requirements.txt
python build_epub.py

Ссылки на готовые книги:

Как я продавал домены через escrow

За последний месяц мне удалось продать два домена воспользовавшись китайским и американским escrow сервисами. Об опыте продажи и отличии сервисов я и хотел бы рассказать.

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

Первый домен я продал очень настойчивому китайцу с фамилией «杨», который просил чтобы сделка была проведена именно через китайский сервис DN.com.

Решив не упускать возможность попробовать в работе китайский сервис я не стал ему отказывать. Наблюдения по работе с сервисом я выписал в список, а процесс от начала сделки до вывода средств на PayPal занял 4 дня.

  • Для активации аккаунта необходима загрузка двух фотографий: скан ID (паспорт, права и т.д.) и фотография себя держащего этот ID;
  • После внесения оплаты покупателем, сервис помогает в передаче AuthCode домена;
  • Денежные средства можно вывести в $, € или ¥ на PayPal или банковский счет;
  • Комиссию снимают два раза, первый раз с покупателя, за сделку, а второй раз с продавца, за вывод денежных средств;
  • При выводе денег через PayPal, комиссия составила $20, против $25-30 за вывод на банковский счет.

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

  • В отличии от DN.com, сервис Escrow.com не требует подтверждение личности, а перед получением денег от покупателя проводится телефонное интервью с продавцом. Основная тема интервью — точное название домена и сумма сделки;
  • После внесения оплаты покупателем сервис никак не помогает в передаче AuthCode домена. А процесс передачи кода должен вестись напрямую с покупателем, по электронной почте;
  • Вывод денежных средств возможен только на банковский счет, комиссия составляет $40, что в два раза превышает китайский сервис.
  • Кроме того, нет возможности держать денежные средства, и сразу по завершению сделки деньги переводятся на банковский счет.

Итого, кроме отсутствия подтверждение личности Escrow.com не предоставляет никаких сервисных преимуществ, имея при этом два раза большую комиссию.

Блеск и нищета Markdown парсеров

Когда на проекте потребовалось сделать поддержку Markdown-синтаксиса, я и представить себе не мог как все плохо с Markdown парсерами на PHP. А протестировав три из четырех популярных решений на Github’e, я убедился что все они работают корректно только на собственных, синтетических тестах. Оценивал подходимость библиотек исходя из следующих требований:

  • Скорость парсинга (бенчмарк);
  • Поддержка GitHub Flavored Markdown;
  • Легко расширяемый синтаксис;
  • Не строгий к разметке и допускать наличие в тексте кастомных html тегов.

erusev/parsedown

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

cebe/markdown

Второй по скорости и стандарт де-факто в Yii 2, но чрезмерное увлечение автора рефлешенами не позволяет использовать GFM при некоторых настройках OPCache. Исправить это через наследование нет никакой возможности, а позиция автора принципиальная и менять архитектуру он не намерен.

michelf/php-markdown

Нет поддержки GitHub Flavored Markdown, так что сразу вычеркиваем.

kzykhys/ciconia

Медленная скорость работы и последний коммит от февраля 2014 года говорит о слабой заинтересованности автора в поддержке. Установке через composer тащит за собой кучу Symfony зависимостей, а не юзабельный автолинкер из GFM и большие проблемы при работе со списками делают его самой слабой библиотекой из трех.

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

Патчим mysqldump в домашних условиях

Бекапы это хорошо, а еще лучше когда они работают так как надо когда они нужны. На одном из проектов понадобилось восстановить дамп из 745 триггеров и накатить их на рабочую MySQL базу. 

MySQL позволяет использовать любые имена триггеров, в том числе с использованием точек (например: analitica.cron.indeg.y.run.a_insert). А mysqldump при создании дампа не учитывает это обстоятельство и добавляет конструкцию для их дропа следующего вида:

/*!50032 DROP TRIGGER IF EXISTS analitica.cron.indeg.y.run.a_insert */;

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

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

Поскольку исправлять этот баг будут долго, а дампы мне нужны прямой сейчас. Решить эту задачу я решил самым прямолинейным способом, а именно самостоятельно пропатчив mysqldump. Для этого склонировал официальный репозиторий перконовского дитрибутива MySQL 5.6 с GitHub’а.

git clone --recursive --depth 1 https://github.com/percona/percona-server/

Открыл файл client/mysqldump.c и добавил апострофы к конструкции DROP TRIGGER IF EXISTS в паре мест. Если посмотреть diff, то получается такой патч:

@@ -3517,7 +3517,7 @@ static void dump_trigger_old(FILE *sql_file, MYSQL_RES *show_triggers_rs,
     fprintf(sql_file, "/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n");

   if (opt_drop_trigger)
-    fprintf(sql_file, "/*!50032 DROP TRIGGER IF EXISTS %s */;\n", (*show_trigger_row)[0]);
+    fprintf(sql_file, "/*!50032 DROP TRIGGER IF EXISTS `%s` */;\n", (*show_trigger_row)[0]);

   fprintf(sql_file,
           "DELIMITER ;;\n"
@@ -3604,7 +3604,7 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs,
     switch_sql_mode(sql_file, ";", row[1]);

     if (opt_drop_trigger)
-      fprintf(sql_file, "/*!50032 DROP TRIGGER IF EXISTS %s */;\n", row[0]);
+      fprintf(sql_file, "/*!50032 DROP TRIGGER IF EXISTS `%s` */;\n", row[0]);

Чтобы собрать пропатченую версию надо поставить пару пакетов и на Ubuntu/Debian, запустить cmake с параметрами из документации к Перконе, а затем make‘ом собрать только mysqldump.

apt-get install build-essential cmake bison libaio-dev libncurses5-dev libreadline-dev
cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_CONFIG=mysql_release -DFEATURE_SET=community -DWITH_EMBEDDED_SERVER=OFF
make mysqldump

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

./percona-server/client/mysqldump \
    --socket=/var/run/mysqld/mysqld.sock \
    -uroot -p --routines --events --triggers \
    --add-drop-trigger --quote-names \
    --no-create-info --no-data --no-create-db --skip-opt \
    database_name | sed -r 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > dump.sql

Как я стал электронным гражданином Эстонии

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

Решение заполнить анкету появилось под влиянием хайпа, а увидев среди пунктов обоснований получения электронного гражданства пункт «Fan of e-Residency» заполнил все поля, оплатил и стал ждать.

Первое письмо получил ровно через месяц после подачи анкеты 18 июля. В письме сообщалось, что моя анкета принята к рассмотрению, а спустя еще месяц, 20 июля пришло сообщение о положительном решении.

e-Residency

И вот наконец спустя почти 3 месяца ожидания я получил в посольстве заветный и скромный конверт, содержащий в себе:

  • Непосредственно карточку с чипом;
  • Небольшой складной USB считывать;
  • Конверт с PIN/PUK кодами.

Наиболее любопытным из этого набора оказался USB считыватель карточки который из формата usb-флешки раскладывается в Т-образную конструкцию для подключения карточки к ноутбуку. 

e-Residency

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