Декомпилятор С++

Тема в разделе "WASM.RESEARCH", создана пользователем Vam, 16 июл 2008.

  1. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    Всем желающим, но не более 10 человек, предлагается протестировать программу на следующих условиях:
    1. Наличие IDA v5.2
    2. Наличие Win32 экзешника, компилированного VS любой версии, с отладочной информацией, желательно самописного.
    3. В течение месяца после инсталляции произвести тестирование программы и выслать отчет, т.к. только в течение этого времени программа будет полностью работоспособна.
    4. Содержание отчета:
    - найденные ошибки, баги, глюки и пр.
    - пожелания, что должно быть изменено.
    - заархивированное содержимое папки ErrorLogs тестируемого проекта, при условии, что размер архива не более 2 Мб.
    5. Запрещается передача программы другому лицу, публикование и распространение.

    Если вы согласны с этими условиями, то пишем в приват и сообщаем свой email, на который будет выслана программа и небольшое руководство в виде readme.
     
  2. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    Пока только win32 exe, т.е. в исследуемом файле должнв быть функция, WinMain или main, за которую программа и цепляется.
     
  3. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    Есть ли в VC утилитах или в библиотеках или в IDA функция, которая из простых имен делает манглед имена.
    PS: Для обратного преобразования используется UnDecorateSymbolName.
     
  4. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Vam
    Что? O-o.
     
  5. a1tus

    a1tus New Member

    Публикаций:
    0
    Регистрация:
    5 янв 2009
    Сообщения:
    22
    Есть ли в VC утилитах или в библиотеках или в IDA функция, которая из простых имен делает манглед имена.


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

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    a1tus
    Знаю, но я спрашиваю про конкретный компилятор - VS.
    Должна же где-то быть прямая функция, если есть обратная - UnDecorateSymbolName.
     
  7. nobodyzzz

    nobodyzzz New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2005
    Сообщения:
    475
    http://wasm.ru/article.php?article=macrofasm здесь есь макрос, который делает мангалинг...
     
  8. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    nobodyzzz
    Там только частичное описание, до полного ему очень далеко. Ладно, если нет готовой функции, то придется написать свою. Мне манглед имя нужно только для одной цели - получение адреса таблицы виртуальных функций класса. Может кто предложит другой способ поиска этой таблицы.
     
  9. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    Встретил "неразрешимую" ситуацию:
    есть переменная (неважно какая - локальная, классовая и т.д.) типа void* ptClass;
    в контексте некоторой функции она используется как ((SomeClass*)ptClass)->SomeFunc(...);
    где SomeFunc объявлена в классе SomeClass как virtual void SomeFunc(...);
    Вопрос: возможно как-то (ессно по ассемблеру) определить, какая же конкретно функция вызывается в этом месте?
     
  10. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Vam
    Deleted
    Не сразу врубился...
     
  11. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Vam
    В общем случае нельзя принципиально - какая именно ф-ция, зависит не только от места.
     
  12. Vam

    Vam New Member

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

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    Vam, с "точки зрения асма" видно какая функция вызывается через vtable (например 4ая в данной таблице) но не видно какой объект мы используем в данные момент. Это ж просто вызов ф-ции через указатель и содержание указателя известно только at run time.

    Если я правильно понял вопрос, то disasm должен показать что-то типа этого:
    ((SomeClass *)p)->VirtualMethod2(arg1, arg2);

    То есть имя таблицы (класс) и номер записи (метод) - больше у тебя нету, т.к. это и не было в исходнике.
     
  14. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    Что-то мы говорим на разных языках - или вы меня не понимаете, или я вас. Речь в этой теме идет о декомпиляторе с ассемблера в исходный код С++ и все вопросы связаны с его созданием.
    Зачем мне это делать, когда это уже сделано. В Ида загружен исследуемый экзешник с отладочной информацией, следовательно весь ассемблерный код доступен.
    Такая функция тоже есть (если интересно - можете потестировать, условия выше...), только делает она не дизасм, а декомпиляцию кода. Но надо иметь в виду, что не каждая функция в этом режиме может быть правильно декомпилирована, для правильной декомпиляции некоторых функций, в том числе и с описанной проблемой, необходимо сначала определить (найти, восстановить и т.д.) некоторые типы переменных, т.к. даже в полной отладочной инфе некоторых типов переменных нет. Причем восстановление типа может быть прямым или косвенным. Прямое определяется по присвоению переменных, косвенное - по сравнению, по вызову функций и другие. Но в моем вопросе тип переменной уже известен - void*, вопрос в том, как определить к какому типу (указателя на класс) он был явно преобразован в исходнике, т.к. декомпилятор встретив такую ситуацию не может для типа void* найти виртуальную таблицу, выдает ошибку и пропускает эту функцию.
    s0larian
    Конечно - это так.
    Тоже понятно, только вопрос в том, как определить содержимое указателя без run time?
    Да, только не disasm, а декомпилятор - в созданном им исходнике должна быть именно такая запись.
    Не понял смысл предложения (оборот какой-то неправильный).
    Что есть, то есть - в исходнике было: ((zSTRING*)m_pObject)->RefreshData(TRUE);
    После декомпиляции VC, на ассемблере видим:
    Код (Text):
    1. .text:007689EB                 mov     edx, [ebp+var_10]
    2. .text:007689EE                 mov     eax, [edx+18h]
    3. .text:007689F1                 mov     [ebp+var_20], eax
    4. .text:007689F4                 mov     ecx, [ebp+var_20]
    5. .text:007689F7                 mov     [ebp+var_1C], ecx
    6. .text:007689FA                 cmp     [ebp+var_1C], 0
    7. .text:007689FE                 jz      short loc_768A1A
    8. .text:00768A00                 mov     esi, esp
    9. .text:00768A02                 push    1
    10. .text:00768A04                 mov     edx, [ebp+var_1C]
    11. .text:00768A07                 mov     eax, [edx]
    12. .text:00768A09                 mov     ecx, [ebp+var_1C]
    13. .text:00768A0C                 call    dword ptr [eax]
    Хочу, чтобы декомпидятор по возможности правильно восстановил исходник.
     
  15. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Определяем тип переменной A=[ebp+var_10] (класс, указатель на структуру).
    Определяем тип переменной B=A->m18 (видимо экземпляр требуемого класса), где-то вызывается конструктор A или создан экземпляр структуры, в любом случае тип поля видимо может быть установлен.

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

    А для этого всего нужно предварительно насквозь прошерстить программу, чтобы распространить типы.
    ЗЫ
    Судя по конструкции, что-то похожее на вызов метода интерфейса.
     
  16. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    crypto
    Уже определен - это this, указатель на класс zCPar_Symbol.
    Уже определен - void* m_pObject;
    Для "правильных" указателей на классы это так и делается. А в нашем случае указатель "неправильный" - void*. Вот в этом и весь вопрос?
    В худшем случае - да, в лучшем - нет, например, тип объекта В можно взять из отладочной инфы.
    Нет, это вызов простой виртуальной функции, запись вызова метода интерфейса будет несколько отличаться (см. добавленную строку):
    Код (Text):
    1. .text:00768A02                 push    1
    2. .text:00768A04                 mov     edx, [ebp+var_1C]
    3. .text:00768A07                 mov     eax, [edx]
    4. .text:00768A09                 mov     ecx, [ebp+var_1C]
    5.                                push     ecx
    6. .text:00768A0C                 call    dword ptr [eax]
     
  17. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Vam
    А почему он void*? Где-то должен быть вызван конструктор нужного класса TCLass. Поэтому он будет иметь тип TClass*.
     
  18. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    crypto
    Да потому, что так написано в исходниках и скомпилировано в экзешник. Если бы тип переменной был неизвестен, я бы так и сказал - не могу определить тип. Что это void* определено 100% по отладочной инфе.
     
  19. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Vam
    Где-то там за кадром осталось явное назначение типа (Class*), которое в отладочную информацию не попало, ес-но. Значит в таких вариантах остается только анализировать типы.
     
  20. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    crypto
    т.е. поступать так, как написано в посте №116? Других вариантов нет?