Сбивающая с толку функция

Итак, используя IDA для дизассемблирования dll, я наткнулся на эту функцию класса:

mov eax, [ecx+4]
mov eax, [eax]
retn

Я знаю, что ecx означает this, а eax — это возвращаемое значение, но я не понимаю, что оно возвращает. Любая помощь?


person 小太郎    schedule 29.06.2010    source источник


Ответы (5)


class C
{
    int a;
    int *b; // ecx+4

    int get_b()
    {
        return *b;
    }
}

Конечно, настоящий тип a и *b неизвестен, но оба они 32-битные. a также может быть указателем на VMT, если в классе есть виртуальные методы или деструкторы.

person Vladimir Panteleev    schedule 29.06.2010
comment
О, но в этом классе ecx+4 на самом деле является самой функцией в таблице vftable. Так что бы это значило...? - person 小太郎; 29.06.2010
comment
Это ничего не меняет. Указатель на vtable хранится в первом поле класса (a в моем примере). - person Vladimir Panteleev; 29.06.2010
comment
Как я смогу узнать, что такое ecx+4? - person 小太郎; 29.06.2010
comment
Ну, вы уже знаете, что это указатель на 32-битное значение. Вам придется посмотреть на другой код, чтобы увидеть, что это такое. Я бы рекомендовал посмотреть код, который вызывает эту функцию, но поскольку вы упомянули, что эта функция виртуальная, вы не сможете просто получить список перекрестных ссылок. Вы можете поместить точку останова в функцию и изучить стек вызовов, чтобы найти код, который ее вызывает. Вы также можете найти таблицу виртуальных методов класса и просмотреть другие виртуальные функции, чтобы узнать, работают ли они с этим значением. - person Vladimir Panteleev; 29.06.2010

Эта функция загружает указатель (в eax) по смещению 4 из того, на что указывает ecx. Затем следует этот указатель для загрузки 32-битного значения в eax, которое возвращается из функции.

Это то, что делает функция, но невозможно сказать, что это означает, без дополнительного контекста.

person Greg Hewgill    schedule 29.06.2010
comment
Вполне вероятно, что он возвращает первый int или элемент ссылки класса с vtable или второй элемент структуры без таковой. - person Pete Kirkham; 29.06.2010
comment
Можете ли вы показать это в синтаксисе C или C++? Hex-Rays возвращает: return **(DWORD **)(this+4); Это на самом деле то, что делает функция? - person 小太郎; 29.06.2010
comment
kotarou3, объяснил с картинкой в ​​моем ответе, следуйте за стрелками, и вы сможете конвертировать на любом языке, с которым вы знакомы. Здесь вы предполагаете, что языком является C/C++, скорее всего, C++, если вы говорите об этом, и любой другой ответ, предполагающий, что это может быть, должен предполагать конкретную среду выполнения; Я думаю (но я не уверен), что стандарты С++ не предписывают, как должна выполняться среда выполнения или даже как класс или объект выполняются на низком уровне, поэтому, если нет контекста... - person ShinTakezou; 29.06.2010

Моя сборка немного заржавела, но первая инструкция что-то загружает в EAX... что-то, на что указывает содержимое регистра ECX... но это слово (4 байта), смещенное от него. Следующая инструкция загружает (перезаписывает) EAX тем, на что указывает EAX.

Это обозначение (квадратные скобки, окружающие вторую или «исходную» операцию этих инструкций MOV (загрузка) указывает на то, что используются режимы косвенной адресации.

Я предполагаю, что это просто способ реализовать своего рода двойную косвенность. Адрес в регистре ECX может указывать на кадр стека или, возможно, на некоторый указатель атрибута C++ "this", на который вы ссылались. Этот адрес, в свою очередь, содержит адрес возвращаемого значения. Таким образом, этот код извлекает адрес в регистр, а затем использует этот адрес в регистре для извлечения значения (попутно в тот же регистр). Этот подход удобен тем, что сохраняет все остальные регистры.

(Кстати, большинство парадигм вызова функций x86 --- системные вызовы, вызовы функций DOS и т. д. оставляют коды возврата функций или системные ошибки... errno в библиотеках stdlib C, в регистре EAX).

person Jim Dennis    schedule 29.06.2010

Что за вопрос. Если ecx содержит указатель на структуру "this", вы должны точно знать, как это делается. Первый instr получает второе двойное слово, еще один указатель; что это может быть? Мы не можем знать. Этот указатель, который теперь хранится в eax, вероятно, указывает на другую структуру или что-то еще. Первое указанное значение помещается в eax, и это то, что возвращает func.

ecx    ------->    dword dataA   offset 0
                   dword dataB   offset 4

  mov eax, [ecx + 4]

eax = dataB ---->  dword dataC   offset 0

  mov eax, [eax]

eax = dataC

Что такое dataC, зависит от многих вещей, которые мы не можем знать.

person ShinTakezou    schedule 29.06.2010

Это сильно зависит от соглашения о вызовах, используемого исходным компилятором. Довольно нормальная настройка, например. MSVC должен возвращать 32-битные значения в регистре eax. Ответ @Gregs говорит, что он делает, но, как он говорит, смысл зависит от знания более подробной информации о языке реализации и компиляторе.

Если вы хотите понять дизассемблирование, попробуйте просмотреть результаты в своем собственном (C/C++) коде. Это действительно единственный способ получить представление о том, что происходит в чужих DLL.

person Pontus Gagge    schedule 29.06.2010