Не в плане докопаться, а попробую указать на те возможности, что автор упустил: 1. библиотека winreg это обёртка над Win32 API. Она работает с вызовамиRegEnumValue и RegEnumKey , которые не видят ключи и значения, начинающиеся с null-байта (Russinovich, 2005); как улучшить - через ctypes дергать NtEnumerateKey/ NtEnumerateValueKey, так будет надежнее. 2. В текущей версии os.listdir и os.path.isfile ищет только .exe?Оч часто зловреды используют скрипты (.bat, .ps1, .vbs), динамические библиотеки (.dll), а также различные LOLBins (легитимные исполняемые файлы, которые используютяс не по назначению). Имеет смысл расширить поиск на эти типы файлов. 3. Можно подключить поиск подозрительных строк в просматриваемых скриптах, например 'reg add', 'sc create', 'schtasks', 'wmic' 4. Есть еще пара вариантов, как усилить решение, но это уже без меня, я жадный ) P.S. Если это ваше первое решение, то для начала сойдет. Удачи в развитии!
// Главный поток приложения - STA. Объект Excel создаётся здесь // и навсегда привязан к этому апартаменту, т.е.к этому потоку). var excel = new Excel.Application();
bool done = false;
// Фоновая работа на потоке пула выполняется уже в другом апартаменте Task.Run(() => { // Обращение к STA-объекту из чужого потока. COM маршалит вызов // обратно в апартамент-владелец,т.е в главный поток. int n = excel.Workbooks.Count; done = true; });
// Блокировка без обработки очереди на главном потоке: // входящий вызов к excel не будет доставлен никогда. while ( !done ) Thread.Sleep(50); // дальше этой строки управление не уйдёт //endcode
excel.Workbooks.Count вызывается с потока пула, но обслужить его обязан поток-владелец Excel - он тут главный. Вызов маршалится туда и ждёт, пока главный поток разберёт свою очередь сообщений. Тем временем главный поток Excel сидит в Thread.Sleep и очередь не трогает. Worker ждёт главного, главный ждёт worker'а и в итоге получаем дедлок. Причем здесь COM, а не «просто блокировка»: замените excel на обычный объект напримерvar list = new List<int>(); int n = list.Count; и зависания не будет. Поток пула просто читает поле, без маршалинга, done мгновенно ==true. Структура та же, блокировка та же. Дедлок появляется ровно тогда, когда объект будет STA-COM с привязкой к потоку. Сразу уточню, и вам отдельное спасибо, за то что задали хороший вопрос и подтолкнули в правильном направлении и помогли уточнить итоговое заключение - блокировка должна быть такой, при которой поток не разбирает свою очередь сообщений: Thread.Sleep, lock, синхронный I/O , например. Замените на Thread.Join() или WaitHandle.WaitOne(), и дедлока может не быть, потому что ожидания на STA-потоке обрабатывают входящие RPC-сообщения и могут протолкнуть COM-вызов. Более подробнее об этом в статье Joe Duffy, ссылку давал наверху.
Насчёт голого Win32, да, и я с этим не спорю. Вложенные циклы сообщений, модальные диалоги (MessageBox etc) со своим циклом, требование реентерабельности WndProc это всё чистый Win32, не COM. Но статья немного о другом. Реентерабельность это когда поток продолжает обрабатывать новые сообщения, не завершив текущий вызов: отсюда повторный вход в процедуру. COM-дедлок - вещь обратная по смыслу, поток перестаёт обрабатывать сообщения, пока в очереди ждёт входящий вызов. STA-объект привязан к потоку-создателю; синхронный межапартаментный вызов к нему маршалится, доставляется в поток-владелец как сообщение и обслуживается, только когда тот обрабатывает свою очередь. Заблокируйте этот поток так, что он перестанет разбирать сообщения, и если на нём же висит ожидание, получаете цикл: A ждёт результат от B, B синхронно вызывает STA-объект на A, вызов стоит в очереди A, а A заблокирован и до очереди не доходит. Это и есть дедлок. А голый Win32-поток, который заблокировали, просто зависнет, не рисует, не отвечает, но это не дедлок: цикла ожидания нет, он выдохнет и возобновит работу по окончанию блокировки.
Спасибо за честный, конструктивный и въедливый ответ, который приятно читать, редкое качество, честно. По первым двум пунктам - отдать все на съедение Task.Run, абсолютно согласен, не идеально, но рабочее решение. Насчет Office-interop и 1С - вы правы 100%, они умеют работать вне UI-треда, но причина не в Task.Run, а в привязке самого объекта:он или создавался и обрабатывался в отдельном потоке, либо он был threadingModel=Both, то есть не был привязан занятому UI-треду. То есть всё упиралось в апартамент и threading model объекта, а не в то, откуда вы его дергаете. По поводу COM-стороны. Я в статье пытался показать не то, как решить проблему непонятного дедлока, а почему он возникает. На уровне COM Task.Run не работает так, как вы от него ждете. STA-объект привязан к апартаменту, то есть к потоку, который его создал и вызовы к нему обязаны обслуживаться на этом потоке. Вызовом Task.Run() с пул-потока маршалится обратно в апартамент объекта, то есть в ваш UI-тред, и если тот заблокирован и не обрабатывает очередь, то получите дедлок. Что я хотел сказать в статье - не давать вам рабочее решение, там нет таких советов. Я про то, что понимание механизма на уровне "я думал это дно, но тут снизу постучали" должно предостеречь от неочевидных ошибок
Плюс от меня, согласен абсолютно. Могу только отметить, что это похоже на костыль, вплетать LPC-вызов в очередь сообщений PeekMessageW + DispatchMessageW
Ну, раз вы настаиваете... Совет «не лочить UI-поток и ставить ConfigureAwait(false)» абсолютно верный и справедливый и я в статье с ним не спорю. Я вообще про то, не про то, как избежать дедлока, а про то, почему он возникает. Вы пишите: "ConfigureAwait(false) же решает". Он решает один частный случай, когда продолжение после await хочет вернуться на UI-поток. Ок, с этим все гуд. Но: ConfigureAwait(false) вообще мимо когда: - .Result / .Wait на коде, который вы не контролируете; - lock, Sleep, блокирующий I/O, тяжелое вычисление прямо на UI-потоке повесят цикл сообщений независимо ни от какого ConfigureAwait; - ну самое и главное, COM-сторона: если реальный STA-COM-объект (Office interop, shell-расширение, out-of-proc сервер) попытается вызвать вас обратно на UI-поток, а вы его заблокировали - это не async-продолжение, а межапартаментный COM-вызов по той же очереди, и ConfigureAwait тут ни при чём. Так что дедлок вполне реальный и до сих пор массовый. В статье хотел показать единый механизм под всеми этими случаями: заблокировал STA-поток → встал цикл сообщений → доставка, будь то async-продолжение или COM-вызов вызывают удивление на лице разраба
По данным публикации о финальном квартале Баффетта на посту CEO, Berkshire сократила позицию в Amazon примерно на 77%, продав около 7,7 млн акций. Этот пункт я бы в статье подавала аккуратно, потому что это уже период перехода управления к Грегу Абелю и часть сделок могла отражать решения портфельных менеджеров Berkshire, а не лично Баффетта.
Кто "я"? Нейросеть? В какой статье? В этой? Хватит позориться, ей-богу, читать невозможно
...к тому же написанная нейросетью - "направить модель на репу" (на куда???), узкий скоуп, adversarial review, "этот код багнутый?", в кишках уже сидит
У меня здесь другой вопрос - sec-high рейтинг у 180 из 271 это очень много. Это может указывать на то, что процессы code review и CI/security gates у Mozilla по крайней мере хромают на полторы ноги.
Слишком много оптимизма в статье. Во-первых, атакующие получают те же инструменты, во-вторых, кодовая база Firefox не статична. Каждый новый коммит потенциально вносит новые уязвимости. В-третьих, 271 уязвимость бгг это не повод для гордости, а повод задуматься. Ну, и наконец, главная ошибка такого рассуждения (ошибка выжившего) - это экстраполяция. Mozilla нашла много багов одним инструментом и экстраполировала это в "мы можем найти все баги". Заявлять, что "дни зеродеев сочтены" - это примерно как объявить конец вирусов после изобретения антивируса. ИИ хорош в поиске ошибок, связанных с повреждением памяти. Только вот сложные логические уязвимости, race conditions в многопоточном коде, timing side-channels, цепочки из нескольких примитивов - ню-ню
Information
Rating
831-st
Registered
Activity
Specialization
Специалист по реверс-инжинирингу, Инженер по безопасности
Спасибо, но для GitHub лучше будет https://github.com/ssteelfactor-oss
Если что, обращайтесь, поделюсь парочкой идей
Не в плане докопаться, а попробую указать на те возможности, что автор упустил:
1. библиотека
winregэто обёртка над Win32 API. Она работает с вызовамиRegEnumValueиRegEnumKey, которые не видят ключи и значения, начинающиеся с null-байта (Russinovich, 2005); как улучшить - через ctypes дергать NtEnumerateKey/ NtEnumerateValueKey, так будет надежнее.2. В текущей версии
os.listdirиos.path.isfileищет только.exe?Оч часто зловреды используют скрипты (.bat,.ps1,.vbs), динамические библиотеки (.dll), а также различные LOLBins (легитимные исполняемые файлы, которые используютяс не по назначению). Имеет смысл расширить поиск на эти типы файлов.3. Можно подключить поиск подозрительных строк в просматриваемых скриптах, например 'reg add', 'sc create', 'schtasks', 'wmic'
4. Есть еще пара вариантов, как усилить решение, но это уже без меня, я жадный )
P.S. Если это ваше первое решение, то для начала сойдет. Удачи в развитии!
Минимальный пример, где COM - именно тот случай.
using Excel =Microsoft.Office.Interop.Excel;// Главный поток приложения - STA. Объект Excel создаётся здесь// и навсегда привязан к этому апартаменту, т.е.к этому потоку).
var excel = new Excel.Application();
bool done = false;// Фоновая работа на потоке пула выполняется уже в другом апартаменте
Task.Run(() =>{
// Обращение к STA-объекту из чужого потока. COM маршалит вызов
// обратно в апартамент-владелец,т.е в главный поток.
int n = excel.Workbooks.Count;
done = true;
});
// Блокировка без обработки очереди на главном потоке:// входящий вызов к excel не будет доставлен никогда.
while ( !done ) Thread.Sleep(50); // дальше этой строки управление не уйдёт
//endcode
excel.Workbooks.Countвызывается с потока пула, но обслужить его обязан поток-владелец Excel - он тут главный. Вызов маршалится туда и ждёт, пока главный поток разберёт свою очередь сообщений. Тем временем главный поток Excel сидит вThread.Sleepи очередь не трогает. Worker ждёт главного, главный ждёт worker'а и в итоге получаем дедлок.Причем здесь COM, а не «просто блокировка»: замените
excelна обычный объект напримерvar list = new List<int>(); int n = list.Count;и зависания не будет. Поток пула просто читает поле, без маршалинга,doneмгновенно ==true. Структура та же, блокировка та же. Дедлок появляется ровно тогда, когда объект будет STA-COM с привязкой к потоку.Сразу уточню, и вам отдельное спасибо, за то что задали хороший вопрос и подтолкнули в правильном направлении и помогли уточнить итоговое заключение - блокировка должна быть такой, при которой поток не разбирает свою очередь сообщений:
Thread.Sleep,lock, синхронный I/O , например. Замените наThread.Join()илиWaitHandle.WaitOne(), и дедлока может не быть, потому что ожидания на STA-потоке обрабатывают входящие RPC-сообщения и могут протолкнуть COM-вызов. Более подробнее об этом в статье Joe Duffy, ссылку давал наверху.Насчёт голого Win32, да, и я с этим не спорю. Вложенные циклы сообщений, модальные диалоги (MessageBox etc) со своим циклом, требование реентерабельности WndProc это всё чистый Win32, не COM.
Но статья немного о другом.
Реентерабельность это когда поток продолжает обрабатывать новые сообщения, не завершив текущий вызов: отсюда повторный вход в процедуру. COM-дедлок - вещь обратная по смыслу, поток перестаёт обрабатывать сообщения, пока в очереди ждёт входящий вызов.
STA-объект привязан к потоку-создателю; синхронный межапартаментный вызов к нему маршалится, доставляется в поток-владелец как сообщение и обслуживается, только когда тот обрабатывает свою очередь. Заблокируйте этот поток так, что он перестанет разбирать сообщения, и если на нём же висит ожидание, получаете цикл: A ждёт результат от B, B синхронно вызывает STA-объект на A, вызов стоит в очереди A, а A заблокирован и до очереди не доходит. Это и есть дедлок. А голый Win32-поток, который заблокировали, просто зависнет, не рисует, не отвечает, но это не дедлок: цикла ожидания нет, он выдохнет и возобновит работу по окончанию блокировки.
Спасибо за честный, конструктивный и въедливый ответ, который приятно читать, редкое качество, честно.
По первым двум пунктам - отдать все на съедение Task.Run, абсолютно согласен, не идеально, но рабочее решение.
Насчет Office-interop и 1С - вы правы 100%, они умеют работать вне UI-треда, но причина не в
Task.Run, а в привязке самого объекта:он или создавался и обрабатывался в отдельном потоке, либо он был threadingModel=Both, то есть не был привязан занятому UI-треду. То есть всё упиралось в апартамент и threading model объекта, а не в то, откуда вы его дергаете.По поводу COM-стороны. Я в статье пытался показать не то, как решить проблему непонятного дедлока, а почему он возникает.
На уровне COM Task.Run не работает так, как вы от него ждете. STA-объект привязан к апартаменту, то есть к потоку, который его создал и вызовы к нему обязаны обслуживаться на этом потоке. Вызовом Task.Run() с пул-потока маршалится обратно в апартамент объекта, то есть в ваш UI-тред, и если тот заблокирован и не обрабатывает очередь, то получите дедлок.
Что я хотел сказать в статье - не давать вам рабочее решение, там нет таких советов. Я про то, что понимание механизма на уровне "я думал это дно, но тут снизу постучали" должно предостеречь от неочевидных ошибок
Плюс от меня, согласен абсолютно. Могу только отметить, что это похоже на костыль, вплетать LPC-вызов в очередь сообщений
PeekMessageW+DispatchMessageWНу, раз вы настаиваете...
Совет «не лочить UI-поток и ставить ConfigureAwait(false)» абсолютно верный и справедливый и я в статье с ним не спорю. Я вообще про то, не про то, как избежать дедлока, а про то, почему он возникает.
Вы пишите: "ConfigureAwait(false) же решает". Он решает один частный случай, когда продолжение после await хочет вернуться на UI-поток. Ок, с этим все гуд.
Но:
ConfigureAwait(false) вообще мимо когда:
- .Result / .Wait на коде, который вы не контролируете;
- lock, Sleep, блокирующий I/O, тяжелое вычисление прямо на UI-потоке повесят цикл сообщений независимо ни от какого ConfigureAwait;
- ну самое и главное, COM-сторона: если реальный STA-COM-объект (Office interop, shell-расширение, out-of-proc сервер) попытается вызвать вас обратно на UI-поток, а вы его заблокировали - это не async-продолжение, а межапартаментный COM-вызов по той же очереди, и ConfigureAwait тут ни при чём.
Так что дедлок вполне реальный и до сих пор массовый.
В статье хотел показать единый механизм под всеми этими случаями: заблокировал STA-поток → встал цикл сообщений → доставка, будь то async-продолжение или COM-вызов вызывают удивление на лице разраба
Кто "я"? Нейросеть? В какой статье? В этой?
Хватит позориться, ей-богу, читать невозможно
...к тому же написанная нейросетью - "направить модель на репу" (на куда???), узкий скоуп, adversarial review, "этот код багнутый?", в кишках уже сидит
...тем более, что реактивная струя из капсулы в обратную сторону направлена
"Один"?
У меня здесь другой вопрос - sec-high рейтинг у 180 из 271 это очень много. Это может указывать на то, что процессы code review и CI/security gates у Mozilla по крайней мере хромают на полторы ноги.
Слишком много оптимизма в статье. Во-первых, атакующие получают те же инструменты, во-вторых, кодовая база Firefox не статична. Каждый новый коммит потенциально вносит новые уязвимости. В-третьих, 271 уязвимость бгг это не повод для гордости, а повод задуматься. Ну, и наконец, главная ошибка такого рассуждения (ошибка выжившего) - это экстраполяция. Mozilla нашла много багов одним инструментом и экстраполировала это в "мы можем найти все баги".
Заявлять, что "дни зеродеев сочтены" - это примерно как объявить конец вирусов после изобретения антивируса. ИИ хорош в поиске ошибок, связанных с повреждением памяти. Только вот сложные логические уязвимости, race conditions в многопоточном коде, timing side-channels, цепочки из нескольких примитивов - ню-ню