Вы можете искать в двоичном коде прологи функций, которые дадут вам все функции, но вы не сможете определить, какая точка входа.Гипотетически, вы также можете искать вызовы функций, а затем предполагать, что вызов, который не вызывается в объектном файле, является вашей точкой входа.Кажется немного мазохистским, но опять же, поэтому вручную загружается и вызывается объектный файл, а не обстреливается исполняемый файл или загружается DLL, и в этом случае нет необходимости знать точку входа.Вот две функции, о которых я говорил:
/*
prologue:
push ebp ; 55
mov ebp esp ; 8B EC
functionCall:
call foo ; E8 &foo
*/
const unsigned char prologueBin[] = {0x55, 0x8B, 0xEC};
const unsigned char callOpcode = 0xE8;
inline bool isThisAfunction(unsigned char* pBin) {
return (pBin[0] == prologueBin[0] && pBin[1] == prologueBin[1] && pBin[2] == prologueBin[2]);
};
inline bool isThisCall(unsigned char* pBin) {
return *pBin == callOpcode;
};
isThisCall () может вызвать много ложных срабатываний, но, поскольку вы будете использовать его для отбраковки списка функций, вызванных функцией isThisAfunction ()вряд ли удастся исключить функцию, которая на самом деле не вызывается.
По сути, я рекомендую это только в том случае, если вам действительно нужно загрузить кусок битов, о котором вы больше ничего не знаете, и вызвать его как функцию.