android - IDA 调试 Android 内核 - 查找 check_flags() 地址
问题描述
IDA 的新手,不确定我看到的是正确还是错误。
从我的手机(aarch64,三星 S7 Edge)加载 zImage 内核图像。加载 kallsyms,将其添加到 IDA
想用ptmx_fops地址覆盖check_flags,通过反转fcntl syscall得到check_flags偏移量
试图找到这里使用的 check_flags() 函数的偏移量:
fs/fcntl.c
#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
static int setfl(int fd, struct file * filp, unsigned long arg)
{
struct inode * inode = file_inode(filp);
int error = 0;
/*
* O_APPEND cannot be cleared if the file is marked as append-only
* and the file is open for write.
*/
if (((arg ^ filp->f_flags) & O_APPEND) && IS_APPEND(inode))
return -EPERM;
/* O_NOATIME can only be set by the owner or superuser */
if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME))
if (!inode_owner_or_capable(inode))
return -EPERM;
/* required for strict SunOS emulation */
if (O_NONBLOCK != O_NDELAY)
if (arg & O_NDELAY)
arg |= O_NONBLOCK;
if (arg & O_DIRECT) {
if (!filp->f_mapping || !filp->f_mapping->a_ops ||
!filp->f_mapping->a_ops->direct_IO)
return -EINVAL;
}
if (filp->f_op->check_flags)
error = filp->f_op->check_flags(arg);
if (error)
return error;
/*
* ->fasync() is responsible for setting the FASYNC bit.
*/
if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op->fasync) {
error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
if (error < 0)
goto out;
if (error > 0)
error = 0;
}
spin_lock(&filp->f_lock);
filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK);
spin_unlock(&filp->f_lock);
out:
return error;
}
听说:
fcntl.c 的 setfl() 中使用了 check_flags 函数。大多数时候它内联在 sys_fcntl 中,因此您可以从 kallsyms 中找到该地址并从那里找到它。
在 IDA 但是我看到了这个:
问题:
- 如何在这里找到 check_flags() 的偏移量(在代码中:)
if (filp->f_op->check_flags)
?使用什么方法? - 为什么反汇编指向 unk_* 部分?他们指向 DCB 的位置?那些是什么?
- 试图做一个快捷方式
也有内核的源代码并尝试导出
fs/btrfs/ioctl.c
static int check_flags(unsigned int flags)
{
if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
FS_NOATIME_FL | FS_NODUMP_FL | \
FS_SYNC_FL | FS_DIRSYNC_FL | \
FS_NOCOMP_FL | FS_COMPR_FL |
FS_NOCOW_FL))
return -EOPNOTSUPP;
if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL))
return -EINVAL;
return 0;
}
EXPORT_SYMBOL(check_flags);
重新编译,但符号不在 vmlinux 和 System.map 中:/
内核配置:
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
有任何想法吗?
也许这也有帮助:
驱动程序/tty/pty.c
static struct file_operations ptmx_fops;
ptmx_fops.open = ptmx_open;
知道如何计算 check_flags 的偏移量:
驱动程序/tty/pty.c
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
int (*iterate) (struct file *, struct dir_context *);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **, void **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
int (*show_fdinfo)(struct seq_file *m, struct file *f);
struct file* (*get_lower_file)(struct file *f);
};
更新1:
静态结构文件操作ptmx_fops;
ptmx_fops.open = ptmx_open;
该结构似乎有 15 个字节大
/usr/bin/aarch64-linux-gnu-nm -a --target elf64-littleaarch64 vmlinux| grep ptmx_fops
ffffffc00229aa00 b ptmx_fops
ffffffc00229aaf0 b ptmx_fops2
在这里,我在 drivers/tty/pty.c 中将 check_flags 导出为静态
/usr/bin/aarch64-linux-gnu-nm -a --target elf64-littleaarch64 vmlinux| grep check_flags
ffffffc0001aa098 t bad_file_check_flags
ffffffc0003ff854 t check_flags
ffffffc0001a0c04 T fiemap_check_flags
ffffffc00042416c t kbase_check_flags
但是我想用系统一.....那么如何在struct中找到15字节的check_flags是哪个字节呢?
更新 2
Puuuuuh ...我做到了...将我的自定义内核上传到三星S7 Edge ....现在我可以调试它了
更新 3
其实我成功了
解决方案
推荐阅读
- maven - 不使用 settings.xml 中提供的镜像
- oracle - 通过单击 Oracle 表单上的按钮并下载输出来调用 XML 报告
- c# - 如何从像axb这样的文本中获取a和b值?
- node.js - 乘客未启动节点应用程序
- azure - 在文件名中使用通配符 (*) 时,无法从 Azure 数据工厂中的 SFTP 复制文件
- jsp - 如何删除 index.jsp 在 URL 中的显示?
- javascript - Javascript更改svg g路径元素的背景颜色
- excel - VBA中的for循环
- sockets - 如何在一个套接字 C++ 中发送和接收多个文件大小?
- grep - 如何每行grep多个模式