Содержание

«Грузщик» или «грузчик» как пишется?

Если вы не знаете, как нужно писать «грузщик» или «грузчик», то следует вспомнить несложные орфографические правила, контролирующие написание суффиксов существительных. Давайте вместе ими воспользуемся.

Как правильно пишется

В соответствии с нормой правописания, этот существительное пишется с согласной буквой «ч» – грузчик.

Какое правило применяется

Ошибки при написании согласных букв в этом слове допускают по той причине, что сочетание «зч» мы произносим как «щ». Нам нужно убедиться, что слово пишется с согласной «ч». Для начала разберем его по составу. В нем можно выделить корень «груз» и суффикс «чик». Мы знаем, что суффикс «щик» также пишется в существительных. Но правило гласит, что если основа оканчивается на буквы «д/т», «с/з/ж», то пишем аффикс «чик». В прочих случаях – «щик». Сравните: подписчик, разносчик, доносчик, но каменщик, барабанщик. Таким образом, пишем нашу лексему с буквой «ч».

Примеры предложений

  • Нам требуется крепкий грузчик для выполнения этой работы.
  • Грузчик в одиночку затащил заказанный диван на третий этаж.

Проверь себя: «Мегаомметр» или «мегомметр» как пишется?

Как неправильно писать

Недопустимо писать это существительное с буквой «щ» – грущик.

Раздел: Орфография

Згідно з чим чи згідно чого як правильно?
Правильно Згідно з чим – правильний варіант вживання прийменникової сполуки в українській мові. Прийменник «згідно» можна вживати тільки з прийменником «з», при цьому іменник має бути в орудному відмінку. Також дану сполуку можна замінити на конструкцію “відповідно до“. Згідно з повір’ями, вітатись через поріг не можна. Таке… Читать дальше »

%d0%b3%d1%80%d1%83%d0%b7%d1%87%d0%b8%d0%ba — со всех языков на все языки

Все языкиАбхазскийАдыгейскийАфрикаансАйнский языкАканАлтайскийАрагонскийАрабскийАстурийскийАймараАзербайджанскийБашкирскийБагобоБелорусскийБолгарскийТибетскийБурятскийКаталанскийЧеченскийШорскийЧерокиШайенскогоКриЧешскийКрымскотатарскийЦерковнославянский (Старославянский)ЧувашскийВаллийскийДатскийНемецкийДолганскийГреческийАнглийскийЭсперантоИспанскийЭстонскийБаскскийЭвенкийскийПерсидскийФинскийФарерскийФранцузскийИрландскийГэльскийГуараниКлингонскийЭльзасскийИвритХиндиХорватскийВерхнелужицкийГаитянскийВенгерскийАрмянскийИндонезийскийИнупиакИнгушскийИсландскийИтальянскийЯпонскийГрузинскийКарачаевскийЧеркесскийКазахскийКхмерскийКорейскийКумыкскийКурдскийКомиКиргизскийЛатинскийЛюксембургскийСефардскийЛингалаЛитовскийЛатышскийМаньчжурскийМикенскийМокшанскийМаориМарийскийМакедонскийКомиМонгольскийМалайскийМайяЭрзянскийНидерландскийНорвежскийНауатльОрокскийНогайскийОсетинскийОсманскийПенджабскийПалиПольскийПапьяментоДревнерусский языкПортугальскийКечуаКвеньяРумынский, МолдавскийАрумынскийРусскийСанскритСеверносаамскийЯкутскийСловацкийСловенскийАлбанскийСербскийШведскийСуахилиШумерскийСилезскийТофаларскийТаджикскийТайскийТуркменскийТагальскийТурецкийТатарскийТувинскийТвиУдмурдскийУйгурскийУкраинскийУрдуУрумскийУзбекскийВьетнамскийВепсскийВарайскийЮпийскийИдишЙорубаКитайский

 

Все языкиАбхазскийАдыгейскийАфрикаансАйнский языкАлтайскийАрабскийАварскийАймараАзербайджанскийБашкирскийБелорусскийБолгарскийКаталанскийЧеченскийЧаморроШорскийЧерокиЧешскийКрымскотатарскийЦерковнославянский (Старославянский)ЧувашскийДатскийНемецкийГреческийАнглийскийЭсперантоИспанскийЭстонскийБаскскийЭвенкийскийПерсидскийФинскийФарерскийФранцузскийИрландскийГалисийскийКлингонскийЭльзасскийИвритХиндиХорватскийГаитянскийВенгерскийАрмянскийИндонезийскийИнгушскийИсландскийИтальянскийИжорскийЯпонскийЛожбанГрузинскийКарачаевскийКазахскийКхмерскийКорейскийКумыкскийКурдскийЛатинскийЛингалаЛитовскийЛатышскийМокшанскийМаориМарийскийМакедонскийМонгольскийМалайскийМальтийскийМайяЭрзянскийНидерландскийНорвежскийОсетинскийПенджабскийПалиПольскийПапьяментоДревнерусский языкПуштуПортугальскийКечуаКвеньяРумынский, МолдавскийРусскийЯкутскийСловацкийСловенскийАлбанскийСербскийШведскийСуахилиТамильскийТаджикскийТайскийТуркменскийТагальскийТурецкийТатарскийУдмурдскийУйгурскийУкраинскийУрдуУрумскийУзбекскийВодскийВьетнамскийВепсскийИдишЙорубаКитайский

Уроки правописания для грузчиков или Как-то раз в супермаркете

Был обычный рабочий день. Подъехала машина с товаром. Увидел на ней надпись-пожелание грузчикам. Интересно, подумалось, знают ли работающие со мной люди, как пишется слово «грузчик»? Какой у нас сегодня уровень грамотности? А не организовать ли нам уроки правописания?

Уроки правописания для грузчиков: день первый

О! Идея! Вырезаю кусок картонки, беру ручку и пишу 5 неправильных вариантов написания слова «грузчик»:

  • грусчик
  • грущик
  • грущек
  • грусщик
  • грузщик

Взял самые банальные и наивные, на мой взгляд, ошибки. Правильное написание, конечно, не включил. Сколько же людей, с которыми я работаю, смогут ответить, как правильно пишется слово «грузчик»? Интересно стало до «не могу».

Пошёл опрашивать народ. Ну, кто первый попадётся? Было приятно, что коллегам мой интерес тоже передался. Улыбаются, переживают по-детски… Только парочку сотрудников отнеслись к моим великим «социологическим исследованиям» с ехидцей и недоверием: мол, чего фигнёй страдаешь? Иди лучше работай!

Но я не обиделся. Ведь это были самые образованные мои коллеги…

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

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

Участвовали разные возрастные категории, примерно от 20 до 73 лет. Было видно, что многие просто не знали ответа, сомневались, думали. Я так старался не выказать на лице никаких эмоций. Но, увы… любая моя мимическая реакция приводила респондентов в замешательство.

Перед тем, как ответить, многие считали нужным сказать о том, что они были отличниками.

Вот один человек посерьёзнел и сказал: да тут же нет правильного варианта!

О! Неужели я сейчас услышу правильный вариант? Хорошо, – говорю, – напиши, как правильно. Пишет: грусщек. Мдааа…

Из всех опрошенных (15 человек) правильно ответили лишь трое: водитель, грузчик и уборщица тётя Клава. Честно говоря, я не на них «ставку делал». А в ком точно не сомневался, наоборот, подвели. Все, кто хотел поучаствовать в опросе, поучаствовал. Остальные – просто наблюдали за нами. Наверно, чтобы не ославиться.

Повеселились, посмеялись, чему-то научились, и, самое главное, – пообщались. А ещё – запомнили, как пишется это до оскомины знакомое слово!

Уроки правописания для грузчиков: день второй

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

Слово было таким: тщательно. С ним тоже все знакомы. Посмотрим, как люди тебя пишут. На этот раз количество вариантов увеличил до восьми, и правильный вариант тоже включил. Из благих побуждений, поверьте. Думал, может, ошибок меньше будет. Что ж, приступаем!

Вот Вам варианты для всплеска адреналина:

  • тсчательно
  • чательно
  • счательно
  • сщательно
  • тщятельно
  • тщательно
  • тшятельно
  • тсщательно

Ага, у нас больше желающих поучаствовать в опросе? Здорово! Прогресс был ещё и в том, что робости было уже меньше, страха ошибиться – тоже, но зато желания учиться – больше! Часть людей выбирала 2 или 3 варианта.

Из 15 опрошенных правильно ответили пятеро! И снова тётя Клава была на высоте!

А ответы какие вкусные были! Смешные, непредсказуемые, неординарные! Куда там моим вариантам! )))

В этот раз я вырезал 2 картонки. На одной были написаны пронумерованные варианты ответов, а на второй я записывал имена отвечающих выбранные ими номера ответов. После опроса я выделил правильный ответ красным маркером и вывесил эти две картонки рядом, чтобы все могли увидеть правильный ответ и сверить с ним свои варианты. Все подходили, рассматривали, улыбались и запоминали правописание ещё одного слова. А значит 15 минут я потратил не зря.

Заключение

У меня не было умысла выставить безграмотность людей напоказ. Ведь я – такой же грузчик, как и ребята, с которыми я работаю. Зачем тогда эти эксперименты? Не знаю. Хотелось просто встряхнуть людей, разбудить интерес к учёбе, самообразованию, чтению книг. Хотелось, чтобы мы все (и я и мои коллеги) задумались о том, почему мы именно здесь – в магазине, а не где-нибудь в банке или в офисе крутой фирмы.

Мы – там, где мы заслуживаем быть. Но если мы хотим большего, надо расти, учиться, развиваться, осваивать что-то новое, тренироваться…

© Максим Иваськив

Начинаем учиться? Наши статьи – настоящие уроки правописания:

Хотите зарабатывать написанием текстов? В Школе Копирайтинга Вы можете освоить профессию копирайтера, SEO-копирайтера, контент-менеджера.


Как правильно писать слова с суффиксами чик, щик, примеры

Для многих существительные, которые оканчиваются на «чик» вызывают затруднения. Но все же нужно понимать, как правильно писать, ведь и тот, и другой вариант может быть верным.

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

Правило правописания слов с суффиксом «чик»

Правил в русском языке достаточно, и для такого случая тоже есть: главное запомнить, что после определенных согласных, которыми заканчивается основа слова нужно писать «чик». Это всего 5 букв — д,т,з,с,ж. Выучить наизусть 5 согласных не сложно, чтобы не допускать грубых ошибок в дальнейшем. Тем более, что есть простой способ для их заучивания.

Примеры слов с «чик»

  • • Добытчик;
  • Перебежчик;
  • Обидчик;
  • Летчик;
  • Извозчик.

Правило правописания слов с «щик»

«Щик» в словах – надо писать после всех других согласных, заканчивающих основу слова кроме тех пяти.

Важно! Но здесь есть один момент: «щ» — мягкая согласная, поэтому все идущие перед ней буквы также смягчаются.

Многие ошибочно ставят мягкий знак перед ней и допускают грубую ошибку. Чтобы этого избежать запомните, что мягкий знак необходим лишь после буквы «л» (кольщик, дольщик).

Конечно, есть исключения, как у многих правил, например, алиментщик, астфальтщик, где основа слова заканчивается на «т», но пишется правильно «щик», хотя если вернуться к правилу, то это ошибочно. Такое возможно если можно применить 3 пункта:

  1. Корень слова из иностранного языка;
  2. Перед суффиксом стоят две согласные подряд;
  3. Основа слова заканчивается на «т».

Примеры слов с «щик»: сварщик, барабанщик, гардеробщик, кладовщик, каменщик, дрессировщик, фонарщик.

Чтобы правильно писать необходимо лишь выучить все 5 согласных и не забывать о них, когда себя проверяешь. Отличным способом помочь себе быстро запомнить – это мнемонические фразы. Для запоминания «д,т,з,с,ж» есть существует фраза «дети за сажей» именно в ней присутствуют нужные для запоминая буквы.

Полезное видео

Буквы щ и ч в суффиксе -щик (-чик)

Прочитайте. В каких словах пишется –чик, хотя произносится [щик]?

 

После каких согласных пишется буква ч в суффиксе -щик (-чик)?

 


В суффиксе существительных -щик (-чик) после букв д — т, з — с и ж пишется буква ч, а не щ,


 

1. Объясните употребление букв ч и щ в суффиксе -щик (-чик).

При списывании обозначьте орфограмму № 33.

Образец рассуждения: слово смазчик образовано от глагола смазывать, перед суффиксом есть буква з, значит, в суффиксе надо писать букву ч.

Извозчик, обходчик (путей), прессовщик, резчик (по кости), обрубщик, аппаратчик, грузчик, подборщик (мехов), разведчик, съёмщик (дачи), смазчик, перебежчик.

 

2. Ч или щ? В скобках запишите слово, от которого образовано данное, существительное.

Буфет..ик, к..пиров..ик, экск..ватор..ик, п..репис..ик, с..ртиров..ик, ра..фасов..ик, стекол..ик, автомат..ик, лёт..ик, объезд..ик, аппарат..ик, разнос..ик, воз..ик, рассказ. .ик, автопогруз..ик.

Какое из значений глагола копировать использовано при образовании выделенного существительного?

 

3. Замените глаголы однокоренными именами существительными с суффиксом -щик (-чик). Обозначите в этих существительных орфограмму № 33, а в словосочетаниях — главные слова.

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

В каком падеже стоит зависимое слово в данных и в записанных вами словосочетаниях? Почему они стоят в разных падежах?

Какое ещё значение имеет выделенное слово?

 

4. Прочитайте толкование лексического значения имён существительных, обозначающих лиц по роду занятий, по профессии, по специальности. Запишите эти существительные, обозначая в них орфограмму № 33.

1. Шахтёр, работающий в забое. 2. Железнодорожник, обслуживающий прицеп вагонов. 3. Лётчик, управляющий вертолётом. 4. Рабочий, работающий по погрузке й выгрузке. 5. Солдат, обслуживающий пулемёт. 6. Типографский рабочий, делающий переплёты у книг. 7. Железнодорожник, на обязанности которого лежит проверка цельности и смазка,колёс. 8. Военнослужащий, в обязанности которого входит разведка данных о противнике. 9. Боец, наводящий орудие или пулемёт на цель. 10. Военнослужащий, обслуживающий ракеты. 11. Специалист по переводам с одного языка, на другой.

Прочитайте ответ на 8-й вопрос. Какие ещё значения ‘этого слова вам известны?

 

5. Спишите, поставьте пропущенные запятые.

1. Строит..ли соб..рались во множеств..: пл..лись неспешно рязанские пилщики да стеколщики чинно ш..гали тверские каменщики и печники проходили кровельщики б..тонщики кузнецы.  (Л. Леонов.) 2. Ре..ко с..гналили шофёры покрикивали возчики, сновали агенты грузчики водники в форменных фура..ках. (А. Рыбаков.) 3. Сегодня вернё(т, ть)ся с лини.. сменщик. (А. Рыбаков.)

Составьте схему 2-го предложения.

Обозначьте орфограмму № 9.

 

6. Распределите слова по орфограммам на месте скобок.

Барабан(?)щик, камен(?)щик, стакан(?)чик, лимон(?)чик, ноч(?)ка, свеч(?)ка, поч(?)та, меч(?)та, свар(?)щик, сбор(?)щик, домен(?)щик, помощ(?)ник, объявление, под(?)ём, вып(?)ет, сквореч(?)ник.

 

7. Диктант. Подчеркните непроверяемые гласные в корне слова.

ЦК ВЛКСМ, Коммунистическая партия Советского Союза, Советское правительство, революция, коммунизм, пионерский галстук.

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

В какой форме стоит выделенное слово?

 

8. Сочинение. Пойдите в клуб (кинотеатр, театр, музей, на почту и т. д.). Внимательно осмотрите помещение. Каковы его размеры, назначение? Как расположены окна, двери? Какие предметы находятся в помещении? Как они расставлены? Какой пол? В какой цвет окрашены стены, потолок? Какие украшения находятся на стенах, на окнах? Как используется помещение? Какие из синонимов в рамках вы используете для описания помещения? Как вы . озаглавите своё сочинение? Какую основную мысль вы будете доказывать в нём? Составьте план и напишите деловое описание помещения.

Буквы щ — ч в суффиксах -щик — -чик

Дата: 27.07.2013 Автор: Dictread Тема: Правописание имен существительных

Летчик, зенитчик, буфетчик, добытчик, раздатчик, переплетчик, и переводчик, разведчик, докладчик, обидчик, водопроводчик, заводчик объездчик.

Перевозчик, рассказчик, заказчик, смазчик, грузчик, резчик, подписчик, переписчик, подносчик.

Наборщик бетонщик, сменщик, банщик, барабанщик, доменщик, табунщик, жестянщик, заправщик, сортировщик, каменщик, фонарщик.

Пильщик, стекольщик, кровельщик, угольщик.

Пальчик, мальчик, телефончик, карманчик, вагончик, самоварчик.

 

I. 1. Около полуночи подводчики и Егорушка опять сидели вокруг небольшого костра (Ч.) 2 Объездчик слушал со вниманием и соглашался. (Ч.) 3. Жили на свете два верных дружка, два пулеметчика, два смельчака. (А. Барто.) 4. Летчики увидели над горизонтом тревожные взмахи голубых лучей прожекторов. (В. Ставский.) 5. Грузчики шли бесконечной вереницей по трапу… (Кат.)

II. 1. Шарманщик на ходу привычным движением плеча поправил на спине шарманку и вытер вспотевшее лицо. (Купр.) 2. Хозяин оставил меня на попечение татарина-банщика. (П.) 3. Под окном стучит молоточком чеканщик Гоголев. (М. Г.) 4. На валу каменщики таскали кирпич и чинили городскую стену. (П.) 5. Между офицером и денщиком установились простые, доверчивые отношения. (Купр.) 5. Пришел фонарщик с лестницей, два тусклые фонарика на площади задул. (И.)

III. 1. Пахнет маляр скипидаром и краской. Пахнет стекольщик оконной замазкой. (М.) 2. По званию Яков — черпальщик на бумажной фабрике. (Т.)

 

ВЫБОРОЧНЫЙ ДИКТАНТ

Выпишите слова: с суффиксом чик в одну колонку, с суффиксом -щик — в другую.

1. Фрол Евсеевич ездит на извозчике в издательство за рукописями, а наборщики и печатники переводят те рукописи в книги. (Прилеж.) 2. К вечеру летчик увидел вертолет над сопками. 3. Из города приезжали скупщики. Они были проворные, ловкие, плутоватые, расчетливые. (Сераф.) 4. На Камчатке множество горячих источников, часто они бьют фонтанчиками. (Михайл.) 5. Объездчик очнулся от мыслей и встряхнул головой. (Ч) 6. В окопчике спал мальчик. (Кат.)

Профессия: грузчик. Многовековая история и современные реалии

Работа грузчиков значительно упрощает нашу жизнь на самых разных уровнях, от доставки продуктов в ближайший магазин до путешествий в дальние страны. Большинство из нас редко задумывается об особенностях этой профессии. Но неутомимый экспериментатор Аарон Кауфман лично попытается выяснить, что означает быть грузчиком в порту города Такома в США. Аарон — талантливый механик, который осваивает необычные виды деятельности в новом проекте на телеканале Discovery. Программа «Крутая работа Аарона Кауфмана» выходит в эфир по вторникам в 22:00 (мск), а мы предлагаем чуть ближе познакомиться с важной профессией грузчика.

Помощь другим с давних времен

Сколько существует человек — столько же он и переносит тяжести. Первый охотник носил добычу, первый земледелец — зерно, первый ремесленник — глину в мастерскую и горшок к заказчику. Изображения рабочих, носящих грузы, встречаются среди древнеегипетских рисунков, и до нас дошли отрывки песен, которые исполняли те, кто перевозил каменные блоки для строительства пирамид — но вот грузчиков ни во времена фараонов, ни позже, в Греции и Риме, не было: грузы носили сами работники, рекрутированные крестьяне или рабы.

Профессия грузчика возникла в Средневековье, когда из-за роста городских производств и развития торгово-рыночных отношений появилась потребность в массовых грузоперевозках — а вместе с ними и в профессионалах, занимавшихся погрузкой и складированием товаров. Поскольку водные — речные и морские — пути были наиболее доступными, быстрыми и безопасными маршрутами перевозок, то первые грузчики работали в портах и на пристанях.

В 30-е годы прошлого века окончательно сформировалась еще одна специализация грузчиков — помощь в переездах. Подобные услуги оказывали и раньше, но в период Великой депрессии в США, когда люди тысячами покидали города в поисках лучшей жизни, начали появляться первые компании, специализирующиеся на мувинге. Работники таких фирм занимались не только транспортировкой груза, но также подготовкой к переезду и упаковкой вещей.

Нелегкий труд

Одним из основных требований к кандидатам на должность грузчика по сей день остается наличие достаточной физической подготовки. По правилам техники безопасности, за один прием рабочий может перенести до 50 кг груза, а за смену длительностью 8 часов общий вес транспортируемых вещей достигает 4 тонн.

Существует распространенное мнение о частых травмах среди грузчиков, но, как и во многих других профессиях, при соблюдении техники безопасности и грамотном распределении веса травмирующих ситуаций не происходит. Кроме того, вполне вероятно, что с развитием технологий с рабочих удастся снять часть физической нагрузки. Например, уже довольно давно на заводах Panasonic в Японии для грузчиков разрабатывают экзоскелеты, которые на 15 кг снижают нагрузку на спину при поднятии тяжестей.

Звездная профессия

С трудностями профессии грузчика не понаслышке знакомы и некоторые известные личности. Актер Дмитрий Нагиев какое-то время проработал грузчиком сначала на почте, а затем в хлебном отделе универмага. Экс-президенты Киргизии и Чехословакии Курманбек Бакиев и Вацлав Гавел также в молодости занимались переноской грузов. Порой грузчики становились героями художественных произведений. Так, в песне Money for Nothing группы Dire Straits повествование ведется от лица рабочего магазина электроники, которому приходится доставлять, переносить и устанавливать технику, а писатель Артур Миллер в своей пьесе «Вид с моста» описывал жизнь докеров. Специальность портового грузчика привлекла и Аарона Кауфмана, бывшего механика мастерской Gas Monkey из проекта «Быстрые и громкие» на Discovery Channel, а что из этого получится — вы узнаете 12 ноября в 22:00 (мск). Также смотрите в программе «Крутая работа Аарона Кауфмана», как он осваивает инженерию больших механизмов в агентстве NASA, пробует работать в пожарной службе, в угольной шахте, на грузовом корабле и в других необычных местах. Увидеть, удастся ли Аарону добиться успехов в новых амплуа, можно по вторникам в то же время на телеканале Discovery.

Написание загрузчика | webpack

Загрузчик – это модуль узла, который экспортирует функцию. Эта функция вызывается, когда ресурс должен быть преобразован этим загрузчиком. Данная функция будет иметь доступ к API загрузчика, используя предоставленный ей контекст и .

Настройка

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

Чтобы протестировать отдельный загрузчик, вы можете использовать путь от до разрешить локальный файл в объекте правила:

webpack.config.js

  const path = require ('path');

module.exports = {
  
  модуль: {
    правила: [
      {
        тест: /\.js$/,
        использовать: [
          {
            загрузчик: path.resolve ('путь / к / loader.js'),
            параметры: {
              
            },
          },
        ],
      },
    ],
  },
};  

Чтобы протестировать несколько, вы можете использовать конфигурацию resolveLoader.modules , чтобы обновить, где webpack будет искать загрузчики. Например, если в вашем проекте был локальный каталог / loaders :

webpack.config.js

  const path = require ('path');

module.exports = {
  
  resolveLoader: {
    модули: ['node_modules', path.resolve (__ dirname, 'loaders')],
  },
};  

Кстати, если вы уже создали отдельный репозиторий и пакет для своего загрузчика, вы можете npm связать его с проектом, в котором вы хотите его протестировать.

tip

Вы можете использовать пакет webpack-defaults для генерации шаблонного кода, необходимого для начала написания загрузчика.

Простое использование

Когда к ресурсу применяется один загрузчик, он вызывается только с одним параметром – строкой, содержащей содержимое файла ресурса.

Синхронные загрузчики могут возвращать единственное значение, представляющее преобразованный модуль. В более сложных случаях загрузчик может вернуть любое количество значений с помощью функции this.callback (err, values ​​...) . Ошибки либо передаются в функцию this.callback , либо загружаются в загрузчик синхронизации.

Ожидается, что загрузчик вернет одно или два значения. Первое значение – это результирующий код JavaScript в виде строки или буфера. Второе необязательное значение – SourceMap как объект JavaScript.

Сложное использование

Когда несколько загрузчиков связаны в цепочку, важно помнить, что они выполняются в обратном порядке – справа налево или снизу вверх в зависимости от формата массива.

  • Последнему загрузчику, вызываемому первым, будет передано содержимое необработанного ресурса.
  • Ожидается, что первый загрузчик, вызываемый последним, вернет JavaScript и дополнительную карту источников.
  • Промежуточные загрузчики будут выполнены с результатами предыдущего загрузчика в цепочке.

В следующем примере загрузчику foo-loader будет передан необработанный ресурс, а загрузчику bar-loader будет получен вывод foo-loader , и он вернет окончательный преобразованный модуль и исходную карту, если это необходимо. .

веб-пакет.config.js

  module.exports = {
  
  модуль: {
    правила: [
      {
        тест: /\.js/,
        используйте: ['bar-loader', 'foo-loader'],
      },
    ],
  },
};  

Указания

При написании загрузчика следует соблюдать следующие указания. Они упорядочены по важности, и некоторые из них применимы только в определенных сценариях. Для получения дополнительной информации прочтите подробные разделы, которые следуют ниже.

  • Держите их простыми .
  • Использовать цепочку .
  • Излучить модульный выход .
  • Убедитесь, что они без гражданства .
  • Использовать утилиты погрузчика .
  • Отметить зависимости загрузчика .
  • Разрешить зависимости модуля .
  • Извлечь общий код .
  • Избегайте абсолютных путей .
  • Использовать одноранговых зависимостей .

Простой

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

Объединение в цепочку

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

Возьмем случай визуализации файла шаблона с данными, указанными с помощью опций загрузчика или параметров запроса. Его можно было бы написать как отдельный загрузчик, который компилирует шаблон из источника, выполняет его и возвращает модуль, который экспортирует строку, содержащую HTML-код.Однако, в соответствии с рекомендациями, существует application-loader , который может быть связан с другими загрузчиками с открытым исходным кодом:

  • pug-loader : преобразовать шаблон в модуль, который экспортирует функцию.
  • apply-loader : выполняет функцию с параметрами загрузчика и возвращает необработанный HTML.
  • html-loader : принимает HTML и выводит действующий модуль JavaScript.
tip

Тот факт, что загрузчики могут быть связаны в цепочку, также означает, что они не обязательно должны выводить JavaScript.Пока следующий загрузчик в цепочке может обрабатывать его выходные данные, загрузчик может возвращать любой тип модуля.

Модульный

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

Stateless

Убедитесь, что загрузчик не сохраняет состояние между преобразованиями модуля. Каждый запуск всегда должен быть независимым от других скомпилированных модулей, а также от предыдущих компиляций того же модуля.

Утилиты загрузчика

Воспользуйтесь преимуществами пакета loader-utils .Он предоставляет множество полезных инструментов, но одним из наиболее распространенных является получение параметров, переданных загрузчику. Наряду с loader-utils , пакет schema-utils должен использоваться для согласованной проверки параметров загрузчика на основе схемы JSON. Вот краткий пример, в котором используются оба:

loader.js

  import {getOptions} from 'loader-utils';
импортировать {проверить} из 'schema-utils';

const schema = {
  тип: 'объект',
  характеристики: {
    тестовое задание: {
      тип: 'строка',
    },
  },
};

функция экспорта по умолчанию (источник) {
  const options = getOptions (это);

  проверить (схема, параметры, {
    name: 'Пример загрузчика',
    baseDataPath: 'параметры',
  });

  

  вернуть `экспорт по умолчанию $ {JSON.stringify (источник)} `;
}  

Зависимости загрузчика

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

loader.js

  путь импорта из «path»;

функция экспорта по умолчанию (источник) {
  var callback = this.async ();
  var headerPath = path.resolve ('header.js');

  this.addDependency (headerPath);

  fs.readFile (headerPath, 'utf-8', function (err, header) {
    if (err) вернуть обратный вызов (err);
    обратный вызов (null, заголовок + '\ n' + источник);
  });
}  

Зависимости модуля

В зависимости от типа модуля для указания зависимостей может использоваться другая схема. В CSS, например, используются операторы @import и url (...) . Эти зависимости должны разрешаться модульной системой.

Это можно сделать одним из двух способов:

  • Путем преобразования их в требуется операторов.
  • Использование функции this.resolve для разрешения пути.

css-loader – хороший пример первого подхода. Он преобразует зависимости в , требуется с, путем замены операторов @import на требуется для другой таблицы стилей и url (...) на требует для указанного файла.

В случае less-loader он не может преобразовать каждый @import в require , потому что все файлы .less должны быть скомпилированы за один проход для переменных и отслеживания микширования. Таким образом, less-loader расширяет компилятор less с помощью настраиваемой логики разрешения пути. Затем он использует второй подход, this.resolve , для разрешения зависимости через webpack.

подсказка

Если язык принимает только относительные URL-адреса (например,грамм. url (файл) всегда ссылается на ./file ), вы можете использовать соглашение ~ , чтобы указать ссылки на установленные модули (например, те, что в node_modules ). В случае url это будет выглядеть примерно как url ('~ some-library / image.jpg') .

Общий код

Избегайте генерации общего кода в каждом модуле, который обрабатывает загрузчик. Вместо этого создайте файл времени выполнения в загрузчике и сгенерируйте require для этого общего модуля:

src / loader-runtime.js

  const {someOtherModule} = require ('./ some-other-module');

module.exports = время выполнения функции (параметры) {
  const x = params.y * 2;

  вернуть someOtherModule (params, x);
};  

src / loader.js

  импортировать среду выполнения из './loader-runtime.js';

загрузчик функций по умолчанию для экспорта (исходный код) {
  

  return `$ {runtime ({
    источник,
    y: Math.random (),
  })} `;
}  

Абсолютные пути

Не вставляйте абсолютные пути в код модуля, поскольку они нарушают хеширование при перемещении корня проекта.В loader-utils есть метод stringifyRequest , который можно использовать для преобразования абсолютного пути в относительный.

Peer Dependencies

Если загрузчик, над которым вы работаете, представляет собой простую оболочку для другого пакета, вам следует включить этот пакет как peerDependency . 4.0,0 ” } }

Тестирование

Итак, вы написали загрузчик, следовали приведенным выше инструкциям и настроили его для локального запуска. Что дальше? Давайте рассмотрим пример модульного тестирования, чтобы убедиться, что наш загрузчик работает так, как мы ожидаем. Для этого мы будем использовать фреймворк Jest. Мы также установим babel-jest и некоторые предустановки, которые позволят нам использовать import / export и async / await . Начнем с установки и сохранения их как devDependencies :

  npm install --save-dev jest babel-jest @ babel / core @ babel / preset-env  

babel.config.js

  module.exports = {
  предустановки: [
    [
      '@ babel / preset-env',
      {
        target: {
          узел: 'текущий',
        },
      },
    ],
  ],
};  

Наш загрузчик обработает файлов .txt и заменит любой экземпляр [имя] параметром name , заданным загрузчику. Затем он выведет действительный модуль JavaScript, содержащий текст в качестве экспорта по умолчанию:

src / loader.js

  import {getOptions} from 'loader-utils';

загрузчик функций по умолчанию для экспорта (исходный код) {
  const options = getOptions (это);

  источник = источник.replace (/ \ [name \] / g, options.name);

  вернуть `экспорт по умолчанию $ {JSON.stringify (источник)}`;
}  

Мы будем использовать этот загрузчик для обработки следующего файла:

test / example.txt

  Привет, [имя]!  

Обратите особое внимание на этот следующий шаг, поскольку мы будем использовать API Node.js и memfs для выполнения webpack. Это позволяет нам избежать вывода на диск и даст нам доступ к данным stats , которые мы можем использовать для получения преобразованного модуля:

  npm install --save-dev webpack memfs  

test / compiler .js

  путь импорта из 'path';
импортировать webpack из webpack;
импортировать {createFsFromVolume, Volume} из memfs;

экспорт по умолчанию (прибор, опции = {}) => {
  const compiler = webpack ({
    контекст: __dirname,
    запись: `./$ {fixture}`,
    выход: {
      путь: path.resolve (__ dirname),
      имя файла: 'bundle.js',
    },
    модуль: {
      правила: [
        {
          тест: /\.txt$/,
          использовать: {
            загрузчик: path.resolve (__ dirname, '../src/loader.js'),
            параметры,
          },
        },
      ],
    },
  });

  компилятор.outputFileSystem = createFsFromVolume (новый том ());
  compiler.outputFileSystem.join = path.join.bind (путь);

  вернуть новое обещание ((разрешить, отклонить) => {
    compiler.run ((ошибка, статистика) => {
      если (ошибка) отклонить (ошибка);
      если (stats.hasErrors ()) отклонить (stats.toJson (). errors);

      разрешение (статистика);
    });
  });
};  
tip

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

И теперь, наконец, мы можем написать наш тест и добавить скрипт npm для его запуска:

test / loader.test.js

 
импортировать компилятор из './compiler.js';

test ('Вставляет имя и выводит JavaScript', async () => {
  const stats = await compiler ('example.txt', {name: 'Алиса'});
  константный вывод = stats.toJson ({источник: истина}). модули [0]. источник;

  ожидать (вывод) .toBe ('экспорт по умолчанию «Привет, Алиса! \\ n»');
});  

package.json

  {
  "scripts": {
    "тест": "шутка"
  },
  "шутка": {
    "testEnvironment": "узел"
  }
}  

Когда все готово, мы можем запустить его и посмотреть, проходит ли наш новый загрузчик тест:

  PASS test / loader.test.js
  ✓ Вставляет имя и выводит JavaScript (229 мс)

Наборы тестов: 1 пройден, всего 1
Тесты: 1 сдан, всего 1
Снимки: всего 0
Время: 1,853 с, расчетное 2 с
Прогнал все наборы тестов.  

Сработало! На этом этапе вы должны быть готовы начать разработку, тестирование и развертывание собственных загрузчиков. Мы надеемся, что вы поделитесь своими творениями с остальным сообществом!

Я впервые пишу загрузчик Webpack | Яш Кульшреста | Netscape

По мере того, как мы приближаемся к более крупным проектам Javascript, нам нужно добавлять все больше и больше файлов в наш индекс .html . Один из способов управления всеми файлами - автоматическое добавление списка файлов на главную страницу. Другой способ - использовать инструмент упаковки, такой как Webpack, и упаковать весь исходный код в один файл. Это также дает дополнительное преимущество в виде оптимизации сетевых вызовов и скорости загрузки.

Webpack, сразу после установки упаковывает весь исходный код в один файл и выводит пакет, но он также имеет большую экосистему загрузчиков и активное сообщество разработчиков загрузчиков. Нужна поддержка ESNext? Просто добавьте babel-loader , и все готово.Webpack также может обрабатывать файлы, отличные от кода Javascript, такие как файлы HTML, CSS, SASS, шрифты, изображения и даже уценку, если вы используете правильный загрузчик.

Да, Webpack - это 🔥.

Эта экосистема загрузчика делает Webpack действительно мощным. Проще говоря, загрузчик - это фрагмент кода, который используется для расширения или создания конвейера обработки для определенного расширения файла. Например, мы можем использовать загрузчик изображений , чтобы позволить Webpack обрабатывать изображения, и мы можем использовать вышеупомянутый загрузчик babel-loader для обработки ESNext Javascript и преобразования его в код, который работает в большом диапазоне браузеров, при этом все еще имея возможность использовать новейшие функции, которые поставляются с новыми стандартами ECMAScript.

На GitHub есть длинный список загрузчиков, в который входят загрузчики общего назначения, такие как css-loader , который может добавлять стили CSS в пакет Webpack для более конкретных загрузчиков, таких как vue-loader , который помогает упаковывать Webpack. Компоненты Vue.js. Эти загрузчики и делают Webpack действительно мощным, но что, если мы хотим стать еще более конкретными, может быть, нам нужен Webpack для внутреннего корпоративного процесса или у нас есть идея, которая еще не существует в качестве загрузчика? Вы можете сделать свой загрузчик!

Немного предыстории, прежде чем я перейду к загрузчику, который я написал.Чтобы получить любой код AngularJS, упакованный через Webpack, у вас должен быть способ вставить шаблоны в код Javascript. В Angular уже есть способ сделать это в виде службы под названием $ templateCache . Все, что вам нужно предоставить, это строка, представляющая собой имя шаблона, и шаблон, считанный из файла, также в строковой форме. Существует загрузчик под названием ngtemplate-loader , который берет шаблоны AngularJS и помещает их в $ templateCache .Вам просто нужно внести изменения во все файлы с шаблоном, а require () шаблон, прежде чем сообщать об этом AngularJS.

Вот где я увидел возможность. Что, если бы нам не нужно было редактировать каждый файл? Упомянутый мной ngtemplate-loader работает с файлами шаблонов HTML в вашем проекте AngularJS. Что, если бы мы написали загрузчик Webpack для работы с файлами Javascript, извлекли бы путь шаблона (сохраненный в ключе с именем templateUrl ), require () , а затем позволили бы ngtemplate-loader работать с HTML-файлами, обозначенными по тропинке? Это именно то, что я сделал.Я создал загрузчик под названием auto-ngtemplate-loader , который будет работать со всеми файлами Javascript, а автоматически требует во всех файлах шаблонов HTML. Нет необходимости в ручном редактировании! Он даже поддерживает несколько шаблонов в одном файле и изменяет имя переменной, в которой хранится шаблон, чтобы избежать конфликтов имен.

Webpack значительно упростил создание загрузчика. На веб-сайте Webpack есть хорошо задокументированное руководство по началу работы, которое проведет вас через настройку проекта загрузчика.Устройство загрузчика действительно довольно простое.

Вот и все! Мы только что создали загрузчик, который возвращает исходный код без изменений. Конечно, этот конкретный загрузчик не очень интересен, но он помогает проиллюстрировать простую структуру загрузчика. Вы получаете исходный код и исходную карту, передаваемую в ваш загрузчик. Вы делаете свою работу, а затем используете this.callback , чтобы сообщить Webpack, когда вы закончили и были ли ошибки. Мало того, этот объект в функции загрузчика имеет доступ ко всем API загрузчика Webpack.👍

Давайте напишем еще один загрузчик, но давайте сделаем все поинтереснее - на этот раз мы напишем загрузчик, который удаляет console.log операторов. Время мне.

Готово!

Следующий шаг - включить наш загрузчик в конфигурацию Webpack и посмотреть, как он работает. Загрузчики Webpack по сути создают конвейер обработки вашего кода, который оценивается в порядке, обратном его перечислению. Например, если наш загрузчик указан после babel-loader , наш загрузчик передаст свои результаты babel-loader .Исходный код , который мы передаем this.callback , затем передается в babel-loader в качестве аргумента.

Мой опыт на протяжении всего процесса разработки загрузчика был исключительным, и это лишь дань команде Webpack за создание простого для понимания и простого в использовании API для расширения Webpack. Кодовая база (с примерами) находится на Github здесь. Взгляните на код!

А теперь пришло время бесстыдной розетки.

Мой загрузчик называется auto-ngtemplate-loader .После включения (желательно последним в списке, чтобы он работал с неизмененным кодом) он просматривает файлы Javascript для ключа templateUrl и добавляет строку кода в верхнюю часть файла для каждого шаблона, который он найдет для импорта. это так, что ngtemplate-loader может поместить в AngularJS $ templateCache .

Если у вас большая кодовая база AngularJS и вы думаете о переходе на React или Angular, или даже если вы просто хотите получить поддержку ESNext, первый шаг, который вам нужно сделать, - это включить Webpack в свою сборку. auto-ngtemplate-loader может помочь облегчить некоторые проблемы, связанные с преобразованием большого проекта AngularJS на более новую технологию. Вы можете добавить auto-ngtemplate-loader в свою сборку, запустив npm install --save-dev auto-ngtemplate-loader . Он полностью задокументирован, и в репозитории есть примеры нескольких случаев, с которыми загрузчик справляется хорошо.

Вы можете найти пакет здесь, на npm, а код - здесь, на Github. Взносы всегда приветствуются. 💯

У меня возникла идея написать загрузчик, который автоматически требует сек в HTML-шаблонах в ваших файлах Javascript, чтобы Webpack мог загружать их в $ templateCache AngularJS.Я думал, что мне придется потратить несколько дней на тестирование, прежде чем я смогу заставить работать загрузчик Webpack, но благодаря отличной документации и руководствам от команды Webpack я был готов к работе примерно за 15 минут и сделал менее чем за половину рабочий день. Это был легкий ветерок; расширение Webpack так же просто, как и использование Webpack. Так бывает нечасто и достойно похвалы. Много ударов кулаками в порядке!

Если это вызвало у вас интерес к загрузчикам Webpack, я рекомендую вам поиграть с API загрузчика Webpack и посмотреть, что у вас получится.Если у вас есть большая кодовая база Javascript, которая использует AngularJS, рассмотрите возможность использования auto-ngtemplate-loader и, надеюсь, он сможет автоматизировать некоторые операции редактирования файлов и упростить переход.

boku7 / CobaltStrikeReflectiveLoader: пользовательский отражающий загрузчик Cobalt Strike, написанный на Assembly & C для расширенных возможностей уклонения.

GitHub - boku7 / CobaltStrikeReflectiveLoader: определяемый пользователем отражающий загрузчик Cobalt Strike, написанный на Assembly & C для расширенных возможностей уклонения.

Файлы

Постоянная ссылка Не удалось загрузить последнюю информацию о фиксации.

Тип

Имя

Последнее сообщение фиксации

Время фиксации

Cobalt Strike Пользовательский отражающий загрузчик, написанный на Assembly & C для расширенных возможностей уклонения.

Последнее обновление! (29.08.21)

  • Добавлена ​​функция NoRWX! Загрузчик Reflective записывает маяк с разрешениями на чтение и запись и после разрешения таблицы импорта и перемещений маяков изменяет раздел кода .TEXT файла Beacon на разрешения на чтение и выполнение.

Версии

  • Другая версия этого проекта определяемого пользователем отражающего загрузчика находится в папке версий
Версия Файл Описание
0.6 ReflectiveLoader-v0_6.c Добавлена ​​функция NoRWX! Загрузчик Reflective записывает маяк с разрешениями на чтение и запись и после разрешения таблицы импорта и перемещений маяков изменяет раздел кода .TEXT файла Beacon на разрешения на чтение и выполнение
0,5 ReflectiveLoader-v0_5.c Добавлен прямой системный вызов HellsGate и HalosGate, заменено выделение заглушек ASM, произведен рефакторинг кода и на ~ 500 байт меньше. Благодарим @ SEKTOR7net, джедая, создателя HalosGate и @smelly__vx & @ am0nsec, создателей / издателей техники Hells Gate! Благодарим @ ilove2pwn_ за рекомендацию удаления заглушек ASM! У меня нет их всех, но буду работать над этим 🙂
0.4 ReflectiveLoader-v0_4.c Шунты AMSI и ETW встроены в отражающий загрузчик. Можно отключить, прокомментировав строку #define BYPASS при компиляции. Благодарим @mariuszbit за отличную идею. Благодарим @_xpn_ + @offsectraining + @ ajpc500 за их исследование и код
0,3,1 ReflectiveLoader-v0_3_1.c Изменены строки с wchar на char и распакованы в unicode с регистрами MMX. Исправляет ошибку компиляции linux, обнаруженную @mariuszbit
0.3 ReflectiveLoader-v0_3.c Обфускация строк с использованием новой техники.
0,2 ReflectiveLoader-v0_2.c Проверяет загрузчик, чтобы увидеть, существует ли уже зависимая библиотека DLL, чтобы ограничить время вызова LoadLibrary (), настраиваемую функцию GetSymbolAddress для уменьшения количества вызовов GetProcAddress () и рефакторинг кода.
0,1 ReflectiveLoader-v0_1.c Это оригинальный загрузчик отражателей, созданный для этого проекта.Он включает примечания в файле C. Эта первоначальная версия была создана с целью исследования и обучения. В этой версии используются небольшие техники обфускации и уклонения.

Первоначальные цели проекта

  • Узнайте, как работает Reflective Loader.
  • Напишите отражающий загрузчик в сборке.
  • Совместим с Cobalt Strike.
  • Кросс-компиляция из macOS / Linux.
  • Внедрить встроенную сборку в проект C.

Цели будущих проектов

  • Используйте исходный проект в качестве шаблона для более сложных методов уклонения, используя гибкость Assembly.
  • Внедрите такие параметры Cobalt Strike, как отсутствие RWX, StompPE, включение модуля, изменение заголовка MZ и т. Д.
  • Напишите достойный сценарий Aggressor.
  • Поддержка x86.
  • Есть разные версии отражающего загрузчика на выбор.
  • Реализуйте HellsGate / HalosGate для начальных вызовов, которые использует отражающий загрузчик (pNtFlushInstructionCache, VirtualAlloc, GetProcAddress, LoadLibraryA и т. Д.).
  • Оптимизировать ассемблерный код.
  • Хеширование / обфускация строк.
  • Какой-то оверлей на языке шаблонов, который может изменять / рандомизировать регистры / методы.

Использование

  1. Запустите сервер Cobalt Strike Team с профилем или без него
 #### Этот профиль ниже не является обязательным, но это профиль, который я тестировал этот отражающий загрузчик с ####
# Установите Go на Kali, если вам это нужно
sudo apt install golang-go -y
# Создание профиля Team Server Cobalt Strike с помощью SourcePoint
## Клонировать проект SourcePoint
git clone https: // github.ru / Tylous / SourcePoint.git
## Сборка проекта SourcePoint Go
cd SourcePoint
перейти на сборку SourcePoint.go
## Запустите его с некоторыми классными флагами (см. Меню справки для получения дополнительной информации)
### Это настройки, с которыми я тестировал UD Reflective Loader.
./SourcePoint -PE_Clone 18 -PostEX_Name 13 -Sleep 3 -Profile 4 -Outfile myprofile.profile -Host  -Injector NtMapViewOfSection
## Запустить Team Server
CD ../
sudo ./teamserver  'T3 @ Ms3Rv3Rp @ $$ w0RD' SourcePoint / myprofile.profile 
  1. Перейдите в графический интерфейс Cobalt Strike и импортируйте файл rdll_loader.cna Agressor скрипт.
  2. Создайте полезную нагрузку x64 (Атаки -> Пакеты -> Исполняемый файл Windows (S))
  • Не поддерживает вариант x86. Корзина x86 - это исходный объектный файл Reflective Loader.
  1. Используйте консоль сценариев, чтобы убедиться, что маяк успешно создан с помощью этого определяемого пользователем отражающего загрузчика
  • В случае успеха вывод в консоли сценариев будет выглядеть следующим образом:

Build (На данный момент тестируется только в macOS)

  1. Запустите файл compile-x64.сценарий оболочки sh после установки необходимых зависимостей
 # Установите brew на macOS, если он вам нужен (https://brew.sh/)
/ bin / bash -c "$ (curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Установите Ming с помощью Brew
варить установить mingw-w64
# Клонировать этот проект Reflective DLL из репозитория github
git clone https://github.com/boku7/CobaltStrikeReflectiveLoader.git
# Скомпилируйте файл объекта ReflectiveLoader
cd CobaltStrikeReflectiveLoader /
кошка compile-x64.sh
x86_64-w64-mingw32-gcc -c ReflectiveLoader.c -o ./bin/ReflectiveLoader.x64.o -shared -masm = intel
bash compile-x64.sh 
  1. Следуйте инструкциям по использованию

Источники / Ссылки

Погрузчик с отражателем

HalosGate SysCaller

  • Reenz0h из @ SEKTOR7net
    • Большинство техник C, которые я использую, взяты из замечательных курсов и блогов Reenz0h
    • Лучшие классы для разработки вредоносных программ.
    • Создатель техники воротных ореолов. Его работа была мотивацией для этой работы.
    • Sektor7 Блог HalosGate

Системный вызов HellsGate

  • @smelly__vx & @ am0nsec (Создатели / издатели техники Hells Gate)

Cobalt Strike Пользовательский отражающий загрузчик

Большой ресурс для изучения Intel ASM

Обход ETW и AMSI

Реализация ASM в коде C с GCC

Генератор профиля Cobalt Strike C2

Около

Определяемый пользователем отражающий загрузчик Cobalt Strike, написанный на Assembly & C, для расширенных возможностей уклонения.

ресурсов

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

pyrsmk / toast: современный загрузчик ресурсов JS / CSS, написанный на TypeScript.

Toast - это загрузчик JS / CSS на основе обещаний для браузера.Он направлен на оптимизацию производительности веб-сайта за счет асинхронной загрузки ваших ресурсов.

Краткое примечание о поддержке IE9 / 10

Поддержка этих браузеров прекращена, поскольку Mocha / Sinon (который используется для запуска наших тестов) больше не поддерживает их. Поскольку для переноса тестов потребуется некоторое время, IE9 / 10 больше не поддерживается Microsoft и его доля на рынке упала ниже 1%, мы также приняли решение прекратить нашу поддержку.

В настоящее время Toast 3.0.2 будет работать с IE9 / 10. Поскольку код не должен сильно развиваться, вы должны быть в безопасности в далеком будущем, пока Toast не достигнет критических изменений.

Toast проверяется на:

  • Chrome 83 (более старая версия тоже должна быть хорошей)
  • Firefox 76 (более старая версия тоже должна подойти)
  • Edge 83 (старая версия тоже должна быть хорошей)
  • Safari 11-13
  • IE11
  • Android 4.4-10
  • iOS 10–13

Создание

Предпочтительный способ загрузки тоста в ваше приложение - установить его через NPM (или Yarn) и импортировать его прямо в кодовую базу (он занимает очень мало места, и чем раньше он загрузится, тем лучше).

У вас есть несколько вариантов загрузки его в код в зависимости от среды приложения:

  • , вставив его в тег

    Обязательно используйте последнюю версию Toast и сохраните фиксированную версию в производственной среде (чтобы избежать критических изменений).

    API

     toast.css (url: string): обещание
    toast.js (url: string): Обещание
    toast.all (urls: string []): Promise 

    Примеры

     if (dark_mode === true) {
        toast.css ('стили / dark.css')
    } еще {
        toast.css ('стили / свет.css')
    } 
     const handleErrors = error => {
        консоль.журнал (ошибка)
    }
    
    toast.js ('http://some.cdn.com/jquery.js')
        .then (() => {
            toast.js ('http://some.cdn.com/jquery-myplugin.js')
                .then (() => $ ('. someClass'). myPlugin ())
                .catch (handleErrors)
            })
        })
        .catch (handleErrors) 
     await toast.all ([
        'assets / css / styles1.css',
        'assets / js / script1.js',
        'assets / js / script2.js',
        'assets / css / styles2.css',
        'assets / js / script3.js',
    ])
    console.log ('Все загружено, ура!') 

    тост.все полагаются на автоматическое определение расширений. Если ваш URL-адрес не содержит расширения файла, вам нужно будет использовать Promise.all и проделать дополнительную работу:

     await Promise.all ([
        toast.css ('активы / css / styles1'),
        toast.js ('активы / js / script1'),
        toast.js ('активы / js / script2'),
        toast.css ('активы / css / styles2'),
        toast.js ('активы / js / script3'),
    ])
    console.log ('Все загружено, ура!') 

    Совместимость с браузером

    • Поддержка IE10 (и ранее) была удалена, поскольку она больше не поддерживается Microsoft, и их доля на рынке упала ниже 1%
    • Toast использует встроенные обещания, поэтому, если вам нужно поддерживать I11, вы должны добавить библиотеку обещания-polyfill перед загрузкой тоста: вот таблица совместимости для функции Promise
    • для вашей информации, IE11 и Edge никогда не запускают событие error при загрузке CSS, если что-то пойдет не так; имейте это в виду, когда вы используете catch prom block
    • , если вы хотите узнать больше о поддержке функций узла SCRIPT / LINK , вы можете взглянуть на эту таблицу совместимости

    Развитие

    Установите зависимости с помощью:

    И создайте библиотеку с помощью:

    Посмотрите скрипты в пакете .json для получения дополнительных сведений.

    Тестирование

    Тесты написаны с использованием Mocha и Sinon, и их можно запускать с помощью:

    Должен открыться ваш браузер по умолчанию (под рабочим столом Gnome). Если нет, просто перетащите tests / index.html в предпочитаемый браузер.


    Эти тесты предназначены только для локальной отладки на этапе разработки, но они должны пройти тесты Karma. Karma - это инструмент для выполнения модульных тестов в удаленных браузерах с помощью Selenium / Appium.Чтобы иметь возможность запускать их, вам понадобится учетная запись в BrowserStack. Это единственная служба, у которой есть бесплатный тарифный план для проектов с открытым исходным кодом.

    Когда ваша учетная запись будет готова, вы должны подготовить свою среду, установив глобальные переменные в файле, который загружается при инициализации вашей консоли, например .bashrc , .zshrc или .profile :

    • перейти на страницу автоматизации
    • отобразите ваш КЛЮЧ ДОСТУПА (он доступен справа от строки поиска)
    • установите переменные env следующим образом:
       экспорт BROWSERSTACK_USERNAME = "<имя_пользователя>"
      экспорт BROWSERSTACK_ACCESS_KEY = "" 

    Затем запустите тесты кармы с:

    Результаты будут отображаться в консоли и на странице автоматизации вашей учетной записи.

    Если вы хотите запускать тесты только в определенном браузере, вы можете использовать одну из следующих команд:

     нпм запустить карма: хром
    npm запустить карму: firefox
    npm запустить карму: safari13
    npm запустить карму: safari12
    npm запустить карму: safari11
    npm запустить карму: край
    npm запустить карму: ie11
    npm запустить карму: android10
    npm запустить карму: android9
    npm запустить карму: android8
    npm запустить карму: android7
    npm запустить карму: android6
    npm запустить карму: android5
    npm запустить карму: android44
    npm run karma: ios13
    npm run karma: ios12
    npm запустить карму: ios11
    npm run karma: ios10 

    Примечание: я не знаю почему, но тесты могут быть нестабильными на некоторых виртуальных машинах при параллельном запуске всех тестов Karma; не стесняйтесь повторно запускать тесты на конкретной виртуальной машине для проверки.

    Лицензия

    MIT.

    Вредоносное ПО с использованием нового загрузчика памяти Ezuri

    Этот блог написали Офер Каспи и Фернандо Мартинес из AT&T Alien Labs

    Несколько злоумышленников недавно начали использовать инструмент на языке Go (Golang), чтобы действовать как упаковщик и избегать обнаружения антивирусов. Кроме того, средство загрузки памяти Ezuri действует как загрузчик вредоносных программ и выполняет свои полезные данные в памяти, не записывая файл на диск. Хотя этот метод известен и широко используется вредоносными программами для Windows, он менее популярен в среде Linux.

    Загрузчик расшифровывает вредоносное ПО и запускает его с помощью memfd create (как описано в этом блоге в 2018 году). При создании процесса система возвращает файловый дескриптор анонимному файлу в '/ proc / PID / fd /', который виден только в файловой системе.

    На рис. 1 показан фрагмент кода загрузчика, содержащий информацию, которую он использует для расшифровки полезной нагрузки с помощью алгоритма AES.

    Рис. 1. Фрагмент кода загрузчика, полученный при анализе Alien Labs.

    Загрузчик, написанный на Golang, взят из кода "Ezuri" на GitHub через пользователя guitmz. Первоначально этот пользователь создал загрузчик ELF примерно в марте 2019 года, когда он написал блог о технике запуска исполняемых файлов ELF из памяти и поделился загрузчиком на своем github. Кроме того, аналогичный пользователь TMZ (предположительно связанный с ранее упомянутым guitmz) разместил этот же код в конце августа на небольшом форуме, где делятся образцами вредоносных программ.

    Пользователь guitmz даже запустил тесты против VirusTotal, чтобы доказать эффективность кода, загрузив обнаруженный Linux.Образец Cephei (35308b8b770d2d4f78299262f595a0769e55152cb432d0efc42292db01609a18) с 30/61 обнаружениями AV в VirusTotal, по сравнению с нулевым обнаружением AV в том же образце, скрытом с помощью кода Ezuri (ddbbf7c514df2ddbfcf2c5d05e4e08e05e08e4f6f6e5f6f6d5d05e6f6d05b5b5b5f6d05b5b5b5b5b5b5b5b5b5b5b5

    Поток выполнения загрузчика состоит в том, чтобы сначала расшифровать полезную нагрузку, а затем выполнить ее из памяти (рисунок 2):

    Рис. 2. Поток выполнения, полученный из анализа Alien Labs.

    Гитмз дал этому образцу имя Эзури, вероятно, в честь одноименной карты из карточной игры «Magic: The Gathering.Эта карта имеет возможность «регенерировать другого целевого эльфа», что отражает способность вредоносной программы загружать и выполнять файл ELF в памяти.

    Обзор кода

    Команда AT&T Alien Labs получила доступ к загруженному Guitmz кода для анализа. Инструмент написан на Golang и интуитивно понятен в использовании. При выполнении он сначала запрашивает путь к полезной нагрузке, которая будет зашифрована, а также пароль, который будет использоваться для шифрования AES. Если пароль не указан, инструмент генерирует его, который используется для сокрытия вредоносного ПО в загрузчике.После ввода пользователя упаковщик компилирует загрузчик с зашифрованной внутри него полезной нагрузкой, чтобы ее можно было расшифровать и запустить в памяти, как только она будет помещена в систему жертвы.

    На рисунке 4 показана основная функция исполняемого файла, где файл сначала дешифруется с помощью « aesDec» , а затем запускается в памяти с помощью « runFromMemory» .

    На рисунке 3 показана основная функция Эзури, полученная из анализа Alien Labs.

    На рисунке 4 показана функция « runFromMemory », используемая для выполнения полезной нагрузки в памяти без размещения обнаруживаемой вредоносной программы на диске.

    На рисунке 4 показана функция Ezuri runFromMemory, полученная из анализа Alien Labs.

    Чтобы использовать инструмент, пользователю будет предложено ввести файл, который нужно скрыть, с именем целевого процесса, а также с дополнительным ключом AES для шифрования (рисунок 5):

    На рисунке 5 показано выполнение Эзури, полученное из анализа Alien Labs.

    TeamTNT

    AT&T Alien Labs за последние несколько месяцев выявила нескольких авторов вредоносных программ, использующих загрузчик Ezuri, в том числе TeamTNT , , который был идентифицирован первым.TeamTNT - это киберпреступная группа, действующая как минимум с апреля 2020 года, когда о них впервые сообщила охранная компания Trend Micro. Основное внимание группы уделяется системам Docker с неправильной конфигурацией, а также незащищенным и открытым API-интерфейсам управления для последующей установки DDoS-ботов и криптомайнеров в зараженные системы.

    Через несколько месяцев после отчета Trend Micro, в августе 2020 года, Cado Security обнаружила новые разработки в группе TeamTNT. В октябре 2020 года подразделение Palo Alto Networks Unit42 обнаружило новые варианты вредоносного ПО для майнинга, которое использует TeamTNT под названием Black-T.В этом образце сначала устанавливаются три сетевых сканера, а затем выполняется проверка памяти в попытке получить учетные данные любого типа, находящиеся в памяти. Кроме того, Unit42 обнаружил несколько немецкоязычных строк в некоторых сценариях TNT.

    Последний образец, идентифицированный Palo Alto Networks Unit42, на самом деле является загрузчиком Ezuri. Расшифрованная полезная нагрузка представляет собой файл ELF, упакованный с помощью UPX, который является известным образцом из TeamTNT, впервые представленным в июне 2020 года (e15550481e89dbd154b875ce50cc5af4b49f9ff7b837d9ac5b5594e5d63966a3).

    Методы и сходства кода между оригинальным инструментом, названным Ezuri, и тем, который недавно использовался TeamTNT, огромны. Наиболее очевидной из них является строка ezuri в скомпилированном двоичном коде (рисунок 6):

    На рисунке 6 показана строка Ezuri в образце TeamTNT, полученном в результате анализа Alien Labs.

    При использовании этого упаковщика обнаружение антивируса (AV) резко падает. Глядя на обнаружение вредоносных программ TeamTNT перед использованием упаковщика Ezuri (b494ca3b7bae2ab9a5197b81e928baae5b8eac77dfdc7fe1223fee8f27024772), мы видим 28/62 обнаружений вредоносного ПО до 28/62 обнаружений вредоносного ПО, в то время как версия, упакованная Ezuri (751014ec0158c78cd2198d648d888c8c8c8c898d888d888d898d888d888d888d888d888d888d888d888d888d88d8

    Помимо TeamTNT, было обнаружено несколько образцов Gafgyt (популярное вредоносное ПО для устройств Интернета вещей с целью DDoS-атак).

    Заключение

    Несколько авторов вредоносных программ использовали инструмент Golang с открытым исходным кодом в качестве загрузчика вредоносных программ, используя известную технику для загрузки двоичных файлов ELF в память и избегания использования легко обнаруживаемых файлов на диске. Авторы используют инструмент с открытым исходным кодом Ezuri, чтобы загрузить ранее обнаруженные полезные нагрузки и избежать обнаружения антивируса в файле.

    Методы обнаружения

    Alien Labs использует следующие связанные методы обнаружения. Читатели могут использовать их для настройки или развертывания средств обнаружения в своей среде или для помощи в дополнительных исследованиях.

    ПРАВИЛА ЯРА

    rule EzuriLoader: LinuxMalware {
    
        мета:
    
            author = "AT&T Alien Labs"
    
            type = "вредоносное ПО"
    
            description = "Обнаруживает загрузчик Эзури Голанга."
    
            copyright = "AT&T Cybersecurity 2020"
    
            reference = "283e0172063d1a23c20c6bca1ed0d2bb"
    
    
        струны:
    
            $ a1 = "ezuri / stub / main.go"
    
            $ a2 = "main.runFromMemory"
    
            $ a3 = "main.aesDec"
    
    
        состояние:
    
            uint32 (0) == 0x464c457f и
    
            размер файла <20 МБ и все ($ a *)
    
    } 
    rule EzuriLoaderOSX: OSXMalware {
    
        мета:
    
            author = "AT&T Alien Labs"
    
            type = "вредоносное ПО"
    
            description = "Обнаруживает загрузчик Эзури Голанга."
    
            copyright = "AT&T Cybersecurity 2020"
    
            reference = "da5ae0f2a4b6a52d483fb006bc9e9128"
    
    
        струны:
    
            $ a1 = "ezuri / stub / main.go"
    
            $ a2 = "main.runFromMemory"
    
            $ a3 = "main.aesDec"
    
            $ Go = "go.buildid"
    
    
        состояние:
    
            (uint32 (0) == 0xfeedface или
    
            uint32 (0) == 0xcefaedfe или
    
            uint32 (0) == 0xfeedfacf или
    
            uint32 (0) == 0xcffaedfe или
    
            uint32 (0) == 0xcafebabe или
    
            uint32 (0) == 0xbebafeca)
    
            и $ Go, размер файла <5 МБ и все ($ a *)
    
    } 

    Ассоциированные индикаторы (IOC)

    Следующие технические индикаторы связаны с сообщаемым интеллектом.Список индикаторов также доступен в OTX Pulse. Обратите внимание, что в пульс могут быть включены другие действия, связанные, но выходящие за рамки отчета.

    c81b4e6e52f5c41f

    ТИП

    ПОКАЗАТЕЛЬ

    ОПИСАНИЕ

    SHA256

    0a569366eeec52380b4462b455cacc9a788c2a7883b0a9965d20f0422dfc44df

    Капельница ELF Golang

    SHA256

    e1836676700121695569b220874886723abff36bbf78a0ec41cce73f72c52085

    Капельница OSX Golang

    SHA256

    e15550481e89dbd154b875ce50cc5af4b49f9ff7b837d9ac5b5594e5d63966a3

    Полезная нагрузка TeamTNT в упаковке

    SHA256

    0a569366eeec52380b4462b455cacc9a788c2a7883b0a9965d20f0422dfc44df

    Капельница ELF Golang

    SHA256

    35308b8b770d2d4f78299262f595a0769e55152cb432d0efc42292db01609a18

    Linux Cephei

    SHA256

    ddbb714157f2ef91c1ec350cdf1d1f5452

    f614

    Ezuri упакованный Linux Cephei

    SHA256

    b494ca3b7bae2ab9a5197b81e928baae5b8eac77dfdc7fe1223fee8f27024772

    Полезная нагрузка TeamTNT до Ezuri

    SHA256

    751014e0154d219dea8c2e999714c32fd98f817782588cd7af355d2488eb1c80

    Ezuri упаковал полезную нагрузку TeamTNT

    Список литературы

    Следующий список источников использовался авторами отчета в процессе сбора и анализа, связанного с этим разведывательным отчетом.

    1. https://web.archive.org/web/*/https://www.trendmicro.com/vinfo/hk-en/security/news/virtualization-and-cloud/coinminer-ddos-bot-attack- докер-демон-порты
    2. https://web.archive.org/web/20201110163424/https://www.cadosecurity.com/post/team-tnt-the-first-crypto-mining-worm-to-steal-aws-credentials
    3. https://web.archive.org/web/20201101092236/https://unit42.paloaltonetworks.com/black-t-cryptojacking-variant/
    4. https://web.archive.org/web/20201101055326/https://github.com / guitmz / ezuri
    5. https://web.archive.org/web/20200

      4802/https://www.guitmz.com/running-elf-from-memory/

    6. https://web.archive.org/web/20201106145814/https://evilop.codes/showthread.php?tid=71

    New Buer Malware Loader распространяется через мошенническое письмо DHL

    Цифровые злоумышленники используют поддельные электронные письма с доставкой DHL, чтобы обманом заставить получателей открыть вредоносный документ Microsoft Office. Согласно Proofpoint, мошенническое письмо DHL приводит к заражению RustyBuer, нового варианта семейства вредоносных программ Buer Loader, написанного на языке программирования Rust.

    Посмотрите, как эта перезапись Rust работает в пользу обработчиков Буэра.

    Мошеннические электронные письма DHL приносят новые покупатели в город

    Кампания использует фишинговые электронные письма на тему DHL для нацеливания на пользователей вредоносных документов Word и Excel. Эти файлы, которые прилагаются к электронным письмам, якобы сообщающим об обновлениях доставки DHL, вытеснили один из двух вариантов Buer Loader. Первый вариант был написан на C, а второй - на Rust. Вложения RustyBuer поставлялись с более подробным содержанием, чем у другого варианта, как средство более тщательного взаимодействия с получателями.

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

    После загрузки RustyBuer использовал файл ярлыка, чтобы установить постоянство при запуске. Затем в некоторых случаях он распространял маяк Cobalt Strike. Этот тип атаки позволит злоумышленникам закрепиться в сетях своих жертв.

    Назад к основам Буера

    Proofpoint рассудил, что авторы Buer Loader переписали свое вредоносное ПО для рассылки мошенников DHL в Rust по одной из двух причин.

    Во-первых, Rust становится все более популярным языком программирования, который имеет больше функций, чем C. Внесение таких изменений создает возможности для выпуска новых функций в будущем.

    Это ведет ко второй точке. Buer Loader существует уже некоторое время. Proofpoint впервые обнаружил цифровую угрозу на подпольном веб-рынке летом 2019 года. Тогда злоумышленники использовали ее для распространения вредоносных макросов, встроенных в документы Microsoft Word.В течение года Buer Loader стал жизнеспособной альтернативой Emotet и Trickbot’s Bazar, отмечает Sophos. В последующие месяцы вредоносное ПО также имитировало GlobalSign и DHL в атаках по электронной почте.

    Вся эта активность угроз предполагает, что охранные фирмы уже знают, на что обращать внимание, когда дело касается Buer. Переписывая свое творение на Rust, злоумышленники дают своему творению шанс уйти от обнаружения.

    Как защититься от мошенничества по электронной почте

    Вышеописанное мошенническое письмо DHL подчеркивает необходимость защиты организаций от атак Buer, передаваемых по электронной почте.Один из способов сделать это - инвестировать в обучающую программу по вопросам безопасности, охватывающую всех сотрудников. С помощью этой программы специалисты по безопасности могут проводить симуляции фишинга, знакомящие сотрудников с типами приманок, которые распространяют Buer Loader и другие вредоносные программы.

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

    Написание собственного загрузчика

    Недавно я смотрел «Предотвращение краха цивилизации» Джонатана Блоу - потрясающий доклад - и мне было любопытно, смогу ли я написать операционную систему с нуля. Итак, я немного погуглил и наткнулся на исчерпывающий учебник по ОС Карлоса Феноллосаса, который основан на очень хорошо написанной лекции «Написание простой операционной системы - с нуля».

    Итак, я поставил себе цель написать 32-битную операционную систему x86. Чтобы убедиться, что я действительно понял все детали, я решил написать в блоге о своем прогрессе. Итак, вот первое сообщение в блоге.

    Мы напишем простой загрузчик с нуля, используя язык ассемблера x86, и загрузим очень минимальное ядро ​​операционной системы, написанное на C. Для простоты мы будем использовать BIOS, а не связываться с UEFI.

    Пост имеет следующую структуру. Прежде чем мы перейдем к деталям, возможно, имеет смысл поискать некоторые вещи, чтобы иметь возможность следовать моим кратким объяснениям.Следовательно, следующие разделы содержат некоторые ключевые слова, которые вы можете прочитать. После этого мы будем поэтапно писать наш загрузчик. Затем мы реализуем наше минималистичное ядро, написанное на C. В последнем разделе мы соединим все вместе и загрузим нашу собственную операционную систему.

    Исходный код можно найти на GitHub.

    Чтобы этот пост был кратким, я собираюсь сосредоточиться на том, что является наиболее важным для достижения нашей цели. Это означает, что некоторые вещи останутся невыясненными.Однако, если вы потратите некоторое время на то, чтобы прочитать о них более подробно в ходе этого поста, вы сможете прекрасно следить за ними.

    Вот список тем, которые полезно знать / читать, чтобы понять содержание этого сообщения.

    Что касается инструментов, нам понадобится эмулятор (QEMU) для запуска нашей операционной системы, ассемблер x86 (NASM) для написания кода нашего загрузчика, а также компилятор C (gcc) и компоновщик (ld) для создания исполняемое ядро ​​операционной системы.Мы соединим все вместе с помощью GNU Make.

    На машине x86 BIOS выбирает загрузочное устройство, затем копирует первый сектор устройства в физическую память по адресу памяти 0x7C00. В нашем случае этот так называемый загрузочный сектор будет содержать 512 байт. Эти 512 байтов содержат код загрузчика, таблицу разделов, подпись диска, а также «магическое число», которое проверяется BIOS, чтобы избежать случайной загрузки того, что не должно быть загрузочным сектором. Затем BIOS инструктирует ЦП перейти к началу кода загрузчика, по сути передавая управление загрузчику.

    В этом руководстве нас интересует только код загрузчика, который запускает ядро ​​операционной системы. Это необходимо, потому что мы не сможем уместить всю операционную систему в 512 байт. Чтобы запустить наше ядро, загрузчик должен будет выполнить следующие задачи:

    1. Загрузка ядра с диска в память.
    2. Настройка глобальной таблицы дескрипторов (GDT).
    3. Переключение из 16-битного реального режима в 32-битный защищенный режим и передача управления ядру.

    Мы собираемся написать загрузчик на сборке x86 с использованием NASM. Ядро будет написано на C. Мы организуем код в несколько файлов, чтобы повысить удобочитаемость и модульность. Следующие файлы будут актуальны для минимальной настройки:

    • mbr.asm - главный файл, определяющий главную загрузочную запись (512-байтовый загрузочный сектор)
    • disk.asm содержит код для чтения с диска с помощью BIOS
    • gdt.asm устанавливает GDT
    • переключиться на 32-битную версию.asm содержит код для переключения в 32-битный защищенный режим
    • kernel-entry.asm содержит код ассемблера для передачи нашей основной функции в kernel.c
    • kernel.c содержит основную функцию ядра
    • Makefile связывает компилятор, компоновщик, ассемблер и эмулятор вместе, чтобы мы могли загрузить нашу операционную систему

    Следующий раздел посвящен написанию файлов, связанных с загрузчиком ( mbr.asm , disk.asm , gdt.asm и switch-to-32bit.asm ). После этого мы напишем ядро ​​и входной файл. Наконец, мы собираемся записать все вместе и попытаться загрузиться.

    Файл основной загрузочной записи

    Главный файл сборки для загрузчика содержит определение главной загрузочной записи, а также операторы include для всех соответствующих вспомогательных модулей. Давайте сначала взглянем на файл в целом, а затем обсудим каждый раздел в отдельности.

      [бит 16]
    [org 0x7c00]
    
    ; куда загрузить ядро
    KERNEL_OFFSET равно 0x1000
    
    ; BIOS устанавливает загрузочный диск в dl; хранить для дальнейшего использования
    mov [BOOT_DRIVE], dl
    
    ; стек установки
    mov bp, 0x9000
    mov sp, bp
    
    вызов load_kernel
    вызов switch_to_32bit
    
    jmp $
    
    % включают "disk.asm"
    % включают "gdt.asm"
    % include "switch-to-32bit.asm"
    
    [бит 16]
    load_kernel:
        mov bx, KERNEL_OFFSET; bx -> пункт назначения
        mov dh, 2; dh -> количество секторов
        mov dl, [BOOT_DRIVE]; dl -> диск
        вызов disk_load
        Ret
    
    [бит 32]
    BEGIN_32BIT:
        позвонить в KERNEL_OFFSET; передать управление ядру
        jmp $; цикл в случае возврата ядра
    
    ; переменная загрузочного диска
    BOOT_DRIVE db 0
    
    ; набивка
    умножить на 510 - ($ - $$) дБ 0
    
    ; магическое число
    dw 0xaa55
      
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Первое, на что следует обратить внимание, это то, что мы собираемся переключаться между 16-битным реальным режимом и 32-битным защищенным режимом, поэтому нам нужно указать ассемблеру, должен ли он генерировать 16-битные или 32-битные инструкции.Это можно сделать с помощью директив [бит 16] и [бит 32] соответственно. Мы начинаем с 16-битных инструкций, когда BIOS переходит к загрузчику, а процессор все еще находится в 16-битном режиме.

    В NASM директива [org 0x7c00] устанавливает счетчик местоположения ассемблера. Указываем адрес памяти, куда BIOS помещает загрузчик. Это важно при использовании меток, поскольку они должны быть переведены в адреса памяти при генерации машинного кода, и эти адреса должны иметь правильное смещение.

    Оператор KERNEL_OFFSET equ 0x1000 определяет константу ассемблера с именем KERNEL_OFFSET со значением 0x1000 , которое мы будем использовать позже при загрузке ядра в память и переходе к его точке входа.

    Перед вызовом загрузчика BIOS сохраняет выбранный загрузочный диск в регистре dl . Мы храним эту информацию в памяти внутри переменной BOOT_DRIVE , поэтому мы можем использовать регистр dl для чего-то еще без риска перезаписать эту информацию.

    Прежде чем мы сможем вызвать процедуру загрузки ядра, нам нужно настроить стек, установив регистры указателя стека sp (верх стека, растет вниз) и bp (нижняя часть стека). Мы поместим нижнюю часть стека в 0x9000 , чтобы убедиться, что мы достаточно далеко от другой памяти, связанной с загрузчиком, чтобы избежать коллизий. Стек будет использоваться, например, операторами call и ret для отслеживания адресов памяти при выполнении процедур сборки.

    Теперь пришло время поработать! Сначала мы вызовем процедуру load_kernel , чтобы дать BIOS команду загрузить ядро ​​с диска в память по адресу KERNEL_OFFSET . load_kernel использует нашу процедуру disk_load , которую мы напишем позже. Эта процедура принимает три входных параметра:

    1. Место в памяти для размещения считанных данных ( bx )
    2. Количество секторов для чтения ( dh )
    3. Диск для чтения ( dl )

    Как только мы закончим, мы вернемся к следующей инструкции call switch_to_32bit , которая вызывает другую вспомогательную процедуру, которую мы напишем позже.Он подготовит все необходимое для переключения в 32-битный защищенный режим, выполнит переключение и перейдет к метке BEGIN_32BIT , когда это будет сделано, эффективно передав управление ядру.

    На этом наш основной код загрузчика завершен. Чтобы сгенерировать действительную главную загрузочную запись, нам нужно добавить некоторое заполнение, заполнив оставшееся пространство 0 байтами умножить на 510 - ($ - $$) db 0 и магическое число dw 0xaa55 .

    Затем давайте посмотрим, как определяется процедура disk_load , чтобы мы могли читать наше ядро ​​с диска.

    Чтение с диска

    Чтение с диска довольно просто при работе в 16-битном режиме, так как мы можем использовать функциональность BIOS, отправляя прерывания. Без помощи BIOS нам пришлось бы напрямую взаимодействовать с устройствами ввода-вывода, такими как жесткие диски или дисководы гибких дисков, что значительно усложнило бы наш загрузчик.

    Чтобы читать данные с диска, нам нужно указать, где начать чтение, сколько читать и где хранить данные в памяти. Затем мы можем отправить сигнал прерывания ( int 0x13 ), и BIOS выполнит свою работу, считывая следующие параметры из соответствующих регистров:

    Регистр Параметр
    айх Режим (0x02 = чтение с диска)
    и Количество секторов для чтения
    шасси Цилиндр
    класс Сектор
    дирхам Голова
    дл Драйв
    es: bx Адрес памяти для загрузки (указатель адреса буфера)

    Если есть ошибки диска, BIOS установит бит переноса.В этом случае мы обычно должны показывать пользователю сообщение об ошибке, но поскольку мы не рассмотрели, как печатать строки, и мы не собираемся в этом посте, мы просто будем бесконечно зацикливаться.

    Давайте теперь посмотрим на содержимое disk.asm .

      disk_load:
        пуша
        толкнуть dx
    
        mov ah, 0x02; режим чтения
        mov al, dh; читать dh количество секторов
        mov cl, 0x02; начать с сектора 2
                     ; (поскольку сектор 1 - это наш загрузочный сектор)
        mov ch, 0x00; цилиндр 0
        mov dh, 0x00; голова 0
    
        ; dl = номер диска установлен как вход для disk_load
        ; es: bx = указатель буфера также устанавливается как ввод
    
        int 0x13; Прерывание BIOS
        jc disk_error; проверьте бит переноса на наличие ошибок
    
        pop dx; вернуть исходное количество секторов для чтения
        cmp al, dh; BIOS устанавливает 'al' равным количеству прочитанных секторов.
                   ; сравните его с 'dh' и выдайте ошибку, если они есть! =
        jne секторов_ошибка
        попа
        Ret
    
    disk_error:
        jmp disk_loop
    
    секторы_ошибка:
        jmp disk_loop
    
    disk_loop:
        jmp $
      
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Основная часть этого файла - процедура disk_load .Вспомните входные параметры, которые мы установили в mbr.asm :

    1. Место в памяти для размещения считанных данных ( bx )
    2. Количество секторов для чтения ( dh )
    3. Диск для чтения ( dl )

    Первое, что должна сделать каждая процедура, - это отправить все регистры общего назначения ( ax , bx , cx , dx ) в стек с помощью pusha , чтобы мы могли вернуть их перед возвратом, чтобы избегать побочных эффектов процедуры.

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

    Теперь мы можем установить все необходимые входные параметры в соответствующие регистры и отправить прерывание. Имейте в виду, что bx и dl уже правильно настроены вызывающим абонентом.Поскольку цель состоит в том, чтобы прочитать следующий сектор на диске, сразу после загрузочного сектора, мы будем читать с загрузочного диска, начиная с сектора 2, цилиндра 0, головки 0.

    После выполнения int 0x13 наше ядро ​​должно быть загружено в память. Чтобы убедиться в отсутствии проблем, мы должны проверить две вещи: Во-первых, была ли ошибка диска (обозначенная битом переноса) с использованием условного перехода на основе бита переноса jc disk_error . Во-вторых, соответствует ли количество прочитанных секторов (установленное как возвращаемое значение прерывания в al ) количеству секторов, которые мы пытались прочитать (извлечены из стека в dh ) с помощью инструкции сравнения cmp al, dh и условный переход в случае, если они не равны jne секторов_ошибка .

    Если что-то пошло не так, мы попадем в бесконечный цикл. Если все прошло нормально, мы возвращаемся из процедуры обратно в основную функцию. Следующая задача - подготовить GDT, чтобы мы могли переключиться в 32-битный защищенный режим.

    Глобальная таблица дескрипторов (GDT)

    Как только мы выходим из 16-битного реального режима, сегментация памяти работает несколько иначе. В защищенном режиме сегменты памяти определяются дескрипторами сегментов, которые являются частью GDT.

    Для нашего загрузчика мы настроим простейший из возможных GDT, который напоминает плоскую модель памяти.Код и сегмент данных полностью перекрываются и занимают все 4 ГБ адресуемой памяти. Наша GDT имеет следующую структуру:

    1. Дескриптор нулевого сегмента (восемь 0-байтов). Это требуется в качестве механизма безопасности для обнаружения ошибок, когда наш код забывает выбрать сегмент памяти, что приводит к недопустимому сегменту в качестве сегмента по умолчанию.
    2. Дескриптор сегмента кода размером 4 ГБ.
    3. Дескриптор сегмента данных размером 4 ГБ.

    Дескриптор сегмента - это структура данных, содержащая следующую информацию:

    • Базовый адрес: 32-битный начальный адрес памяти сегмента.Это будет 0x0 для обоих наших сегментов.
    • Предел сегмента: длина сегмента 20 бит. Это будет 0xfffff для обоих наших сегментов.
    • G (степень детализации): если установлено, предел сегмента считается как страницы размером 4096 байт. Это будет 1 для обоих наших сегментов, преобразуя ограничение в 0xfffff страниц в 0xfffff000 байта = 4 ГБ.
    • D (размер операнда по умолчанию) / B (большой): если установлено, это 32-битный сегмент, в противном случае - 16-битный. 1 для обоих наших сегментов.
    • L (длинный): если установлено, это 64-битный сегмент (и D должно быть 0 ). 0 в нашем случае, так как мы пишем 32-битное ядро.
    • AVL (доступно): может использоваться для чего угодно (например, для отладки), но мы просто собираемся установить его на 0 .
    • P (присутствует): здесь 0 в основном отключает сегмент, не позволяя никому ссылаться на него. Очевидно, что для обоих наших сегментов будет 1 .
    • DPL (уровень привилегий дескриптора): уровень привилегий в кольце защиты, необходимый для доступа к этому дескриптору. В обоих наших сегментах будет 0 , так как ядро ​​будет к ним обращаться.
    • Тип: Если 1 , это дескриптор сегмента кода. Значение 0 означает, что это сегмент данных. Это единственный флаг, который отличается между нашим кодом и дескрипторами сегмента данных. Для сегментов данных D заменяется на B, C заменяется на E, а R заменяется на W.
    • C (соответствующий): Код в этом сегменте может вызываться с менее привилегированных уровней.Мы устанавливаем это значение на 0 , чтобы защитить память нашего ядра.
    • E (развернуть вниз): расширяется ли сегмент данных от предела до основания. Актуально только для сегментов стека и в нашем случае установлено значение 0 .
    • R (читаемый): Установите, если сегмент кода может быть прочитан. В противном случае его можно будет только выполнить. В нашем случае установите 1 .
    • Вт (с возможностью записи): Установите, если в сегмент данных можно записывать. В противном случае его можно будет только прочитать. В нашем случае это 1 .
    • A (доступ): этот флаг устанавливается оборудованием при доступе к сегменту, что может быть полезно для отладки.

    К сожалению, дескриптор сегмента не содержит эти значения в линейном виде, а вместо этого они разбросаны по структуре данных. Это делает несколько утомительным определение GDT в сборке. Пожалуйста, обратитесь к диаграмме ниже для визуального представления структуры данных.

    В дополнение к самому GDT нам также необходимо настроить дескриптор GDT.Дескриптор содержит как расположение GDT (адрес памяти), так и его размер.

    Довольно теории, давайте посмотрим на код! Ниже вы можете найти наш gdt.asm , содержащий определение дескриптора GDT и двух дескрипторов сегмента, а также две константы сборки, чтобы мы знали, где сегмент кода и сегмент данных расположены внутри GDT.

      ;;; Метки gdt_start и gdt_end используются для вычисления размера
    
    ; дескриптор нулевого сегмента
    gdt_start:
        dq 0x0
    
    ; дескриптор сегмента кода
    gdt_code:
        dw 0xffff; длина сегмента, биты 0-15
        dw 0x0; база сегмента, биты 0-15
        db 0x0; база сегмента, биты 16-23
        db 10011010b; флаги (8 бит)
        db 11001111b; флаги (4 бита) + длина сегмента, биты 16-19
        db 0x0; база сегмента, биты 24-31
    
    ; дескриптор сегмента данных
    gdt_data:
        dw 0xffff; длина сегмента, биты 0-15
        dw 0x0; база сегмента, биты 0-15
        db 0x0; база сегмента, биты 16-23
        db 10010010b; флаги (8 бит)
        db 11001111b; флаги (4 бита) + длина сегмента, биты 16-19
        db 0x0; база сегмента, биты 24-31
    
    gdt_end:
    
    ; Дескриптор GDT
    gdt_descriptor:
        dw gdt_end - gdt_start - 1; размер (16 бит)
        dd gdt_start; адрес (32 бита)
    
    CODE_SEG equ gdt_code - gdt_start
    DATA_SEG equ gdt_data - gdt_start
      
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Имея GDT и дескриптор GDT, мы наконец можем написать код, который выполняет переключение в 32-битный защищенный режим.

    Переход в защищенный режим

    Чтобы переключиться в 32-битный защищенный режим, чтобы мы могли передать управление нашему 32-битному ядру, мы должны выполнить следующие шаги:

    1. Отключите прерывания с помощью инструкции cli .
    2. Загрузите дескриптор GDT в регистр GDT с помощью инструкции lgdt .
    3. Включить защищенный режим в регистре управления cr0 .
    4. Дальний переход в наш сегмент кода с использованием jmp .Это должен быть большой скачок, чтобы очистить конвейер ЦП, избавившись от всех оставшихся предварительно загруженных 16-битных инструкций.
    5. Настройте все регистры сегментов ( ds , ss , es , fs , gs ), чтобы они указывали на наш единственный сегмент данных размером 4 ГБ.
    6. Установите новый стек, установив 32-битный нижний указатель ( ebp ) и указатель стека ( esp ).
    7. Вернитесь к mbr.asm и передайте управление ядру, вызвав нашу 32-битную процедуру входа в ядро.

    Теперь давайте переведем это в сборку, чтобы мы могли написать switch-to-32bit.asm :

      [бит 16]
    switch_to_32bit:
        cli; 1. отключить прерывания
        lgdt [gdt_descriptor]; 2. загрузить дескриптор GDT
        mov eax, cr0
        или eax, 0x1; 3. включить защищенный режим
        mov cr0, eax
        jmp CODE_SEG: init_32bit; 4. дальний прыжок
    
    [бит 32]
    init_32bit:
        mov ax, DATA_SEG; 5. обновить регистры сегментов
        mov ds, топор
        mov ss, топор
        mov es, ax
        mov fs, ax
        mov gs, топор
    
        mov ebp, 0x

    ; 6.стек установки mov esp, ebp позвоните BEGIN_32BIT; 7. вернуться на mbr.asm

    Войти в полноэкранный режимВыйти из полноэкранного режима

    После переключения режима мы готовы передать управление нашему ядру. Давайте реализуем фиктивное ядро ​​в следующем разделе.

    Ядро C

    После того, как наша основная функциональность загрузчика запущена и работает, нам нужно только создать небольшую фиктивную функцию ядра на C, которую мы можем вызывать из нашего загрузчика. Хотя выход из 16-битного реального режима означает, что у нас больше не будет BIOS в нашем распоряжении, и нам нужно будет писать собственные драйверы ввода-вывода, теперь у нас есть возможность писать код на языке более высокого порядка, таком как C! Это означает, что нам больше не нужно полагаться на ассемблер.

    На данный момент задачей ядра будет вывод буквы X в верхнем левом углу экрана. Для этого нам придется напрямую модифицировать видеопамять. Для цветных дисплеев с включенным текстовым режимом VGA память начинается с 0xb8000 .

    Каждый символ состоит из 2 байтов: первый байт представляет кодированный символ ASCII, второй байт содержит информацию о цвете. Ниже приведена простая функция main внутри kernel.c , которая печатает X в верхнем левом углу нашего экрана.

      void main () {
        символ * video_memory = (символ *) 0xb8000;
        * video_memory = 'X';
    }
      
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Запись в ядро

    Когда вы снова посмотрите на наш mbr.asm , вы заметите, что нам все еще нужно вызывать основную функцию, написанную на C. Для этого мы собираемся создать небольшую программу сборки, которая будет размещена в KERNEL_OFFSET расположение перед скомпилированным ядром C при создании загрузочного образа.

    Давайте посмотрим на содержимое kernel-entry.asm :

      [бит 32]
    [внешняя основная]
    позвонить в главный
    jmp $
      
    Войти в полноэкранный режимВыйти из полноэкранного режима

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

    Важно помнить, что kernel-entry.asm не включен в наш mbr.asm , но будет помещен в начало двоичного файла ядра в ходе следующего раздела. Итак, давайте посмотрим, как мы можем объединить все элементы, которые мы построили.

    Для создания образа нашей операционной системы нам понадобится немного инструментов. Нам нужно nasm для обработки наших файлов сборки. Нам нужно gcc для компиляции нашего кода C. Нам нужно ld , чтобы связать наши скомпилированные объектные файлы ядра и нашу скомпилированную запись ядра в двоичный файл.> $ @ запустить: os-image.bin qemu-system-i386 -fda $ < чистый: $ (RM) * .bin * .o * .dis Войти в полноэкранный режимВыйти из полноэкранного режима

    Важно отметить, что вам может потребоваться кросс-компиляция ld и gcc , чтобы иметь возможность скомпилировать и связать с автономным машинным кодом x86. По крайней мере, я должен был сделать это на своем Mac.

    Теперь давайте скомпилируем, соберем, скомпилируем, загрузим наше изображение в qemu и посмотрим на красивый X в верхнем левом углу экрана!

    Мы сделали это! Следующим шагом будет написание некоторых драйверов, чтобы мы могли взаимодействовать с нашими устройствами ввода-вывода, но это будет рассмотрено в следующем посте 🙂


    Изображение на обложке Майкла Дзедзича на Unsplash.