Антикейлоггер «для параноика» в Safari

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

ed852e10dad040f3a32162c48995f64b.png

Существуют встроенные решения (например, виртуальная клавиатура в Windows), однако, как мы с тобой подозреваем, определить какие именно значения вводятся при помощи такого инструмента теоретически можно с помощью получения (X, Y) нашей драгоценной мышки. Чтобы выйти из ситуации просто перемешаем раскладку виртуальной клавиатуры! Что? Перемешать раскладку? Это же дико неудобно! — воскликнешь ты. И будешь прав, однако, параноим до упора…

Если быть честным, идея перемешать раскладку подсмотрена в одном крупном банке — на сайте отсутствует поле для ввода реквизитов банковской карты и предложено вводить номер через виртуальную клавиатуру, причем цифры в панели «калькулятора» переставляются местами. Сделаем же нечто подобное для любого сайта => мастерим свое расширение для браузера! #В качестве примера используем Safari.

Чтобы не особо мучаться — возьмем готовую виртуальную клавиатуру на javascript/css отсюда и слегка доработаем ее.

Основная форма



	
 
	Online Keyboard
	


 
  • `~
  • 1!
  • 2@
  • 3#
  • 4$
  • 5%
  • 6^
  • 7&
  • 8*
  • 9(
  • 0)
  • -_
  • =+
  • delete
  • tab
  • q
  • w
  • e
  • r
  • t
  • y
  • u
  • i
  • o
  • p
  • [{
  • ]}
  • |
  • caps lock
  • a
  • s
  • d
  • f
  • g
  • h
  • j
  • k
  • l
  • ;:
  • '"
  • return
  • shift
  • z
  • x
  • c
  • v
  • b
  • n
  • m
  • ,<
  • .>
  • /?
  • shift
  •  

Стили
* {
margin: 0;
padding: 0;
}
body {
font: 71%/1.5 Verdana, Sans-Serif;
background: #eee;
}
#container {
margin: 100px auto;
width: 688px;
}
#write {
margin: 0 0 5px;
padding: 5px;
width: 671px;
height: 200px;
font: 1em/1.5 Verdana, Sans-Serif;
background: #fff;
border: 1px solid #f9f9f9;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
#keyboard {
margin: 0;
padding: 0;
list-style: none;
}
	#keyboard li {
	float: left;
	margin: 0 5px 5px 0;
	width: 40px;
	height: 40px;
	line-height: 40px;
	text-align: center;
	background: #fff;
	border: 1px solid #f9f9f9;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	}
		.capslock, .tab, .left-shift {
		clear: left;
		}
			#keyboard .tab, #keyboard .delete {
			width: 70px;
			}
			#keyboard .capslock {
			width: 80px;
			}
			#keyboard .return {
			width: 77px;
			}
			#keyboard .left-shift {
			width: 95px;
			}
			#keyboard .right-shift {
			width: 109px;
			}
		.lastitem {
		margin-right: 0;
		}
		.uppercase {
		text-transform: uppercase;
		}
		#keyboard .space {
		clear: left;
		width: 681px;
		}
		.on {
		display: none;
		}
		#keyboard li:hover {
		position: relative;
		top: 1px;
		left: 1px;
		border-color: #e5e5e5;
		cursor: pointer;
		}

Обработка нажатий
$(function(){
	var $write = $('#write'),
		shift = false,
		capslock = false;
 
	$('#keyboard li').click(function(){
		var $this = $(this),
			character = $this.html(); // If it's a lowercase letter, nothing happens to this variable
 
		// Shift keys
		if ($this.hasClass('left-shift') || $this.hasClass('right-shift')) {
			$('.letter').toggleClass('uppercase');
			$('.symbol span').toggle();
 
			shift = (shift === true) ? false : true;
			capslock = false;
			return false;
		}
 
		// Caps lock
		if ($this.hasClass('capslock')) {
			$('.letter').toggleClass('uppercase');
			capslock = true;
			return false;
		}
 
		// Delete
		if ($this.hasClass('delete')) {
			var html = $write.html();
 
			$write.html(html.substr(0, html.length - 1));
			return false;
		}
 
		// Special characters
		if ($this.hasClass('symbol')) character = $('span:visible', $this).html();
		if ($this.hasClass('space')) character = ' ';
		if ($this.hasClass('tab')) character = "	";
		if ($this.hasClass('return')) character = "
";
 
		// Uppercase letter
		if ($this.hasClass('uppercase')) character = character.toUpperCase();
 
		// Remove shift once a key is clicked.
		if (shift === true) {
			$('.symbol span').toggle();
			if (capslock === false) $('.letter').toggleClass('uppercase');
 
			shift = false;
		}
 
		// Add the character
		$write.html($write.html() + character);
	});
});


Как видно из «основной формы» наша виртуальная клавиатура представляет собой обычный структурированный список ul-li, его превращает в виртуальную клавиатуру прилагающийся css файл, а обработкой нажатий занят js-скрипт, изменяющий соответствующие характеристики кнопок (видимость, регистр и прочее).

Сперва внесем некоторые модификации в стили, добавив #keycont зависимость, тем самым изолировав стили нашей клавиатуры от стилей страницы, на которой мы будем ее использовать следующим образом:

#keycont {
display: none;
position: fixed !important;
top: 50% !important;
left: 50% !important;

font: normal 14px/1.5 Verdana, Sans-Serif !important;
color: #444 !important;
text-shadow: none !important;
background-color: #eee !important;
padding: 5px 0 0 5px !important;
margin: 0;

-moz-border-radius: 5px !important;
-webkit-border-radius: 5px !important;
-webkit-user-select: none !important;

z-index:999999999 !important;
}

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

Далее доработаем на js-скрипт. Добавляем функцию перемешивания клавиш:

Array.prototype.shuffle = function( b )
{
 var i = this.length, j, t;
 while( i ) 
 {
  j = Math.floor( ( i-- ) * Math.random() );
  t = b && typeof this[i].shuffle!=='undefined' ? this[i].shuffle() : this[i];
  this[i] = this[j];
  this[j] = t;
 }
 return this;
};

Она-то и будет менять положение кнопочек на клавиатуре. Следующим шагом добавим элементы «кнопочки» для перемешивания. Для простоты — будем перемешивать клавиши в рамках горизонтали расположения (не совсем чисто, но вполне достаточно для наших нужд):
	//Constructing keyboard
	var keyboard = '
    '; var line0 = new Array('
  • ` ~
  • ', '
  • 1 !
  • ', '
  • 2 @
  • ', '
  • 3 #
  • ', '
  • 4 $
  • ', '
  • 5 %
  • ', '
  • 6 ^
  • ', '
  • 7 &
  • ', '
  • 8 *
  • ', '
  • 9 (
  • ', '
  • 0 )
  • ', '
  • - _
  • ', '
  • = +
  • '); var line1 = new Array('
  • q
  • ', '
  • w
  • ', '
  • e
  • ', '
  • r
  • ', '
  • t
  • ', '
  • y
  • ', '
  • u
  • ', '
  • i
  • ', '
  • o
  • ', '
  • p
  • ', '
  • [ {
  • ', '
  • ] }
  • ', '
  • \ |
  • '); var line2 = new Array('
  • a
  • ', '
  • s
  • ', '
  • d
  • ', '
  • f
  • ', '
  • g
  • ', '
  • h
  • ', '
  • j
  • ', '
  • k
  • ', '
  • l
  • ', '
  • ; :
  • ', '
  • ' "
  • '); var line3 = new Array('
  • z
  • ', '
  • x
  • ', '
  • c
  • ', '
  • v
  • ', '
  • b
  • ', '
  • n
  • ', '
  • m
  • ', '
  • , <
  • ', '
  • . >
  • ', '
  • / ?
  • '); line0.shuffle(); line1.shuffle(); line2.shuffle(); line3.shuffle(); keyboard += line0.join(""); keyboard += '
  • delete
  • '; keyboard += '
  • tab
  • '; keyboard += line1.join(""); keyboard += '
  • caps lock
  • '; keyboard += line2.join(""); keyboard += '
  • return
  • '; keyboard += '
  • shift
  • '; keyboard += line3.join(""); keyboard += '
  • shift
  • '; keyboard += '
  •  
  • '; keyboard+='
'; $('body').append(keyboard);

Клавиатура собрана!

Осталось дело за малым — на страничке клавиатура нужна далеко не всегда, а только в тех случаях, когда мы собираемся что-то вводить в «секретные» поля, причем этих полей на странице может быть несколько (в данном релизе будем отлавливать поля ввода пароля по известному свойству). Поэтому добавляем пару-тройку новых функций по активации/деактивации (скрытию/показу) клавиатуры:

	$write.focus(function(){
		$write = $(this);
		$keycont.fadeIn();
		wrfocus = true;
	});

	$write.focusout(function(){
		if (focusss == false) {wrfocus=false; $keycont.fadeOut();}
	});

	$keycont.hover(
	function(){
		if (wrfocus == true) focusss = true;
	},
	function(){
		focusss = false;
	}
	);

	$keycont.focusout(function(){
		if (focusss == false) {wrfocus=false; $keycont.fadeOut();}
	});

	$keycont.click(function(){
		focusss = true;
		if (wrfocus == true) $write.focus();
	});

Вот и вся магия, если не углубляться дальше.

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

Протестировано на ряде популярных ресурсов:

Для Habrahabr
d12cfb4a66474f29a46cd12107df1776.png
Для Facebook
291e5378deeb4814821330da9774795c.png
Для VK
e9c36f963af14f74bd90de99b56cb54a.png
Для Stackoverflow
fc0a3ba79713421195e5258c58f47f83.png

К сожалению, не заработало в Google и iCloud, скорее всего есть специфические моменты на данных ресурсах.

Делал клавиатуру давно, поэтому извиняюсь за не слишком подробное описание.

Сборку расширения для Safari можно скачать по этой ссылке. Устанавливается и активируется в Safari через вкладку «Разработчик», о том как это сделать — спросить в любимом поисковике.

P.S. можно настроить клавиатуру по своему вкусу (отлавливать поля ввода банковских карт и прочих специфических полей любимых сайтов), перемешивание кнопочек же отключается удалением соответствующей строчки в коде.

Пользуемся на здоровье, удачи!

Комментарии (5)

  • 13 октября 2016 в 23:45 (комментарий был изменён)

    0

    Если вдруг кто-то будет искать подобное для Firefox — Keylogger Beater
  • 14 октября 2016 в 07:57 (комментарий был изменён)

    0

    Array.prototype.shuffle = function( b )

    var line0 = new Array('


  • var line1 = new Array('

  • var line2 = new Array('
  • if (focusss == false)

  • Ужас, ужас, ужас. Приведите в порядок код и форматирование.

  • 14 октября 2016 в 09:41

    +2

    На моей памяти есть банковские трояны, которые не только сохраняют данные набираемые с клавиатуры, но и сохраняют небольшую область экранного буфера под курсором в момент клика мышкой. Так что это не панацея
    • 14 октября 2016 в 10:06

      0

      есть даже трояны с «прямым эфиром» — streaming screencast. Единственная разница- это легко заметить по нагрузке сетевой карты.
    • 14 октября 2016 в 11:42

      0

      Да. Не панацея. Но в статье хорошая идея:
      Чтобы выйти из ситуации просто перемешаем раскладку виртуальной клавиатуры!

      Конечно, если злоумышленник будет получать скрины в момент клика, то это не поможет. Но здесь возможна хитрость: обозначим буквы-цифры пиктограммами: 1-Яблоко,…, 9-Молоток,…, а-Персик, и т.д. Распечатаем на принтере эту табличку и будем выводить на клавиатуре со случайной раскладкой пиктограммы. Пользователь, набирает пароль по бумажной табличке, которую злоумышленник не видит (не забыть отключить web-камеру, перед вводом пароля!). Злоумышленник получит скрины, где были нажаты: Молоток, Персик, Яблоко, Молоток, Яблоко, … и далее ему остается делать перебор, который будет очень долгим при достаточной длине пароля.

      Можно модифицировать этот метод и использовать обычную клавиатуру, если ПО будет ее перекодировать при вводе пароля: пусть 1 → q, 2 → x, …, a → t, b → 8, … Тогда, чтобы набрать пароль x8q, пользователь должен набрать 2b1. Понятно, что таблица перекодировки должна быть надежно зашифрована, и должны быть приняты меры на случай дампа участков памяти — в этом плане предложено много эффективных подходов.

      Еще можно зашумлять набор. После каждого нажатия/клика пользователем ПО случайным образом эмулирует несколько нажатий/кликов, запоминает их и удаляет из общей последовательности нажатий/кликов, получая таким образом пароль, введенный пользователем. А злоумышленнику придется гадать, что в общей последовательности исходит от пользователя.

© Habrahabr.ru