# #c #x86 #reverse-engineering #decompiling #ghidra
Вопрос:
Анализируя список сборок в Гидре, я наткнулся на эту инструкцию:
CALL dword ptr [EBX*0x4 0x402ac0]=gt;DAT_00402abc
Я предположил , что программа вызывала функцию, адрес которой находился внутри DAT_00402abc
, и я сначала подумал, что это переменная dword. Действительно, при попытке создать функцию в том месте, где DAT_00402abc
она находится, Гидра не позволила бы мне это сделать.
Декомпилятор показывает мне эту строку кода для перевода этой инструкции:
(*(code *)(amp;int2)[iVar2])();
Поэтому мне было интересно, что это значит и что программа должна делать с этим вызовом? Есть ли вероятность, что Гидра полностью облажался? И если да, то как я должен интерпретировать эту инструкцию?
Ответ №1:
Я совсем не знаком с Гидрой, но могу рассказать вам, как интерпретировать машинную инструкцию…
CALL dword ptr [EBX*0x4 0x402ac0]
Существует таблица адресов функций по адресу 0x402ac0
; вызывается запись EBX в этой таблице. Я понятия не имею, что DAT_00402abc
это значит, но если вы проверите память в блоках размером с dword по адресу 0x0402ac0
, вы должны найти правдоподобные адреса функций. [РЕДАКТИРОВАТЬ: 0x0040_2abc = 0x0040_2ac0 — 4. Я подозреваю, что это означает, что Гидра считает, что EBX имеет значение -1, когда контроль достигает этой точки. Это может быть неправильно, или, может быть, в программе есть ошибка. Можно было бы ожидать, что EBX будет иметь неотрицательное значение, когда контроль достигнет этой точки.]
Естественный исходный код C, соответствующий этой инструкции, будет выглядеть примерно так
extern void do_thing_zero(void); extern void do_thing_one(void); extern void do_thing_two(void); extern void do_thing_three(void); typedef void (*do_thing_ptr)(void); const do_thing_ptr do_thing_table[4] = { do_thing_zero, do_thing_one, do_thing_two, do_thing_three }; // ... void do_thing_n(unsigned int n) { if (n gt;= 4) abort(); do_thing_table[n](); }
Если функции в таблице принимают аргументы или возвращают значения, вы увидите код передачи аргументов до и после приведенной вами инструкции ВЫЗОВА, но сама инструкция ВЫЗОВА не изменится.
Вы бы увидели что-то другое и гораздо более сложное, если бы все функции не принимали один и тот же набор аргументов.