関数の戻りアドレスを取得するために EBP/RBP の内容が必要です。このアドレスは、スタック フレーム内の 8(%RBP) の位置にある必要があります (x86_64 ビット アーキテクチャのみを考えてみましょう)。
シグナル ハンドラに渡される ucontex_t 構造体からこの値を取得しますが、プログラムは非常に奇妙な動作をします。RBP レジスタに含まれる値がまったく意味をなさない場合 (たとえば、0x00、0x01) や、正しいスタック ベース値が含まれている場合があります。もちろん、この動作はいくつかのアプリケーションのクラッシュを引き起こします。
呼び出し元関数のアドレスを知りたいので、関数の戻りアドレスを取得する必要があります。
これは私が使用しているコードです:
syscall = ctx->uc_mcontext.gregs[REG_SYSCALL];
pc=ctx->uc_mcontext.gregs[REG_PC];
stack=ctx->uc_mcontext.gregs[REG_STACK];
stack_base=ctx->uc_mcontext.gregs[REG_BASE];
function_address=get_function_address((char *)stack_base);
DPRINT(DEBUG_INFO, "Received SYS_SECCOMP signal : syscall %lu\n", syscall);
DPRINT(DEBUG_ALL, "Syscall instruction address %p\n", info->si_call_addr);
DPRINT(DEBUG_ALL, "PC 0x%lx, BASE_STACK 0x%lx, Stack 0x%lx\n", pc, stack_base, stack);
DPRINT(DEBUG_ALL, "Syscall number %d\n", info->si_syscall);
DPRINT(DEBUG_ALL, "Syscall arch %u\n", info->si_arch);
マクロは次のように定義されます。
#define REG_SYSCALL REG_RAX
#define REG_PC REG_RIP
#define REG_BASE REG_RBP
#define REG_STACK REG_RSP
前のコードの出力の例: 正しい値:
[DEBUG_INFO] Received SYS_SECCOMP signal : syscall 3
Syscall instruction address 0x7fa058d67452
PC 0x7fa058d67452, BASE_STACK 0x7fff145c1d00, Stack 0x7fff145c1bc0
Syscall number 3
Syscall arch 3221225534
間違った値:
[DEBUG_INFO] Received SYS_SECCOMP signal : syscall 78
Syscall instruction address 0x7fa058df2495
PC 0x7fa058df2495, BASE_STACK 0xffffffffffffffa8, Stack 0x7fff145c1ed0
Syscall number 78
Syscall arch 3221225534
さらに悪いことに:
[DEBUG_INFO] Received SYS_SECCOMP signal : syscall 3
Syscall instruction address 0x7fa058e18360
PC 0x7fa058e18360, BASE_STACK 0x0, Stack 0x7fff145c1e68
Syscall number 3
Syscall arch 3221225534
RBP にゼロが含まれている場合、アプリケーションが終了するまで同じ値が保持されることに気付きました。