Новичок в IDA, не уверен, что то, что я вижу, является правильным или неправильным.
Загруженное изображение ядра zImage с моего телефона (aarch64, Samsung S7 Edge). Загруженные kallsyms, добавленные в IDA
Хотите использовать адрес ptmx_fops и перезаписать check_flags, получить смещение check_flags путем обращения к syscall fcntl
Попытка найти смещение функции 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;
}
Слышал, что:
Функция check_flags используется в setfl () из fcntl.c. Большую часть времени он встроен в 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
Есть идеи?
Может быть, это также поможет:
drivers / tty / pty.c
static struct file_operations ptmx_fops;
ptmx_fops.open = ptmx_open;
Любая идея, как определить смещение check_flags:
drivers / 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:
статическая struct file_operations 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
Здесь я экспортировал check_flags как статические в драйверах / tty / pty.c
/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
Но я хочу использовать системный ..... Итак, как найти, какой байт является check_flags 15 байтов в структуре?
Обновление 2
Puuuuuh ... Я сделал это ... загрузил мой Custom Kernel вSamsung S7 Edge .... теперь я могу отладить его
Обновление 3
На самом деле мне удалось
https://github.com/marcinguy/CVE-2019-2215#update-5