надёжный способ отличить код от данных в pe файле

Тема в разделе "WASM.RESEARCH", создана пользователем vladqq, 19 авг 2009.

  1. vladqq

    vladqq New Member

    Публикаций:
    0
    Регистрация:
    24 мар 2009
    Сообщения:
    69
    с билдеровскими exe получается проблема даже если есть detailed map файл, тк не понятно в какой момент заканчивается функция и начинаются константы (многие функции имеют много ret-ов). а константу можно вполне принять за нормальный код, отличить проблематично. но ида их както со 100%ной точностью распознаёт.
     
  2. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    а заголовки функции используют?
     
  3. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    вы б вобщето выложили какойнить маленький файлик с описанным затруднением.
    а вобще, вам стоит самому понакомпилить маленьких ехе (мало кода/данных), но чтоб в код данные поклало. отдельно с числами, строками, сруктурами, каллбэками и посмотреть что там и как. а возникнут вопросы - не стесняйтесь аттачить. ато я, например, делфу/билдер около 2к года последний раз видел.
     
  4. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    qqwe
    выложите ка программку, где вы в билдере используете (с пользой) код как данные
    я не говорю, что не возможно, а лишь констатирую тот факт, что чушь с генерированную билдером не просто не возможно предсказать (а если еще и включить оптимизацию), но и использовать с пользой (вот на асме еще вполне реально).
     
  5. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    max7C4
    потому мсвс, хотя имхо разница тут небольшая

    отдельный файл с функцией(ями) foo используемой и как данные (исходные/проверяемые/изменяемые)
    Код (Text):
    1. #include <stdio.h>
    2. #include <math.h>
    3.  
    4. extern int
    5. foo(int _a, int _b){
    6.     double a, b, c;
    7.     a = (double)_a;
    8.     b = (double)_b;
    9.     c = a + b * log(a + b);
    10.     c = a * sin(c);
    11.     if(c > 0){
    12.         a = b * c;
    13.         b = tan(a) * b + c;
    14.         printf("%.4f\n", a - b);
    15.         return 1;
    16.     }
    17.     return 0;
    18. }
    19.  
    20. extern void
    21. foo_e(){}
    отдельный вспомогательный файл нужный, чтобы получить скомпиленую foo без хекседиторов
    Код (Text):
    1. #include <stdio.h>
    2.  
    3. extern int foo(int, int b);
    4. extern void foo_e();
    5.  
    6. int
    7. main(){
    8.     unsigned char* f = (unsigned char*)(&foo);
    9.     int foo_sz = (int)(&foo_e) - (int)(&foo);
    10.     int i;
    11.  
    12.     printf("foo (0x%X), size = %d\n\n", f, foo_sz );
    13.     printf("foo bytes = {\n\t");
    14.     for(i = 0; foo_sz > 0; foo_sz--, f++, i >= 8 ? printf("\n\t", i = 0) : i++)
    15.         printf("0x%.2X, ", *f);
    16.     printf("}\n");
    17.  
    18.     return 0;
    19. }
    ессно, первый файл после считывания уже не перекомпиливается.

    как видите, мы не просто предсказали, а узнали совершенно точно.
    как и для чего это можно использовать.. ну a + b = c. а можно и a + b = a.. вобщем каков много. исходные данные полюбому нужны
     
  6. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    да неправда, часто в mcf-прогах не распознает функции, т.к. большинство вызовов виртуальные => нет ссылок на многие функции, и они лежат как данные, попробуй поискать в 10 mfc-shareware-прогах надпись о неправильном номере, и т.д. , уверен, что наткнешься на такую в которой ссылки на текст не будет, хотя бинарным поиском текст будет искаться, а потом, после хардварного брейка на аксесс, будет видно, что код, читающий -- не дизассемблирован)) может я не прав, пусть гуру поправят, но ида ищет именно по ссылкам перекрестным + иногда минимально как-то еще)) тк все-таки иногда попадаются явно функции без ссылог..
     
  7. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    qqwe
    1.
    в том-то и прикол. говорится про билдер и его любовь пихать данные в сегмент кода.
    2.
    3.
    с успехом можно заменить строкой байт. т.е. это не код. потеряна смысловая нагрузкам как кода, хоть в исходнике это и код - в программе это лишь данные для вывода.
     
  8. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    max7C4
    а какая разница в данном случае? ов тоже может все запихать в код, если ему это указать. впрочем у меня нет билдера и вам знать лучше, тк вы можете проверить

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

    да много чего придумать можно. например, некоторую защиту от декомпиля/анализа

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

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

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    qqwe
    я хочу подчеркнуть, что именно КОД как данные
    ваш же случай эквивалентен
    printf("ggg muhaha bugaga");
    где в роли строки берутся данные откомпилированные как "код", но ни разу не исполняемые (что снимает с этих данных смысловую нагрузку код). и хоть в исходнике вы видите код, но на самом деле это лишь последовательность байт (константный массив с данными, однозначно в вашем примере)
    это снимает с явно определяет указатель на код
    это тоже однозначно определяет участок данных как код
    аналогично
    ну я к примеру не вижу ни одного ее вызова, явного или не явного т.е. этот кусок данных так или иначе не подвергается исполнению => его можно рассматривать как массив данных
    я лишь хочу указать, на то, что данные в бинарнике делятся на две категории
    1) подвергаемые исполнению - код
    2) используемые при исполнении - данные
    я же имею ввиду например данные, которые используются в качестве кода, но одновременно являются полезными данными
    пример: "rescue"
    обычное слово, но на него может быть сделан не явный переход т.к. дизассембируется это как
    Код (Text):
    1. jc 0x65
    2. jnc 0x63
    3. jz 0x65
    и первые 2 команды означают безусловный переход на 0х65 байт дальше, где может располагаться shadow executable procedure, а после затирания данных (хоть ей же) и не найти эту процедуру
    в дизассемлере это определится явно как строка (особенно если она явно будет использоваться как строка), а не явно может вызываться и быть кодом (вот тогда это действительно не отличить). в ваших же примерах на Си вы похоже даже не подозреваете что как будет логически оцениваться после компиляции.
     
  10. Stiver

    Stiver Партизан дзена

    Публикаций:
    0
    Регистрация:
    18 дек 2004
    Сообщения:
    812
    Адрес:
    Germany
    Как уже было отмечено выше, в общем случае эта задача не решаема. Еще лет 30 назад было доказано, что она эквивалентна проблеме остановки (halting problem).

    А на старых системах код нередко использовался одновременно как данные. Вот даже литературное свидетельство: http://www.pbm.com/~lindahl/mel.html
     
  11. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    max7C4
    Код (Text):
    1. #include <stdio.h>
    2.  
    3. extern void
    4. foo(char* b, char* e){
    5.         int i;
    6.  
    7.         printf("foo (0x%X), size = %d\n\n", b, e - b );
    8.         printf("foo bytes = {\n\t");
    9.         for(i = 0; e > b; b++, i >= 8 ? printf("\n\t", i = 0) : i++)
    10.                 printf("0x%.2X, ", *((unsigned char*)b));
    11.         printf("}\n");
    12. }
    13.  
    14. extern void foo_e(){}
    Код (Text):
    1. #include <stdio.h>
    2.  
    3. extern void foo(char*, char*);
    4. extern void foo_e();
    5.  
    6. int
    7. main(){
    8.     foo((char*)&foo, (char*)&foo_e);
    9.  
    10.     return 0;
    11. }
    так лучше?
    файл N 2 нужен только для узнавания во что скомпилилась функа в файле 1. для использования 1 пишутся файлы 3, 4 итд

    ??

    откуда такая уверенность? на буквы не похоже? не похожи на буквы картинки, архивы, шифры и даже текст в утф8 на китайском не с начала

    абсолютно все можно рассматривать как массивы данных.

    это заблуждение. крипторы/морферы/виртуалки полным ходом рассматривают код как данные

    ну, я многое не подозреваю, потому частенько проверяюсь. вот и счас
    Код (Text):
    1. #include <stdio.h>
    2.  
    3. char *s = "rescue";
    4.  
    5. typedef void(*foo)();
    6.  
    7. int main(){
    8.     foo f = (foo)s;
    9.  
    10.     printf(s);
    11.    
    12.     f();
    13.     return 0;
    14. }
    запустить не получается, но ида поняла как строку. те способ действенный, хоть и немного сложный в написании. невнимательный реверсер не сразу допрет
     
  12. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Stiver
    ни кто и не говорит об однозначности. просто при дизассемблировании можно классифицировать те или иные байты как команды/данные в зависимости от признаков:
    1) по адресу производится переход или вызов - команды
    2) по адресу производится чтение/запись - данные/команды (на этот вопрос отвечает первый признак)
    3) по адресу производится индексированное чтение/запись - массив/команды (на этот вопрос отвечает первый признак)
    4) по адресу производятся последовательный доступ и применение идентичных операций - строка/команды (на этот вопрос отвечает первый признак)

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

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    уже лучше.
     
  14. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    По-моему задача частично решается методами, используемыми в OllyDBG (там есть несколько разных методов анализа кода в том числе и эвристика). Кто-нибудь встречал подробное описание этих методов?
     
  15. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    dermatolog
    Вот именно, только частично, причем не самым лучшим образом. В IDA распознавание данных и кода выполнено намного лучше. Надо учитывать, что за один проход (OllyDBG), правильный результат получить невозможно, IDA многопроходна, но и ей не хватает мастерства, необходимо или чуток изменить алгоритм или добавить пару проходов. Правильный алгоритм - распознаем код, а всё, что не код - это данные.
     
  16. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Vam
    На то она и IDA :))
    Понятно что это самый правильный способ, только есть одно НО - в общем случае это нереализуемо на автомате.
     
  17. Killer

    Killer New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2008
    Сообщения:
    316
    Верно. И это нужно учитывать.

    Реализуемо на 95%

    Конкретно по сабжу:

    1. Дизасм у Олли хороший, можно его улучшить. Например переделать эвристику, добавить поиск сигнатур частых кусков кода, анализировать фиксапы(если есть).

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

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Killer
    Вроде речь идет про статику - причем тут динамика?
     
  19. Killer

    Killer New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2008
    Сообщения:
    316
    dermatolog

    Ок, тогда сигны заюзать.