1. Си / Говнокод #20245

    −47

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    //                   ПРЕОБРАЗОВАНИЕ КОДА И КОНЕЧНЫЕ АВТОМАТЫ
    //                   ---------------------------------------
    //               (проектируем очень хуево дизассемблируемый код)
    
    int T[256] =
    {
      4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      //                      , -      0 1 2 3 4 5 6 7 8 9
      0,0,0,0,0,0,0,0,0,0,0,0,2,3,0,0, 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    };
    
    for(;;)
    {
      int A;
      switch( S )
      {
        case 0:
                switch( T[*c] )
                {
                  case 1:  { S=1; A=1; }; break;
                  default: { S=5; A=2; }; break;
                }
                break;
        case 1:
                switch( T[*c] )
                {
                  case 2:  { S=0; A=2; }; break;
                  case 1:  { S=1; A=3; }; break;
                  case 3:  { S=2;      }; break;
                  case 4:  { S=4; A=2; }; break;
                  case 0:  { S=5;      }; break;
                }
                break;
        case 2:
                switch( T[*c] )
                {
                  case 1:  { S=3; A=4; }; break;
                  default: { S=5;      }; break;
                }
                break;
        case 3:
                switch( T[*c] )
                {
                  case 2:  { S=0; A=5; }; break;
                  case 1:  { S=3; A=6; }; break;
                  case 4:  { S=4; A=5; }; break;
                  default: { S=5;      }; break;
                }
                break;
        case 4:
                A = 7;
                break;
        case 5:
                A = 8;
                break;
      }
      switch( A )
      {
        case 1: { l=*c-'0';      c++; }; break;
        case 2: { store(l,l);    c++; }; break;
        case 3: { l=l*10+*c-'0'; c++; }; break;
        case 4: { h=*c-'0';      c++; }; break;
        case 5: { store(l,h);    c++; }; break;
        case 6: { h=h*10+*c-'0'; c++; }; break;
        case 7: { exit();             }; break;
        case 8: { error();            }; break;
      }
    }

    http://z0mbie.daemonlab.org/automaton.txt отсюда

    Мне это напомнило вот эту вот ебанутейшую хуиту https://src.chromium.org/viewvc/native_client/trunk/src/native_client/src/trusted/validator_ragel/gen/validator_x86_64.c из хрома, которая делает валидацию опкодов из-под NaCl, его через какой-то ragel делают

    Запостил: j123123, 22 Июня 2016

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

    • Как по мне, лучше уж специальный запутывающий компилятор придумать, чем подобные извращения
      Ответить
      • Можно писать сразу на асме, а чтобы не декомпилировали, прыгать в середину инструкции (если это CISC):
        http://govnokod.ru/13242
        Ответить
        • Можно и в ARM-ах прыгать в середину инструкции, когда речь идет о переключении из arm в thumb http://www.keil.com/support/man/docs/armasm/armasm_dom1361289866466.htm
          Ответить
          • А ΒΧ отбрасывает младший бит (который служит для индикации типа инструкций) или реально переходит на нечётный адрес?
            Ответить
            • P.S. Пока не нашёл ответа на свой вопрос, зато нашёл это: «You must ensure that the processor never receives instructions of the wrong instruction set for the current state».
              Ответить
            • Насколько я понял, этот младший бит просто сигнализирует что нужен или не нужен переход в thumb или arm. А исполнение по нечетному адресу невозможно. Инструкции в arm mode всегда имеют фиксированный размер под 4 байта и выровнены под 4 байта, а вот thumb может быть и 2 и 4 байта, и выровнен должен быть под 2 байта

              http://stackoverflow.com/a/28670713
              Ответить
              • Тогда вижу две возможности для запутывания:
                1. В режиме thumb прыгнуть в середину четырёхбайтовой инструкции.
                2. Исполнить одну и ту же цепочку байтов и как thumb, и как ARM (придётся подобрать цепочку, которая имеет смысл в обоих режимах).
                Ответить
      • Так он к этому и ведёт, как я понял.
        Самое интересное заключается в том, что все показанные здесь
        преобразования кода возможно осуществлять автоматически,
        то есть конвертировать части обычных бинарных программ или сорцов
        в конечные автоматы и/или заменять порядок выполнения команд
        функцией.

        Предположим, что в качестве переменной части состояния автомата
        был бы использован не флаг ZF, а, скажем, значение регистра AL.
        Тогда для получения всей информации, закодированной в функции,
        на каждом шаге пришлось бы анализировать 256 вариантов.
        А если бы это был регистр AX, то при проверке первых
        двух байт файла на MZ, из текущего состояния было бы 65534 перехода
        на одну ветвь исполнения, и 2 перехода на другую ветвь.
        При еще больших размерах состояний, перебор всех состояний на
        каждом шаге стал бы еще более трудным, и тогда часть программы,
        отвечающая за изменение того же exe файла была бы пропущена,
        то есть не была бы экстрактирована из функции.

        В идеале такая функция должна представлять собой черный ящик,
        в него подают текущее состояние - он возвращает следующее,
        а получить значение из середины последовательности крайне сложно.
        Ответить
      • http://tigress.cs.arizona.edu/ и не такую мешанину умеет делать
        Ответить
    • мне табличка сверху напомнила про http://esolangs.org/wiki/Befunge и http://esolangs.org/wiki/Piet

      ЗЫ
      > его через какой-то ragel делают
      к слову, если ты на встроенщине трахаешься, то тебе ragel может быть даже и понравится - http://www.colm.net/open-source/ragel/
      Ответить
    • >проектируем очень хуево дизассемблируемый код
      Мне это нравится.
      Ответить
      • Гипотетически можно разработать бэкенд для gcc, который может вместить в себя целые банки плохо дизассемблируемого кода.
        Ответить
        • Да он и так неплохо путает, когда оптимизации включены. Инлайнит до седьмого колена, строчки кода между собой перемешивает, локальные переменные прямо об esp читает вместо ebp...
          Ответить
          • Надо ещё сильнее разработать, чтобы IDA вообще ничего найти не могла.
            Ответить
          • Интересно, а может ли flto делать ссылки в какую-то байт-код жопу? И вообще сильно ли он путает?
            Ответить

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