Para executar um “JMP” a CPU calcula o novo valor do “%IP” fazendo:

instruction_pointer = instruction_pointer + 5 + relative_offset;

Sendo ‘5’ o tamanho da instrução JMP (5 bytes).

Para hookar uma função, e desviar o fluxo do programa, precisamos calcular o offset relativo entre a função que estamos hookando (function_A) e a nossa própria função (function_B) . Revertendo a fórmula utilizada pela CPU para calcular o novo “%IP”, temos:

relative_offset = function_B - function_A - 5;

A subtração entre o endereço das duas funções acontece por se tratar de um “relative jump”. Exemplo:

function_A = 0×401000
function_B = 0×401800
 
func_B - func_A = 0×800 bytes ~Relative Offset~

Em assembly, o redirecionamento da função A para a função B fica:

Observamos que as instruções que ocupavam os bytes dos endereços ‘0x401000’, ‘0x401001’ e ‘0x401003’ foram sobrescritas. Antes do hook, esse espaço continha 3 instruções, após o hook apenas 2.

Isso acontece porque a instrução ‘JMP’ ocupa 5 bytes (as instruções podem ter tamanhos diferentes), então sozinha, ela ocupa o espaço utilizado pelas 3 instruções anteriores. As 3 instruções originais ocupam 6 bytes, enquanto que o ‘JMP’ ocupa apenas 5, isso deixa 1 byte sobrando, esta sobra é sobrescrita por um ‘NOP’ (para garantir que nenhum byte de instrução isolado cause problemas).

Esses bytes que foram sobrescritos, são chamados “stolen bytes”.

Trampoline Hook:

O ‘JMP’ no trampoline é calculado assim:

relative_offset = (function_A_trampoline + 6) - (function_A + 6) - 5;

http://jbremer.org/x86-api-hooking-demystified/#ah-abstract


🌱 Back to Garden