应用程序调试(四)————自制系统调用、编写进程查看器

一、自制系统调用
这里写图片描述

(1)Linux内核(基于Linux_2.6.22)
1、在syscalls.h中申明函数:

asmlinkage void sys_hello(const char __user * buf, int count);

2、在calls.S中加入sys_hello

/* 350 */   CALL(sys_timerfd)
        CALL(sys_eventfd)
        CALL(sys_hello)

3、在read_write.c中定义sys_hello函数

asmlinkage void sys_hello(const char __user * buf, int count)
{
    char ker_buf[100];
    if (buf)
    {
        copy_from_user(ker_buf, buf, (count < 100) ? count : 100);
        ker_buf[99] = '\0';
        printk("sys_hello: %s\n", ker_buf);
    }
}

(2)写一个应用函数test_system_call.c

#include <errno.h>
#include <unistd.h>
//#include <sysdep.h>

//#if defined(__thumb__) || defined(__ARM_EABI__)
//#define __NR_SYSCALL_BASE 0
//#else
#define __NR_SYSCALL_BASE   0x900000
//#endif

void hello(char *buf, int count)
{
    /* swi */

    asm ("mov r0, %0\n"   /* save the argment in r0 */
         "mov r1, %1\n"   /* save the argment in r0 */
         "swi %2\n"   /* do the system call */
         :  
         : "r"(buf), "r"(count), "i" (__NR_SYSCALL_BASE + 352)
         : "r0", "r1");
}

int main(int argc, char **argv)
{
    printf("in app, call hello\n");
    hello("www.100ask.net", 15);
    return 0;
}

二、编写进程查看器
这里写图片描述

使用自制的系统调用打断点(无需网络gdbserver)
主要方式:
1、 根据反汇编文件找到一条简单的指令,确定机器码(可执行文件中),把它替换为swi val。

 84cc:  e5823000    str r3, [r2]
    84d0:   e51b3010    ldr r3, [fp, #-16]
    84d4:   e2833002    add r3, r3, #2  ; 0x2 
                        // 因为这条指令比较简单
                        // 把它替换为swi指令"ef900160        swi     0x00900160"

2、执行程序(修改后的可执行文件)
3、进入sys_hello,
在sys_hello中打印信息,
执行原来的指令,
返回。

asmlinkage void sys_hello(const char __user * buf, int count)
{
    static int cnt = 0;
    int val;
    int ret;
    struct pt_regs *regs; 

    /* 1. 输出一些调试信息 */
    /* 应用程序test_sc的反汇编里:       0001078c <cnt>: */
    /* 应用程序test_sc_sleep的反汇编里: 000107c8 <cnt>: */
//  copy_from_user(&val, (const void __user *)0x0001078c, 4);
    copy_from_user(&val, (const void __user *)0x000107c8, 4);
    printk("sys_hello: cnt = %d\n", val);


    /* 2. 执行被替换的指令: add r3, r3, #2  ; 0x2 */
    /* 搜 pt_regs , 在它的结果里再搜 current */
    regs = task_pt_regs(current);
    regs->ARM_r3 += 2;

    /* 打印局部变量i */
    copy_from_user(&val, (const void __user *)(regs->ARM_fp - 16), 4);
    printk("sys_hello: i = %d\n", val);

    /* 3. 返回 */
    if (++cnt == 5)
    {
        copy_from_user(&val, (const void __user *)0x8504, 4);
        printk("[0x8504] code = 0x%x\n", val);
        printk("regs->ARM_lr  = 0x%x\n", regs->ARM_lr);
        val = 0xe2833002;
        //if (copy_to_user((const void __user *)0x8504, &val, 4))
        //  printk("restore code error!\n");
        ret = access_process_vm(current, 0x8504, &val, 4, 1);
        printk("access_process_vm ret = %d\n", ret);

        cnt = 0;
    }

    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值