1. Assembler / Говнокод #14225

    +143

    1. 1
    2. 2
    .686
    .model tiny

    Весьма специфичная ошибка при использовании masm32.

    Запостил: laMer007, 14 Декабря 2013

    Комментарии (56) RSS

    • Хорошо что не:

      .666
      .model 90-60-90
      Ответить
    • А в чем ошибка? Что-то запрещает запускать .com файлы на 686+? :) Или .686 у масма не только переключает допустимый набор инструкций, но и делает еще что-то нехорошее и конфликтующее с tiny моделью?

      P.S. Меня вот masm32 смущает в сочетании с tiny, аля .com...

      P.P.S. Последний раз юзал masm и tasm лет 8-9 назад, может быть поэтому ошибка не по глазам... Кому-то еще нужны эти поделия, когда есть полноценные и кроссплатформенные макроассемблеры типа nasm'а?
      Ответить
      • Ошибка в том, что masm32 будет по умолчанию генерировать код для 32-битного сегмента. Нужна ещё директива для переключения на 16 бит, если я правильно понял автора.
        Ответить
        • Ну т.е. подвох все-таки в masm32.

          Unfortunately, MASM often defaults to 32 bit mode whenever you select an 80386 or later processor using a directive like .386, .486, or .586 in your program.
          <...>
          If you use one of the directives to activate the 80386 or later instruction sets, you should put use16 in all your code segments.
          Ответить
          • Проверил WASM, такая же штука: если в качестве процессора указано что-то выше 286, то пользоваться короткой директивой .code нельзя, приходится писать длинную директиву типа _TEXT SEGMENT USE16 ...

            P.S. Хотел спросить, а чем же тогда отличается FLAT от TINY, но потом сам понял: в модели FLAT сегменты кода и данных по умолчанию не объединяются в группу.
            Ответить
            • Кстати да, когда читал Зубкова или кого-то другого, меня все мучал вопрос - а что если стек дорастет до данных/кода?
              Ответить
              • Годная ось от сторожевой страницы сообщит о конце света стека.
                Ответить
                • Для кома кто-то что-то сообщал? И дальше что? Нет, под виндой тебе в другие проги нагадить не дадут, а вот себе нагадить никто не помешает, так?
                  Ответить
                  • в хорошей оси код защищён от записи
                    Ответить
                    • Код - да. Данные - не все, по определению.
                      Ответить
                    • >в хорошей оси
                      >DOS
                      /0. Тогда было модно делать самомодифицирующийся код. Ёба, ком - это исполняемый образ без заголовков.
                      Ответить
                  • > себе нагадить никто не помешает
                    В винде, насколько помню, в конце стека помещается guard page, при касании которой к стеку подклеиваются еще странички. А дальше - пустота. За обращение к пустоте программу убивают с access violation. Так что маловероятно, что ты ростом стека запорешь сегмент данных.

                    P.S. Кстати поэтому на старых виндокомпиляторах был забавный баг - пишешь локальный массив килобайт на 8, и касаешься первого элемента - прога вылетает с access violation, хотя места под стек еще полно :)

                    А для доса - да, защиты памяти нет, можно спокойно портить код и даные. Что случится - а х.з. либо прога попадет в случайный цикл, либо напорется на неизвестный опкод. У меня обычно выводилось немного мусора и прога висла.
                    Ответить
                    • Сейчас компиляторы сами лапают сторожевую страницу при доступе к большой структуре или массиву на стеке?
                      Ответить
                      • Насколько помню - да. Посмотри в дизасме, вроде бы цикл втыкался с шагом 4кб перед первым использованием большого массива.
                        Ответить
                    • Оффтопну. Есть один баг переполнения буфера (EIP перезаписывался). Как бы сделать под него эксплоит? Просто так помогать никто не торопился, хотя я людям на форумах раньше часто помогал (сейчас бросил там сидеть, бесполезно это).
                      Ответить
                      • > Как бы сделать под него эксплоит?
                        Ну я надеюсь, что только в образовательных целях? :)

                        Ну если нет NX и ASLR - можно попробовать поместить шеллкод в тот самый буфер и перезаписать адрес возврата, который попадет в eip, так, чтобы он попал на посадочную полосу перед шеллкодом. Классика жанра ;)

                        Если есть NX, то этот метод не проканает, и придется снимать защиту от исполнения на буфере с шеллкодом. Для этого, с помощью ROP*, тебе придется вызвать некую апишку (например VirtualProtect, если это винда).

                        Если есть и ASLR - то будет туго. Придется искать библиотеки, которые грузятся по статическому адресу (в линухе, это только сам экзешник, если он собран без -pie), и юзать ROP только на них.

                        Если ASLR тотальный (64 битная линуха, экзешник откомпилен с -pie), то придется лососнуть тунца, и забить на переполнение буфера :)

                        * ROP - return-oriented programming. Ты ищешь кусочки кода с нужными тебе инструкциями, стоящими прямо перед ret. Затем аккуратно раскладываешь в стеке адреса этих кусочков в нужном порядке. Каждый ret будет вынимать адрес следующего кусочка из стека и прыгать на следующий кусочек..
                        Ответить
                        • не понял про ROP.
                          > забить на переполнение буфера
                          И как тогда? 64 винда и линь стоит уже почти везде.
                          Ответить
                          • > И как тогда? 64 винда и линь стоит уже почти везде.
                            Лососнуть тунца... не зацикливаться на переполнении буфера... смириться, с тем, что оно осталось в прошлом веке (не только благодаря ASLR, но и языкам типа жабы, решетки и т.п.)... уйти в запой и выйти в окно... искать другие методы взлома :)

                            > не понял про ROP.
                            Что именно? У меня у самого про ROP познания чисто теоретические, т.к. не было повода их применить.

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

                            Работа кропотливая, чем-то похожая на составление паззла, но вполне реализуемая, и, наверное, даже автоматизируемая ;)

                            Если же ASLR нету - можно почти не париться с кусочками (немного все-таки придется, чтобы как-то поместить на стек адрес шеллкода), а раскладывать на стеке аргументы и адреса нужных апишек.
                            Ответить
                          • Простой и наивный пример по ROP. Допустим бинарник некого "сервера" на линухе собран без -pie, и мы можем заиметь его для изучения. В учебных целях попытаемся завершить его с exit code = 42.
                            void vulnerable() {
                                char buf[32];
                                gets(buf);
                                /* какая-то обработка buf */
                            }
                            Состояние стека будет примерно таким:
                            локальные переменные vulnerable (в нашем случае buf на 32 байта)
                            указатель на предыдущий фрейм (4 байта, есть не всегда)
                            адрес возврата (4 байта)
                            аргументы vulnerable (в данном случае их нет)
                            локальные переменные вызвавшей функции
                            и т.п.
                            Один из способов выполнить exit(42) - положить 1 в eax и 42 в ebx и вызвать прерывание 0x80. Ищем подходящие кусочки кода в экзешке. Допустим нам повезло, и мы нашли:
                            // первый фрагмент (адрес 0x00123456)
                            mov eax, 1
                            mov edi, 100500
                            xor esi, esi
                            ret
                            // второй фрагмент (адрес 0x00654321)
                            mov ebx, 42
                            ret
                            // третий фрагмент (адрес 0x0000DEAD)
                            int 0x80
                            Значит на вход программе нужно подать <32 байта хлама (+4 если есть фреймпоинтер)> 0x56 0x34 0x12 0x00 0x21 0x43 0x65 0x00 0xAD 0xDE 0x00 0x00. ret внутри vulnerable снимет со стека адрес первого кусочка, в eax попадет 1, рет из первого кусочка снимет со стека адрес второго, в ebx попадет 42, рет в нем снимет адрес последнего кусочка, и вуаля, программа завершилась с кодом 42 ;)

                            P.S. Грань между хакером и безопасником, имхо, очень тонкая. Знания у них практически одинаковые, разница только в целях ;)
                            Ответить
                            • gets не нужен.
                              олсо круто!
                              Ответить
                              • > gets не нужен.
                                Об этом гцц как бы намекает при компиляции ;)
                                Ответить
                            • >Грань между хакером и безопасником, имхо, очень тонкая.
                              Если под безопасником имеется в виду пентестер, то да, а так задача не совсем совпадает. Если у меня будет задача избавить код от скуль, я не буду искать, как их эксплуатировать, я просто заменю все запросы на параметризированные - выйдет быстрее и шаблонно.
                              Ответить
                              • > Если у меня будет задача избавить код от скуль, я не буду искать, как их эксплуатировать, я просто заменю все запросы на параметризированные - выйдет быстрее и шаблонно.
                                Ну здесь что имеется в виду. В обоих случаях ты знаешь о наличии этой уязвимости, ты знаешь о том, как она выглядит в коде (непараметризованный запрос без экранирования) и как ее устранить. Вот эти знания они общие что для защиты, что для атаки.

                                Специфика да, она безусловно есть. Но базовые знения то общие ;)
                                Ответить
                                • Совсем базовые - да. Но взломщик должен думать о том, как протащить скулю через фильтры/ограничения. Как сломать побольше. С другой стороны, безопасник должен думать не о том, как залатать побольше, а как оставить поменьше - а это не одно и то же. "Фильтрация" рекомендованная пыхомакаками тут есть не идеальный вариант, ибо небезопасна по умолчанию - хотя свою работу в принципе выполняет и взломщика бы устроила как контрмера.

                                  Точно так же не обязательно уметь писать сплоиты к переполнениям буфера, чтобы не допускать их.
                                  Ответить
                                  • > Точно так же не обязательно уметь писать сплоиты к переполнениям буфера, чтобы не допускать их.
                                    Ну да, я примерно представляю, как это делается, но на практике - скорее всего не смогу, от недостатка опыта.

                                    P.S. Фаерфокс упал 2 раза от нажатия на кнопку "ответить". Переполнение буфера от специально сформированного комментария? :)
                                    Ответить
                                    • Может, из-за проверяльщика орфографии? Хз отчего еще.
                                      Ответить
                          • ROP - по сути, ты записываешь порядок и параметры вызова функций.
                            Ответить
                        • Так я в этом не шарю толком. Будем для простаты считать, что ничего нету. С чего начать? Можно как-то готовый из metasploit присобачить?
                          Ответить
                          • > Так я в этом не шарю толком.
                            Я тоже, на практике не пробовал ;)

                            > С чего начать?
                            С книги "Как научиться ломать сервера через переполнение буфера для чайников" :)

                            > Можно как-то готовый из metasploit присобачить?
                            Я не в курсе, что metasploit умеет ;(
                            Ответить
                            • >С книги "Как научиться ломать сервера через переполнение буфера для чайников" :)
                              А кто бы мог помочь с ним или даже сколько будет стоить такое заказать?

                              Там есть готовые payload-ы, connect, reverse connect, с просто шеллом и даже что-то покруче.
                              Ответить
                    • Читаю с упоением. Спасибо, кэп.
                      Ответить
              • Забыл написать. Речь идет о com файлах.
                Ответить
        • Лол. Катаюсь по полу. Попробовал написать хелоуворлд для masm32.
          Если делать так:
          .686
          .model tiny
          То получаю 32хбитный код, но если обменять строки местами, то получаю 16тибитный. о_О
          В обоих случаях никаких ошибок компиляции (или ассемблирования?). Заводил только один сегмент .code
          Ответить
          • Кстати, а кому такая странная идея реализации завязанной на порядок директив пришла на ум? Как это вообще объяснить? Однопроходностью?
            Ответить
            • Может, после указания 1 из директив первой, он игнорирует вторую?
              Ответить
            • Предположу, что ассемблеры - засохшее гавно мамонта.
              Ответить
              • > засохшее гавно мамонта
                masm32 и tasm то? Так и есть ;)
                Ответить
                • Да все асмы. Тогда такие вещи могли просто никого не интересовать, есть 3 асма (еше wasm был вроде), у них есть свои "особенности", все кто ими пользовался их знал. Это сейчас разожрались.
                  Ответить
      • nasm? Так он вроде так и не научился собирать приложения под дос? Хотя кому это нужно...
        Ответить
        • > приложения под дос
          Досовские .com - без проблем, т.к. заголовков никаких не нужно. bits 16 и погнали.
          Досовские .exe - напрямую не умеет, зато умеет obj в OMF формате, которые, по идее можно долинковать любым досовским компоновщиком.

          На самый-самый крайний случай можно досовский заголовок собрать тупо директивами db/dw. Там же в основном константы да смещения, которые легко считаются как расстояние между двумя метками.

          > Хотя кому это нужно...
          Вот именно ;)
          Ответить
          • > по идее можно долинковать любым досовским компоновщиком.
            Это как-то не интересно. Хочется всё из коробки стандартными средствами ассемблера.

            > На самый-самый крайний случай можно досовский заголовок собрать тупо директивами db/dw
            Когда-то смотрел на их сайт. Так и написано в его доках. Это же извращение.

            > Вот именно ;)
            Предлагаю забить на асм и обсудить что-нибудь полезное.
            Сейчас наблюдаю какой-то иностранный форум и там плывет дата постов. Часа 3 назад все посты были в пределах 2 AM и после все пошли спать, а теперь там у всех постов 5 AM. Как такое возможно?
            Ответить
            • > Это же извращение.
              Ну почему. Можно же сделать набор макросов для этого, и поместить его в отдельный инклудник ;)

              > Часа 3 назад все посты были в пределах 2 AM и после все пошли спать, а теперь там у всех постов 5 AM
              1) Админ перевел часы на серваке.
              2) Админ сменил часовой пояс на серваке.
              3) Ты сменил часовой пояс в профиле.
              Ответить
              • 4) сервак переехал в другой часовой пояс.
                Ответить
                • Наверное хостится на Windows Azure
                  Ответить
                  • Для тех кто не понял - там серваки могут подниматься на разных машинах (обычно виртуальных) и по очереди то врубаться то вырубаться и так экономят нагрузку на сеть.
                    Например всего 50 серваков. А проектов 10. Когда на одном из проектов максимальная нагрузка, то ему отдают 41 машину. Остальным, если нагрузки нет, то им по одной машине. Когда нагрузка поменялась, то например 10 машин - одному проекту, 32 другому, а 8 оставшимся (каждому по одному).
                    Ответить
                • Я вообще считаю, что все серваки должны работать в UTC и только в UTC :)
                  Ответить
              • Да ничего я не менял... Хотя... Я смотрел с другого компьютера. Я поменял часовой пояс телепортацией.
                Ответить

    Добавить комментарий