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

    −248

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    nop
    nop
    nop
    call somelabel
    somelabel:
    pop si
    sub si, 3

    ассемблер - источник массы говнокода, классика...

    Запостил: guest, 08 Декабря 2008

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

    • Destman:
      Вполне такой нормальный код :)
      Зачемто понадобился адрес 4-й команды (может данные какиенить в сегменте cs лежат, али еще чего такого темного понадобилось сделать).
      А нопы - это либо выравнивание, либо остаток от предыдущей комманды (однопроходные компиляторы часто имеют такую особенность, что если пыргаеш вперед по коду (компилятор не знает сколько там байтов впереди) то резервируется место для команды с длинным переходом, потом когда метка куда прыгать всплывает - компилятор уже вставляет нужный вариант перехода и если осталось место - оно все в нопах :) )
      Ответить
      • Ну если это выхлоп компилятора, а не ручное творечтво, то смеяться не над чем
        Ответить
    • Destman:
      Наверно в списке нету асма :)
      Ответить
    • страйко:
      ща добавим :)
      Ответить
    • Destman:
      Не ну наглеж. Все языки как языки а ассемблер с маленькой буквы :)
      Ответить
    • страйко:
      да, надо быть политкорректным
      Ответить
    • гм, просто пропатчили чтото, вот и гавнакод вышел;)
      Ответить
    • Dr.Freez:
      А чо) ... этаж асм...пишешь пишешь, накидаешь 20 строк кода а потом нахрен их)...вот и остаются такие ляпы)
      Ответить
    • Бармалейкин:
      Собственно, слово «ассемблер» это не название конкретного языка программирования (типа Фортран, Форт, Паскаль, Пролог, Си или Java), а просто слово английского технического языка, обозначающее процесс трансляции неких команд в исполняемый код. Потому писать его можно с любой буквы. Дело привычки.
      Ответить
    • nobodyzzz:
      вполне нормальный код. попробуйте погуглить про базонезависимый код.
      Ответить
    • Mike:
      Ну, nop зачем не знаю, а дальше получение смещения для проги, которая будет висеть по неизвестным адресам в памяти. Нормально. Например для вируса.
      Ответить
    • Mike:
      Кстати, пример вырванного из контекста кода. Если бы дали строчки 8,9,10 - было бы понятно. И скорее всего не исходник, а дизассемблированный листинг, так как строка 4 должна выглядеть как

      BaseAddress:
      call somelabel
      Потом в SI смещение правильное.

      Вообщето, действительно говнокод, так как можно было бы переименовать somelabel в BaseAddress и не городить sub si,3

      Когдато сам писал такой код, когда еще были .com файлы, в начале 3 байта jmp на то что аттачнул к файлу, а потом уже все остальное :))
      Ответить
    • Archaron:
      NOP - задержка, никто не писал для микроконтроллеров разве?
      Ответить
    • Mike:
      Под х86 обычно юзали прерывания BIOS или DOS, непосредственно до оборудования через in/out редко преходилось, поэтому особой надобности в задержках небыло. Только если контроллеру прерывний что сказать. :)) Код, видно по:
      pop si
      sub si , 3
      16-битный, так что сейчас обсуждаем MS-DOS.
      Ответить
    • Destman:
      Ну код может быть и 32 и 64 битным :)
      Это только часть кода, и тут работа идет максимум с 16 битными операндами...

      З.Ы. Я такую конструкцию тоже юзал както, в перехватчике винапи вызвов (для дебаговых целей мониторил адрес функции которую перехватил)
      Ответить
    • Хуй тебе
      Ответить
    • zzzz
      Ответить
    • Нормально. В «Линуксе» такое используется для position-independent code. В «DOS» такой же приём использовали вирусы.
      Ответить
      • показать все, что скрытоvanished
        Ответить
      • PIC же это когда смешение добавляется к регистру, и оно патчится, не?
        Ответить
        • «PIC» — это когда код не зависит от адреса, по которому он загружен. Основная проблема — доступ к данным: в «x86» можно было загружать данные только по абсолютным адресам (ну, абсолютным базам), поэтому приходилось делать разные трюки. В частности, один из них приведён в ОП-посте:
          jmp start
          db_start:    ; Данные
          db 'Hello World', 0
          
          start:
          call get_ip
          get_ip:
          pop eax     ; Теперь в eax находится реальный адрес 'get_ip'
          sub eax, (get_ip - db_start)    ; Свинтаксис забыл
          push eax
          call puts

          А в «x86_64» завезли «RIP-relative» адресацию, и такие трюки стали нинужны.
          Ответить
          • Да, так понятно. Мне казалось, что там всегда добавляется регистр, и в нем указывается смещение: очевидно, я спутал с RIP
            Ответить
          • Кстати за call + pop защита от нарушения control flow потихоньку начинает пиздить по яйцам. Как и за push + ret.
            Ответить
            • Ага, пару лет назад читал интересную статейку на тему нахождения таких паттернов в коде для противостояния всяческим RCE.
              Ответить
            • Control flow не нужен.
              Ответить
            • Кстати, control flow можно исправить:
              mp start
              db_start:    ; Данные
              db 'Hello World', 0
              
              start:
              call get_ip
              loopa:
              jmp zaloopa
              get_ip:
              mov ebx, esp
              mov eax, [ebx]     ; Теперь в eax находится реальный адрес 'loopa'
              ret
              zaloopa:
              sub eax, (loopa - db_start)    ; Свинтаксис забыл
              push eax
              call puts
              Ответить

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