5バイトのジャンプを挿入する基本的なx86メソッドを使用して関数にフックを書き込んでいます。私のコードは錆びているが、私はロジックがあると思う。私は、LD_PRELOAD env varに対して実行すると、セグメンテーションフォールトエラーが発生します。基本的には、置換機能、フック関数、トランポリン関数を使用して元のアドレスを修正して返します。以下はコードリンクです。mprotectを使用してメモリを保護するためのLinux書き込みジャンプ
foo.hという
#ifndef foo_h__
#define foo_h__
extern void foo(const char*);
#endif // foo_h_
foo.cの
#include <stdio.h>
void foo(const char*str)
{
puts(str);
}
main.cの
#include <stdio.h>
#include "foo.h"
int main(void)
{const char*str="I am a shared lib!\n";
int count=1;
puts("This is a shared library test...");
while(count!=200){
printf("%d time!\n",count);
foo(str);
count++;
}
return 0;
}
hook.c
# include <stdio.h>
# include <unistd.h>
# define __USE_GNU
# include <dlfcn.h>
# include <stdint.h>
# include <sys/mman.h>
const char*str = "Hooked! ma fucker!\n";
struct hookdata
{
int64_t*origFunc;
int64_t*newFunc;
const char*s;
void (*foo_trampoline)(const char*str);
}*hkd;
void fooHooked(const char*str)
{
puts(str);
hkd->foo_trampoline(hkd->s);
}
void hook(void)
{
//Get pointers to the original and new functions and calculate the jump offset
hkd->origFunc = dlsym(RTLD_NOW, "foo");
hkd->newFunc = (int64_t*) &fooHooked;
int64_t offset = hkd->newFunc - (hkd->origFunc + 5);
//Make the memory containing the original funcion writable
//Code from http://stackoverflow.com/questions/20381812/mprotect-always-returns-invalid-arguments
size_t pageSize = sysconf(_SC_PAGESIZE);
uintptr_t start = (uintptr_t) hkd->origFunc;
uintptr_t end = start + 1;
uintptr_t pageStart = start & -pageSize;
mprotect((void *) pageStart, end - pageStart,
PROT_READ | PROT_WRITE | PROT_EXEC);
//Insert the jump instruction at the beginning of the original function
int32_t instruction = 0xe9 | offset << 8;
*hkd->origFunc = instruction;
}
void foo(const char*str)
{
if (*hkd->origFunc == 0xe9)
{
printf("hook detected!");
}
else
hook();
}
'int64_t'がポインタを保持することは保証されません。また、関数ポインタの整数への変換は、標準のように未定義の動作であり、一旦それらが(ファンクション)ポインタにキャストされると、そのような整数値に対する算術演算である。少なくとも、あなたはそのようなポインタを保持するために専用の型を使うべきです。(算術演算なしで) 'uintptr_t'(ポインタの符号付き整数の使用も悪い考えです;ポインタは定義によっては符号なしです)。それは言った:どのようにあなたのarithmetics作品を知っていますか?マシンコードをチェックしましたか?デバッガは何を言いますか? – Olaf
この方法は設計上の問題です。 OSの保護だけでなく、コンパイラもあります。あなたはこのハックでどの問題を解決しようとしていますか?なぜコンプライアンス・アプローチを使用せず、コンパイラに潜在的な最適化を任せますか? – Olaf