Linux 上自定义信号处理程序中的未知参数

逆向工程 linux 海湾合作委员会 x86-64
2021-06-13 15:32:29
   0x0000000008001946:  mov    0xa8(%rdx),%rax
   0x000000000800194d:  lea    0x28(%rdx),%rsi
   0x0000000008001951:  lea    0x2(%rax),%rdi
   0x0000000008001955:  add    $0xe,%rax
   0x0000000008001959:  mov    %rax,0xa8(%rdx)
   0x0000000008001960:  jmpq   0x8001ee0

以上是信号处理程序完整反汇编,它通常由我正在研究的程序设置,即程序注册信号处理程序并通过SIGILL使用操作码引发 a 立即调用它ud2

信号处理程序在这里注册:

   0x8001965:   push   %rbx
   0x8001966:   xor    %eax,%eax
   0x8001968:   mov    $0x26,%ecx
   0x800196d:   sub    $0xa0,%rsp
   0x8001974:   lea    0x8(%rsp),%rdi
   0x8001979:   rep stos %eax,%es:(%rdi)
   0x800197b:   lea    -0x3c(%rip),%rax        # 0x8001946
   0x8001982:   lea    0x10(%rsp),%rdi
   0x8001987:   movl   $0x8000004,0x90(%rsp)
   0x8001992:   mov    %rax,0x8(%rsp)
   0x8001997:   callq  0x8000f60 <sigfillset@plt>
   0x800199c:   xor    %edx,%edx
   0x800199e:   test   %eax,%eax
   0x80019a0:   jne    0x80019bb
   0x80019a2:   lea    0x8(%rsp),%rbx
   0x80019a7:   xor    %edx,%edx
   0x80019a9:   mov    $0x4,%edi
   0x80019ae:   mov    %rbx,%rsi
   0x80019b1:   callq  0x8000f90 <sigaction@plt>

哪里0x8001946是处理程序的地址,在第一个代码块之前被反汇编。

我的问题是关于信号处理程序的第一条指令,它似乎毫无意义,我无法调试它,因为我不能在上面放置断点:

0x0000000008001946:  mov    0xa8(%rdx),%rax

%rdx由 ABI 定义为传递给函数的第三个参数,并且由is a (强制转换结构)sigaction的第三个参数定义,但是 a 的定义中没有索引,这让我相信它是别的东西。sa_sigactionvoid *ucontext_t0xa8struct ucontext_t

我认为%rdxud2调用指令之前它可能是一个集合

   0x0000000008000fde:  test   %al,%al
   0x0000000008000fe0:  mov    $0x2,%edx
   0x0000000008000fe5:  je     0x8001028
   0x0000000008000fe7:  movslq %ebx,%rdi
   0x0000000008000fea:  mov    %rbp,%rsi
   0x0000000008000fed:  callq  0x8001190

但是在调用0x80001190(错误)之前,%rdx只包含$0x2. 所以我更糊涂了。

任何人都可以阐明%rdx引发0x8001946a 之后可能包含SIGILL内容,并将信号传递给在该地址定义的自定义处理程序?

1个回答

它似乎是%rip(的地址ud2):

#include <signal.h>
#include <stdio.h>
#include <ucontext.h>

void handler(int signo, siginfo_t *info, void *context) {
    ucontext_t *uc = (ucontext_t*)context;
    printf("%llx\n", uc->uc_mcontext.gregs[REG_RIP]);
}

编译为:

handler(int, siginfo_t*, void*):
        movq    168(%rdx), %rsi
        movl    $.L.str, %edi
        xorl    %eax, %eax
        jmp     printf
.L.str:
        .asciz  "%llx\n"

( https://gcc.godbolt.org/z/RC064L )