termux / proot

An chroot-like implementation using ptrace.
https://wiki.termux.com/wiki/PRoot
Other
775 stars 160 forks source link

How do I know which function has called the kill method via svc? #223

Closed w296488320 closed 2 years ago

w296488320 commented 2 years ago

I found a function that calls the kill function via svc and I want to know where the kill is called, I tried to intercept by ptrace and judging by the system call number if it was a kill function I tried to print his FP register but get 0 .

        case SC_kill: {
            word_t LRAddress = peek_reg(tracee, CURRENT, SYSARG_RESULT);
            word_t PCAddress = peek_reg(tracee, CURRENT, INSTR_POINTER);
            word_t SPAddress = peek_reg(tracee, CURRENT, STACK_POINTER);
            word_t FPAddress = peek_reg(tracee, CURRENT, FRAME_POINTER);

            LOGE(">>>>>>>>>  ptrace find call kill by svc , sig -> %lu "
                 "LR reg address -> 0x%lX  "
                 "PC reg address -> 0x%lX  "
                 "栈顶 SP reg address -> 0x%lX  "
                 "栈底 FP reg address -> 0x%lX  ",
                 peek_reg(tracee, CURRENT, SYSARG_2),
                 LRAddress,
                 PCAddress,
                 SPAddress,
                 FPAddress
            )

             mapItemInfo info = getSymbolforAddress(LRAddress, tracee->pid);
             LOGE(">>>>>>>>>  ptrace call kill LR so name  -> %s ,start addr -> %zu ",
                     info.mapsName,
                     info.start
             )

I add the reg.cpp to the original one ARCH_ARM64 -> [FRAME_POINTER] = USER_REGS_OFFSET(regs[29]), ARCH_ARM_EABI -> [FRAME_POINTER] = USER_REGS_OFFSET(uregs[12]),

#elif defined(ARCH_ARM_EABI)
static off_t reg_offset[] = {
        [SYSARG_NUM]    = USER_REGS_OFFSET(uregs[7]),
        [SYSARG_1]      = USER_REGS_OFFSET(uregs[0]),
        [SYSARG_2]      = USER_REGS_OFFSET(uregs[1]),
        [SYSARG_3]      = USER_REGS_OFFSET(uregs[2]),
        [SYSARG_4]      = USER_REGS_OFFSET(uregs[3]),
        [SYSARG_5]      = USER_REGS_OFFSET(uregs[4]),
        [SYSARG_6]      = USER_REGS_OFFSET(uregs[5]),
        [SYSARG_RESULT] = USER_REGS_OFFSET(uregs[0]),
        [STACK_POINTER] = USER_REGS_OFFSET(uregs[13]),
        [INSTR_POINTER] = USER_REGS_OFFSET(uregs[15]),
        [USERARG_1]     = USER_REGS_OFFSET(uregs[0]),
        [FRAME_POINTER]     = USER_REGS_OFFSET(uregs[12]),
};
#elif defined(ARCH_ARM64)
#undef  USER_REGS_OFFSET
#define USER_REGS_OFFSET(reg_name) offsetof(struct user_regs_struct, reg_name)

static off_t reg_offset[] = {
[SYSARG_NUM]    = USER_REGS_OFFSET(regs[8]),
[SYSARG_1]      = USER_REGS_OFFSET(regs[0]),
[SYSARG_2]      = USER_REGS_OFFSET(regs[1]),
[SYSARG_3]      = USER_REGS_OFFSET(regs[2]),
[SYSARG_4]      = USER_REGS_OFFSET(regs[3]),
[SYSARG_5]      = USER_REGS_OFFSET(regs[4]),
[SYSARG_6]      = USER_REGS_OFFSET(regs[5]),
[SYSARG_RESULT] = USER_REGS_OFFSET(regs[0]),
[STACK_POINTER] = USER_REGS_OFFSET(sp),
[INSTR_POINTER] = USER_REGS_OFFSET(pc),
[USERARG_1]     = USER_REGS_OFFSET(regs[0]),
[FRAME_POINTER]     = USER_REGS_OFFSET(regs[29]),
};

I don t know if it s because I write wrong causing the FP register is equal 0 or the original FP register is equal 0。 Do you have any good advice?Great developer

michalbednarski commented 2 years ago

regs[29] appears to be correct place for FRAME_POINTER on AArch64 (when both proot and tracee are 64bit), however depending on programming language and compiler (e.g. when using gcc -fomit-frame-pointer) frame pointer might not be present

I'd recommend attaching debugger to target inside proot (with debugger also running inside proot) and seeing what registers are set to

If you want to stop program at point of particular syscall do kill(tracee->pid, SIGSTOP) (assuming single-threaded program, you'll need to adapt snippet otherwise) at moment of handling particular syscall and then check registers using debugger inside proot