Всем желающим, но не более 10 человек, предлагается протестировать программу на следующих условиях: 1. Наличие IDA v5.2 2. Наличие Win32 экзешника, компилированного VS любой версии, с отладочной информацией, желательно самописного. 3. В течение месяца после инсталляции произвести тестирование программы и выслать отчет, т.к. только в течение этого времени программа будет полностью работоспособна. 4. Содержание отчета: - найденные ошибки, баги, глюки и пр. - пожелания, что должно быть изменено. - заархивированное содержимое папки ErrorLogs тестируемого проекта, при условии, что размер архива не более 2 Мб. 5. Запрещается передача программы другому лицу, публикование и распространение. Если вы согласны с этими условиями, то пишем в приват и сообщаем свой email, на который будет выслана программа и небольшое руководство в виде readme.
Пока только win32 exe, т.е. в исследуемом файле должнв быть функция, WinMain или main, за которую программа и цепляется.
Есть ли в VC утилитах или в библиотеках или в IDA функция, которая из простых имен делает манглед имена. PS: Для обратного преобразования используется UnDecorateSymbolName.
Есть ли в VC утилитах или в библиотеках или в IDA функция, которая из простых имен делает манглед имена. для того, чтобы декорировать имя функции надо знать типы аргументов, ей передаваемых. в иде такого не видел. Да и потом декорировать тоже по-разному можно. Насколько мне известно разные компилеры это по-разному делают.
a1tus Знаю, но я спрашиваю про конкретный компилятор - VS. Должна же где-то быть прямая функция, если есть обратная - UnDecorateSymbolName.
nobodyzzz Там только частичное описание, до полного ему очень далеко. Ладно, если нет готовой функции, то придется написать свою. Мне манглед имя нужно только для одной цели - получение адреса таблицы виртуальных функций класса. Может кто предложит другой способ поиска этой таблицы.
Встретил "неразрешимую" ситуацию: есть переменная (неважно какая - локальная, классовая и т.д.) типа void* ptClass; в контексте некоторой функции она используется как ((SomeClass*)ptClass)->SomeFunc(...); где SomeFunc объявлена в классе SomeClass как virtual void SomeFunc(...); Вопрос: возможно как-то (ессно по ассемблеру) определить, какая же конкретно функция вызывается в этом месте?
green Это понятно, т.к. чтобы определить виртуальную функцию при вызове нужно точно знать тип вызывающей переменной. Я спрашиваю про другое, не как по конкретному месту на ассемблере определить какая функция вызывается, а как вообще теоретически можно определить что же в этом случае вызывается. Я не верю, что это нельзя принципиально, многие исследуют программы и наверняка используют какие-либо алгоритмы определения вызова виртуальных функций, в противном случае это был бы уникальный метод скрытия защит. Первое, что приходит на ум - это отследить все присвоения этой переменной, отфильтровать указатели на классы с вирт. функциями, затем последовательная подстановка шаблона вызова функции в место вызова, далее наблюдение за стеком (аргументы) и возвращаемым значением дадут точное или приблизительное (когда под один шаблон вызова попадают несколько функций) решение. Дальнейшее разрешение ситуации для приблизительного случая может быть осуществлено интерактивностью, когда вам будут предложены несколько вариантов на выбор. Но это всё довольно сложно, хотя и реализуемо, хотелось бы увидеть и другие варианты.
Vam, с "точки зрения асма" видно какая функция вызывается через vtable (например 4ая в данной таблице) но не видно какой объект мы используем в данные момент. Это ж просто вызов ф-ции через указатель и содержание указателя известно только at run time. Если я правильно понял вопрос, то disasm должен показать что-то типа этого: ((SomeClass *)p)->VirtualMethod2(arg1, arg2); То есть имя таблицы (класс) и номер записи (метод) - больше у тебя нету, т.к. это и не было в исходнике.
Что-то мы говорим на разных языках - или вы меня не понимаете, или я вас. Речь в этой теме идет о декомпиляторе с ассемблера в исходный код С++ и все вопросы связаны с его созданием. Зачем мне это делать, когда это уже сделано. В Ида загружен исследуемый экзешник с отладочной информацией, следовательно весь ассемблерный код доступен. Такая функция тоже есть (если интересно - можете потестировать, условия выше...), только делает она не дизасм, а декомпиляцию кода. Но надо иметь в виду, что не каждая функция в этом режиме может быть правильно декомпилирована, для правильной декомпиляции некоторых функций, в том числе и с описанной проблемой, необходимо сначала определить (найти, восстановить и т.д.) некоторые типы переменных, т.к. даже в полной отладочной инфе некоторых типов переменных нет. Причем восстановление типа может быть прямым или косвенным. Прямое определяется по присвоению переменных, косвенное - по сравнению, по вызову функций и другие. Но в моем вопросе тип переменной уже известен - void*, вопрос в том, как определить к какому типу (указателя на класс) он был явно преобразован в исходнике, т.к. декомпилятор встретив такую ситуацию не может для типа void* найти виртуальную таблицу, выдает ошибку и пропускает эту функцию. s0larian Конечно - это так. Тоже понятно, только вопрос в том, как определить содержимое указателя без run time? Да, только не disasm, а декомпилятор - в созданном им исходнике должна быть именно такая запись. Не понял смысл предложения (оборот какой-то неправильный). Что есть, то есть - в исходнике было: ((zSTRING*)m_pObject)->RefreshData(TRUE); После декомпиляции VC, на ассемблере видим: Код (Text): .text:007689EB mov edx, [ebp+var_10] .text:007689EE mov eax, [edx+18h] .text:007689F1 mov [ebp+var_20], eax .text:007689F4 mov ecx, [ebp+var_20] .text:007689F7 mov [ebp+var_1C], ecx .text:007689FA cmp [ebp+var_1C], 0 .text:007689FE jz short loc_768A1A .text:00768A00 mov esi, esp .text:00768A02 push 1 .text:00768A04 mov edx, [ebp+var_1C] .text:00768A07 mov eax, [edx] .text:00768A09 mov ecx, [ebp+var_1C] .text:00768A0C call dword ptr [eax] Хочу, чтобы декомпидятор по возможности правильно восстановил исходник.
Определяем тип переменной A=[ebp+var_10] (класс, указатель на структуру). Определяем тип переменной B=A->m18 (видимо экземпляр требуемого класса), где-то вызывается конструктор A или создан экземпляр структуры, в любом случае тип поля видимо может быть установлен. Как только выяснили, какому классу принадлежит B, смотрим его таблицу виртуальных методов. А для этого всего нужно предварительно насквозь прошерстить программу, чтобы распространить типы. ЗЫ Судя по конструкции, что-то похожее на вызов метода интерфейса.
crypto Уже определен - это this, указатель на класс zCPar_Symbol. Уже определен - void* m_pObject; Для "правильных" указателей на классы это так и делается. А в нашем случае указатель "неправильный" - void*. Вот в этом и весь вопрос? В худшем случае - да, в лучшем - нет, например, тип объекта В можно взять из отладочной инфы. Нет, это вызов простой виртуальной функции, запись вызова метода интерфейса будет несколько отличаться (см. добавленную строку): Код (Text): .text:00768A02 push 1 .text:00768A04 mov edx, [ebp+var_1C] .text:00768A07 mov eax, [edx] .text:00768A09 mov ecx, [ebp+var_1C] push ecx .text:00768A0C call dword ptr [eax]
Vam А почему он void*? Где-то должен быть вызван конструктор нужного класса TCLass. Поэтому он будет иметь тип TClass*.
crypto Да потому, что так написано в исходниках и скомпилировано в экзешник. Если бы тип переменной был неизвестен, я бы так и сказал - не могу определить тип. Что это void* определено 100% по отладочной инфе.
Vam Где-то там за кадром осталось явное назначение типа (Class*), которое в отладочную информацию не попало, ес-но. Значит в таких вариантах остается только анализировать типы.