Ошибка cmd.exe разбора приводит к другим эксплойтам?

Прежде чем продолжить, обратите внимание, что это довольно длинное информационное уведомление о командной строке Windows, поскольку я нашел ошибку, которая может быть использована с использованием простых пакетных файлов. Эта ошибка распространена во всех версиях Windows с 2000 года и работает на 64-разрядных и 32-разрядных машинах, и, будучи ошибкой партирования пакетного файла, не требуется дополнительное программное обеспечение для установки (cmd.exe является частью Windows по умолчанию) и может быть инициирован любым пользователем с любым уровнем привилегий (при условии, что они могут запускать cmd.exe и, следовательно, анализировать пакетные файлы). В это резюме включена сборка, где происходит ошибка (с разбивкой потока кода, чтобы показать, почему). Это не ошибка уровня RCE (а не то, что я еще смог найти), просто тип DoS и требует, чтобы пользователь запустил его (или использовал его как элемент запуска), но учитывая его простоту и вездесущность систем Windows, я полагал, что это заслуживает второго взгляда. Обратите внимание, что я не несу ответственности, если вы запустили какую-либо из этих ошибок, включающую командные файлы и разбив вашу систему (диспетчер задач и убить PID работает на runaway script, если вы их запустите).

TL;DR: командный файл с только этой строкой ^ nul<^ приведет к массивной утечке памяти, тогда как командный файл с только этой строкой ^|^ приведет к сбою командной строки из-за бесконечности рекурсии. Эти поведения могут привести к интересным пакетным "взломам" в любой системе Windows (Win2k +), и причиной является логическая ошибка в обработке пакетного файла cmd.exe (см. Далее код сборки и псевдо-кода ниже).

Фон

Отвечая на вопрос о SuperUser (ссылка), я столкнулся с интересной аномалией того, как интерпретатор команд разбирает пакетные файлы. Если символ каретки (^) является последним символом файла, может произойти сбой памяти /cmd.exe. Каретка должна быть последним символом файла и не может сопровождаться символом \n (символ линии), хотя \r (символ возврата каретки) в порядке, когда он удаляется до анализа синтаксиса; ничто не может проследить его, поскольку это приведет к тому, что парсер будет нормально работать (поскольку ^\r\t станет ^\t, поэтому \t будет "проигнорирован" ). Эта последняя заметка о символах возврата каретки в порядке, чтобы эта ошибка все еще происходила, фактически делает ее немного более интересной, потому что она "подделывает" новую строку в большинстве текстовых редакторов, а в блокноте вы можете обмануть мысль о том, что в конце появляется новая строка ( "технически" это возврат каретки или новая старая "Мак".

После нескольких быстрых исследований я обнаружил, что ^ в конце файла может привести к утечке памяти или может привести к сбою командной строки (более конкретно, command.com или cmd.exe), я также нашел что определенные командные файлы (и их последовательности) могут привести к очень интересному поведению. Дальнейшие исследования приводят меня к другим людям, которые отмечают подобные проблемы; вопрос о переполнении стека, в котором пользователь отметил утечку памяти и тему сообщения на ss64.com, в которой отмечен другие интересные поведения с кареткой в ​​EOF. Вопрос о переполнении стека помог подтвердить суспензии о том, что это бесконечная ситуация с типом цикла, но не пыталась погрузиться гораздо глубже, чем это. В разделе ss64.org в основном обсуждались различные способы сбоя командной строки, но не удалось объяснить, что это за крушение или почему.

Естественно, это привело меня к вопросу о том, что происходит и почему (и может ли оно быть использовано). Ответы смешаны, и исправление довольно просто (по крайней мере, это кажется "простым" на собрании, которое я проверял). Я обнаружил, что существует несколько комбинаций обманчивости пакетных файлов, которые могут привести к утечке памяти, насколько быстро или медленно зависит от того, что помещается в пакетный файл (а не сколько календаря, но последовательности труб и интересная длина строки [более поздняя])) и независимо от сбоя или утечки памяти, код парсера находится в жестком цикле в одном потоке, поэтому использование ЦП значительно возрастает (одноядерный процессор или толкается в одно сродство, дает в среднем 98%% использования ЦП).

Сбой

Чтобы свернуть командную строку было достаточно просто, командный файл без строк новой строки, содержащий только следующие символы ^&^ (или ^|^), вызовет командную строку, с которой пакет обрабатывается, для сбоя с кодом ошибки of 0xC00000FD, который является переполнением стека/кадра из-за бесконечной рекурсии. Это подтвердило сценарий "бесконечного цикла", но не совсем объяснило утечку памяти (или почему в этом случае она терпит крах из-за бесконечной рекурсии?). В этой связи я начал изучать некоторые из самых простых способов создания утечки памяти; как оказалось, 2-байтовый пакетный файл - это все, что необходимо для использования 100% -ного процессора и использования памяти (хотя и с безумно медленной скоростью, ~ 8 к /5 с на 2,7 ГГц i7).

Ешьте память

Пакетный файл, который я использовал для тестирования, содержал следующие шестнадцатеричные байты:

0x01 0x5E

0x5E является символом каретки (^) и 0x01 является символьным кодом ASCII для "начала заголовка". Первый HEX-код только наполовину значим в ошибке, он не может быть нулевым (0x00), \r, | или &, поскольку эти символы приводят к выходу пакетного файла с помощью обычного завершения (т.е. "недействительная команда обнаружена" ). Я использовал 0x01, чтобы продемонстрировать, что он не должен быть допустимой командой (или печатаемым символом, если на то пошло), чтобы вызвать ошибку, также будет достаточно 2-байтовый пакетный файл, содержащий просто a^.

Выполняя некоторые другие тесты, я нашел, что самый быстрый способ съесть память (и самый простой) с командным файлом - это следующая строка: ^ nul<^

... Неправильно запуская это сам пару раз, будьте внимательны, это очень быстро повредит 64-битную систему; потребовалось примерно 20 секунд, чтобы съесть все оставшиеся 14 ГБ оперативной памяти (всего 16 ГБ) на моем четырехъядерном ядре (HTT, так что 8 эффективных ядер) i7, которые затем сделали мою машину бесполезной, пока все пыталось выполнить страницу (мне пришлось перезапустить мой машина). Запуск этой "быстрой" версии в 32-битной системе завершил синтаксический анализатор команды с ошибкой out of memory, поскольку он быстро исчерпал свой 32-битный лимит 2 ГБ. Это не приводит к сбою командной строки, вместо этого кажется, что есть проверка, чтобы обеспечить правильную память malloc d, и когда она не может просто прерывать пакетную обработку.

Прикованная забавная ошибка

Обратите внимание, что все эти "пакетные эксплоиты" могут быть "соединены" вместе, поэтому в 32-битной системе (при условии, что у нее всего 4 ГБ ОЗУ без PAE), можно выполнить следующую команду для префикса DoS на нем: cmd eat_mem.bat | eat_mem.bat (это запустит 2 синтаксических анализатора и выйдет 2 ГБ каждый).

Еще одна интересная вариация - объединить пакетные файлы "crash"; например, предположив там файл с именем crash.bat, и он содержит наш "аварийный эксплоит" сверху (^&^), вы можете сделать следующее: cmd crash.bat | crash.bat и отметить некоторое интересное поведение. Этот конкретный приводит к тому, что вывод cmd crash.bat записывается в поврежденный канал (из-за ошибки парсера) и, таким образом, дает ошибки wrote to a non-existent pipe при попытке CTRL+C из него; достаточно интересно, хотя он по-прежнему позволяет выполнять команды, такие как ввод notepad и нажатие enter запустит блокнот. Я исследовал это больше для возможного угона, но у меня пока нет ничего плодотворного (подробнее об "подвигах" ниже).

Буфер 8K

Как упоминал вопрос/ответ о переполнении стека, чем больше ^ у вас на линии, тем быстрее он будет потреблять память (кроме "быстрой" версии, которую я нашел). Через несколько экспериментов я обнаружил, что "длина линии" может действительно иметь некоторые интересные эффекты для этой ошибки. Если последняя строка командного файла имеет ^ в конце и составляет ровно 8192 байта (включая каретку), ошибка выходит из строя... Однако все, что ниже и выше, кратно 8192, вызывает ошибку. Чем больше байтов в строке, тем быстрее потребляется память (до кратного 8192). Этот номер 8192 интересен тем, что наша утечка памяти составляет 8 тыс. (Или в больших кусках).

Следует отметить, что размер файла не имеет отношения к ошибке, и из-за этого может быть помещен практически любой безобидный командный файл. В качестве теста я поставил "быструю" версию (^ nul<^) в конце командного файла, который я использую, чтобы скомпилировать много устаревшего кода. Этот компилятор script находится чуть ниже 21 КБ с рекурсивными вызовами и несколькими функциями (чтобы я мог скомпилировать определенные вещи), и поместив строку "багги" в конец файла, мне удалось запустить компиляцию script как обычно и полно как обычно, но когда он попал в "ошибку", он развернул мой процессор и быстро съел мою память.

Если бы я был скромным инженером-программистом, получившим "простой" компилятор script (при вызове :eof случайным образом там "заставляя" ошибку), я бы не подумал дважды, если script внезапно ударил мой процессор, и если бы я не обращал внимания на мой диспетчер задач, я бы не увидел, как быстро моя RAM была съедена, а затем нужно перезагрузить (не весело).

Копать глубже

Отсюда я решил провести несколько проверок более высокого уровня, чтобы увидеть, что происходит с командной строкой, пока эта утечка происходила. Я открыл Process Explorer и Procmon инструменты для проверить, что происходит в процессах (в стеке с PE) и с системой (через Procmon). Procmon подтвердил утечку 8k (более конкретно 8191 bytes) с вызовом ReadFile с буфером байтов 8191, а PE подтвердил вызовы к ядру для ReadFile, хотя я не был уверен, почему читается командный файл?

Интересно, что эта ошибка также позволяет изменять командные файлы во время работы и повторного анализа (до 8 тыс. "разбора", линейных каналов и т.д.). Следует отметить, что содержимое может быть изменено, и некоторые команды будут обработаны, но я заметил, что, если там не будет много других команд (более конкретно линейных фидов до окончательного ^), время также может сыграть роль в успех модифицированного пакетного "взлома", хотя это происходит чаще, чем нет (т.е. он работает большую часть времени).

Эти групповые эксплоиты заставляют меня задаться вопросом, можно ли это сделать программно; моя первая попытка была простой программой на C, которая просто имела system("crash.bat");, которая вызывала пакетный файл, содержащий ^&^ в нем. Это запустило отдельный процесс cmd.exe, который впоследствии разбил возвращаемый контроль на мою программу (все это ожидалось). Затем я переключился на простой файл утечки памяти (содержащий только a^) и снова запустил программу, на этот раз cmd.exe запустился и начал вращаться (как и ожидалось), но когда я нажал CTRL+C, cmd.exe процесс был осиротевшим, и управление вернулось к моей программе, и мне пришлось закончить процесс изгоев cmd.exe через диспетчер задач. Я также попытался использовать строки из файла непосредственно в моей программе (т.е. Вызывая что-то в действии system("^ nul<^");), но получил верные результаты назад (в этом случае допустимо, что команда была признана "недопустимой" парсером команд). Я пробовал варианты того, как подключиться к процессу или воспользоваться ошибкой/кадра, но из-за того, что cmd.exe является самим парсером, некоторые из наиболее очевидных эксплойтов будут не такими легкими. В этой связи я решил открыть процесс cmd.exe и проверить сборку, чтобы проверить, что происходит, и лучше понять, что происходит и как это можно использовать (если вообще).

Код (cmd.exe)

Я использовал Visual Studio 2010 и подключился к запущенному процессу cmd.exe, а затем используя "простой" пакетный пакет памяти (a^) приостановил процесс, чтобы пройти через сборку, в то время как синтаксический анализатор находился в состоянии ошибки. После проверки сборки и использования Process Explorer, чтобы проверить, в каком модуле я находился во время отладки, мне удалось проследить много потоков кода и найти, где синтаксический анализатор искал символ ^ (hex 0x5E). Ниже приведен поток сборки, так как я вижу, где проблема.

Обратите внимание, что большая часть функции "основной" и "синтаксической" функции была удалена для краткости (соответствующий код отправлен, но полный дамп того, что я нашел, доступен по запросу [1,2 МБ дампа ASM с комментариями] ):

; start cmd.exe asm code flow 

000000004A161D50 ; { start main  (more init frame/code here)
; { start loop
000000004A161FC1 3B F5                cmp         esi,ebp  
; mem leak here?? esi == #bytes, ebp == our 8191 buffer size number
000000004A161FC3 7D 29                jge         000000004A161FEE  
000000004A161FC5 0F B7 44 24 20       movzx       eax,word ptr [rsp+20h]  
000000004A161FCA 48 8D 54 24 70       lea         rdx,[rsp+70h]  
000000004A161FCF 48 8D 4C 24 20       lea         rcx,[rsp+20h]  
000000004A161FD4 66 89 03             mov         word ptr [rbx],ax  
000000004A161FD7 48 83 C3 02          add         rbx,2  
000000004A161FDB FF C6                inc         esi 
000000004A161FDD 48 89 5C 24 60       mov         qword ptr [rsp+60h],rbx  
000000004A161FE2 E8 99 04 00 00       call        000000004A162480  ; main_parser_fn
000000004A161FE7 3D 00 01 00 00       cmp         eax,100h  
000000004A161FEC 75 D3                jne         000000004A161FC1
; } end loop
000000004A162058 ; } end main?? function here

; { start main_parser_fn
000000004A162480 48 8B C4             mov         rax,rsp  
000000004A162483 48 89 58 08          mov         qword ptr [rax+8],rbx  
000000004A162487 48 89 70 10          mov         qword ptr [rax+10h],rsi  
000000004A16248B 48 89 78 18          mov         qword ptr [rax+18h],rdi  
000000004A16248F 4C 89 60 20          mov         qword ptr [rax+20h],r12  
000000004A162493 41 55                push        r13  
000000004A162495 48 83 EC 20          sub         rsp,20h  
000000004A162499 48 8B DA             mov         rbx,rdx  
000000004A16249C 48 8B F9             mov         rdi,rcx  
000000004A16249F E8 BC FB FF FF       call        000000004A162060  ; get_next_char
000000004A1624A4 33 F6                xor         esi,esi  
000000004A1624A6 66 89 07             mov         word ptr [rdi],ax  
000000004A1624A9 39 35 D1 98 03 00    cmp         dword ptr [4A19BD80h],esi  
000000004A1624AF 0F 85 F1 75 01 00    jne         000000004A179AA6  
000000004A1624B5 0F B7 17             movzx       edx,word ptr [rdi]  
000000004A1624B8 41 BD 3C 00 00 00    mov         r13d,3Ch  
000000004A1624BE 8B CA                mov         ecx,edx  
000000004A1624C0 45 8D 65 CE          lea         r12d,[r13-32h]  
000000004A1624C4 3B D6                cmp         edx,esi  
000000004A1624C6 74 98                je          000000004A162460  
000000004A1624C8 41 2B CC             sub         ecx,r12d  
000000004A1624CB 74 93                je          000000004A162460  
000000004A1624CD 83 E9 1C             sub         ecx,1Ch  
000000004A1624D0 74 91                je          000000004A162463  
000000004A1624D2 83 E9 02             sub         ecx,2  
000000004A1624D5 0F 84 61 FF FF FF    je          000000004A16243C  
000000004A1624DB 83 E9 01             sub         ecx,1  
000000004A1624DE 0F 84 6A FF FF FF    je          000000004A16244E  
000000004A1624E4 83 E9 13             sub         ecx,13h  
000000004A1624E7 0F 84 76 FF FF FF    je          000000004A162463  
000000004A1624ED 83 E9 02             sub         ecx,2  
000000004A1624F0 0F 84 6D FF FF FF    je          000000004A162463  
000000004A1624F6 83 E9 02             sub         ecx,2  
000000004A1624F9 0F 84 28 FF FF FF    je          000000004A162427  ; quote_parse_fn
000000004A1624FF 41 3B CD             cmp         ecx,r13d  ; check if it the '<'
000000004A162502 0F 84 5B FF FF FF    je          000000004A162463  
000000004A162508 83 FA 5E             cmp         edx,5Eh  ; start the '^' parse
000000004A16250B 0F 84 86 DC 00 00    je          000000004A170197  ; caret_parse
000000004A162511 83 FA 22             cmp         edx,22h  
000000004A162514 0F 84 5E 2F 00 00    je          000000004A165478  
000000004A16251A F6 03 23             test        byte ptr [rbx],23h  
000000004A16251D 0F 84 E5 00 00 00    je          000000004A162608  
000000004A162523 0F B7 0F             movzx       ecx,word ptr [rdi]  
000000004A162526 FF 15 54 6C 02 00    call        qword ptr [4A189180h]  
000000004A16252C 3B C6                cmp         eax,esi  
000000004A16252E 0F 85 C0 10 00 00    jne         000000004A1635F4  
000000004A162534 33 C0                xor         eax,eax  
000000004A162536 48 8B 5C 24 30       mov         rbx,qword ptr [rsp+30h]  
000000004A16253B 48 8B 74 24 38       mov         rsi,qword ptr [rsp+38h]  
000000004A162540 48 8B 7C 24 40       mov         rdi,qword ptr [rsp+40h]  
000000004A162545 4C 8B 64 24 48       mov         r12,qword ptr [rsp+48h]  
000000004A16254A 48 83 C4 20          add         rsp,20h  
000000004A16254E 41 5D                pop         r13  
000000004A162550 C3                   ret  
; } end main_parser_fn

; { start get_next_char
000000004A162060 FF F3                push        rbx  
000000004A162062 48 83 EC 20          sub         rsp,20h  
000000004A162066 48 8B 05 0B C2 02 00 mov         rax,qword ptr [4A18E278h]  
000000004A16206D 8B 0D ED 9B 03 00    mov         ecx,dword ptr [4A19BC60h]  
000000004A162073 33 DB                xor         ebx,ebx  
000000004A162075 66 39 18             cmp         word ptr [rax],bx 
000000004A162078 74 29                je          000000004A1620A3  ; when bx=0 
000000004A16207A 66 83 38 0D          cmp         word ptr [rax],0Dh ; 0d = \r
000000004A16207E 0F 84 69 0E 00 00    je          000000004A162EED  
000000004A162084 3B CB                cmp         ecx,ebx  
000000004A162086 0F 85 46 7A 01 00    jne         000000004A179AD2  
000000004A16208C 0F B7 08             movzx       ecx,word ptr [rax]  
000000004A16208F 48 83 C0 02          add         rax,2  
000000004A162093 48 89 05 DE C1 02 00 mov         qword ptr [4A18E278h],rax  
000000004A16209A 66 8B C1             mov         ax,cx  
000000004A16209D 48 83 C4 20          add         rsp,20h  
000000004A1620A1 5B                   pop         rbx  
000000004A1620A2 C3                   ret  
; } end get_next_char
000000004A1620A3 E8 18 00 00 00       call        000000004A1620C0  
000000004A1620A8 48 8B 05 C9 C1 02 00 mov         rax,qword ptr [4A18E278h]  
000000004A1620AF 8B 0D AB 9B 03 00    mov         ecx,dword ptr [4A19BC60h]  
000000004A1620B5 EB C3                jmp         000000004A16207A  

000000004A1620C0  ; this starts a large chunk of code that does more parsing (as well as calls
; some CriticalSection code) it omitted from this because the issues that are prevalent in the
; rest of the code are pertaining to the 'caret_parser' not returning properly. The 'memory leak'
; is in this section code (an 8k buffer read that also checked in main loop).


; { start quote_parse
000000004A162463 F6 03 22             test        byte ptr [rbx],22h  
000000004A162466 0F 85 9C 00 00 00    jne         000000004A162508  
000000004A16246C B8 00 01 00 00       mov         eax,100h  
000000004A162471 E9 C0 00 00 00       jmp         000000004A162536  
; } end quote_parse

; { start caret_parse
000000004A170197 F6 03 22             test        byte ptr [rbx],22h ; check if '"' 
000000004A17019A 0F 85 71 23 FF FF    jne         000000004A162511  ; if char == '"'
000000004A1701A0 E8 BB 1E FF FF       call        000000004A162060  ; get_next_char
000000004A1701A5 66 89 07             mov         word ptr [rdi],ax  ; ax will be 0 if EOF
000000004A1701A8 66 41 3B C4          cmp         ax,r12w  ; r12w is 0x0A ('\n') here, so this is a EOL check (fail in EOF case)
000000004A1701AC 0F 85 82 23 FF FF    jne         000000004A162534  ; this is the jump back to the 'main_parser_fn' <--error
000000004A1701B2 E9 0B 99 00 00       jmp         000000004A179AC2  ; == call 000000004A162060 (get_next_char)
000000004A1701B7 33 C9                xor         ecx,ecx  
000000004A1701B9 E8 22 1B FF FF       call        000000004A161CE0  
; } end caret_parse

; end cmd.exe asm code flow 

Основываясь на этой сборке, я смог убедиться, что код синтаксического анализа cmd.exe делает что-то вроде этого (код psuedo-C):

void main_parser_fn() { 
    /* the 'some_read_condition' is based on a lot of things but
       interestingly one of them is an 8k buffer size; the ASM
       shows an 8191 byte buffer for reading/parsing, but I
       couldn't ascertain why having a buffer divisible by exactly
       8192 bytes in the line buffer was 'ok' but anything more or
       less causes the continuation (mem leak)?? */
    while (some_read_condition) {
        // allocate 8k buffer appropriately
        x = get_next_char();
        if (x == '|' || x == '&') {
            main_parser_fn();
        }
        if (x == '^') {
            get_next_char(); // error here
            // POSSIBLE FIX:
            // if (get_next_char() == 0) { abort_batch(); }
            continue;
        }
        // free buffer (never get here due to EOF error)
    }
}

Это (конечно) грубое приближение на основе ввода/вывода и сборки, но кажется, что код для получения следующего символа после каретки находится там, где проблема.

Объяснение ошибки

Ошибка заключается в том, что при обнаружении каретки следующий символ считывается из файла (для "экранирования" ). Если каретка является последним символом файла, это приводит к логической ошибке, так как при вызове get_next_char указатель файла увеличивается на единицу; в этом случае это передается через EOF. Поскольку EOF эффективно игнорируется, когда парсер команд продолжает читать следующий вход, он по существу "сбрасывает" свой указатель на файл из-за ошибки EOF+1. В этом случае, если указатель файла на EOF+1 вызывает указатель на некотором большом отрицательном числе, и поскольку файл не может опускаться ниже 0, указатель файла в основном reset равен 0, и синтаксический анализ продолжается с самого начала файла.

Это объясняет утечку памяти и почему она 8k (буфер чтения 8k 'заполняется), а также может объяснить проблему рекурсии. Когда a | или & обнаружен в пакетном файле, он рекурсивно разбирается, и поскольку существует ошибка EOF, рекурсия становится бесконечной, поскольку пути возврата не могут быть выполнены.

Изменить: Как отмечалось в некоторых комментариях, и дальнейшие исследования показали, что карет не должен быть в конце файла, чтобы эта ошибка произошла, я в настоящее время изучаю (и разбиваю больше от ASM), чтобы увидеть, есть ли другой сценарий и почему/как это происходит.

Исправление

Похоже, что простым решением было бы проверить EOF на чтение следующего символа при анализе каретки. Эта проверка (и последующая функциональность "правильного пакетного прерывания" ) устранит проблему утечки памяти, а также бесконечную рекурсию.

бреши?

После более подробного изучения процесса и размышлений о возможных подвигах я не вижу, чтобы это было настолько серьезным, как MS14-019, но учитывая легкость его использования/реализации (и относительную легкость его фиксации), я бы рассмотрел этот "средний" уровень предупреждения, так как большинство "эксплойтов" потребовало бы, чтобы пользователь запускал командный файл, а "очевидные" пути, например, пытались использовать ошибка/кадра или запуск кода оболочки через пакетный файл окажется более сложным по сравнению с многими другими эксплойтами, которые приведут к более "плодотворному" исходу против этой безобидной пакетной ошибки. Хотя я вижу, что он используется в DoS-атаке, так как легко написать один, учитывая, что он имеет 7 байтов (^ nul<^) и потенциально может быть распределен и "настроен" довольно легко.

Вот простой vbscript, который можно было бы использовать для записи и запуска командного файла 'killer' (и делать все это тихо)

CreateObject("Scripting.FileSystemObject").CreateTextFile("killer.bat", True).Write("^ nul<^") & VbCr
CreateObject("WScript.Shell").Run "killer.bat", 0, False

Это создаст командный файл с именем killer.bat с ^ nul<^\r в нем, а затем запустит его, его можно будет поместить в файл .vbs и запустить при запуске, или поместить в макрос Excel и запустить.

echo|set /p="^ nul<^" > killer.bat

Эта строка является командной строкой, эквивалентной созданию командного файла 'killer' (выполнение нормального эха в файле приведет к \r\n в конце файла и, следовательно, ошибка не будет присутствовать).

В качестве доказательства концепции я создал этот vbscript (а также некоторые другие тесты командного файла) и поместил их в папку Startup и реестр. Когда я вошел в систему, меня приветствовали командной строки при использовании пакетных файлов и ничего при использовании vbscript, и через несколько секунд моя система остановилась и была непригодной для использования, поскольку script потреблял всю мою оперативную память. Сценарии можно завершить, убив запущенный процесс cmd.exe, но поскольку они работают так быстро, у вас может не хватить времени для запуска диспетчера задач, прежде чем он будет потреблять всю ОЗУ. Удаление с помощью Safe Mode было "лекарством" для этого, но не "исправлением".

Я мог бы также представить сценарий, когда ничего не подозревающий администратор будет запускать backup.bat script с этой неудачной ошибкой в ​​нем и непреднамеренным сбоем своего сервера. Или забава, которая может быть связана с at/schtasks.exe в незащищенной системе.

Конечно, я не вижу этих " эксплойтов", оставляя область DoS или шуток.

Я все еще проверяю различные возможности с помощью трубопровода и перенаправления "сломанных" скриптов, которые могут привести к RCE, поскольку он является самым простым вектором атаки, является DoS-атакой с "быстрым" файлом. Я тестировал эту ошибку в Windows 98, 2000, XP, Vista, 7, 8 и вариантах сервера (включая 32 и 64 бит). Командная строка Windows 98 не влияет на это, но каждая версия над ним (включить command.com, поскольку она использует cmd.exe для разбора пакетных файлов). Из любопытства я также проверил это на ReactOS и Wine (ни у кого не было проблемы).

Вопросы (отредактированы после дополнительных исследований)

Как уже говорилось, я не вижу, чтобы эта ошибка была "эксплуатируемой" больше, чем отказ в обслуживании "атака" (или шутка со стороны сотрудника/друга), но мне все-таки приходилось думать о переполнении кадров и утечках памяти, более конкретно, если они могут быть использованы (как правило, вообще).

Мой опыт и понимание с точки зрения разработки программного обеспечения/хакера говорят о том, что утечка памяти или переполнение кадров могут быть потенциально использованы на более старой ОС (скажем, Windows 98/2000/XP или более старые версии * nix?), которые не имеют определенные защитные меры (например, использование бит NX или ASLR) с учетом правильных условий, но я не смог найти никаких исследований в этих областях, кроме "нормальных" векторов атаки (переполнение буфера на основе стека) или общего документация о том, что это за вещи "(т.е. обсуждение" белой бумаги "о том, что происходит переполнение кадра или утечка памяти, и что такое NX/ASLR), а не" почему "вы не можете.

Я экспериментировал с вводом потока или какого-либо другого метода в выполняемый процесс cmd.exe для запуска тестов и анализа переполнения кадров и утечки памяти, которые происходят внутри него (а также просто общего удовольствия, которое может быть выполнено с этой ошибкой, например, с помощью CreateProcess, а затем EmptyWorkingSet для общего удовольствия), и я знаю, что не буду "никуда" эта ошибка, но это заставило меня задуматься (или, скорее, думать): когда-либо существовал эксплойт переполнения фрейма или утечка памяти в дикой природе или есть какая-то документация, которую я мог бы прочитать, что объясняет, почему (более конкретно/технически ) это не выполнимо?

Я понимаю "почему", но более конкретна, например, "регистр EIP защищен, потому что XYZ...", в отличие от "нет, это невозможно", было бы полезно; Я знаю, что каждая архитектура отличается, и я могу попросить более подробную информацию, чем можно было бы получить в ответ, но ссылки или точки обсуждения, которые я мог бы ссылаться, также полезны, поскольку я не могу найти слишком много ссылок на это.

Я плаваю в сборке, всегда помогает свежая перспектива:)

Примечание. Я отправил электронное письмо (от 04/25/2014) в Microsoft с этой ошибкой, и они ответили, что они передали это команде разработчиков и расследуют, никаких исправлений в бюллетене по безопасности не планируется (согласитесь с их на этом, поскольку ничто еще не указывает на серьезный недостаток). Будет ли редактировать, если появятся новые обновления.