cscg24-haunted

CSCG 2024 Challenge 'Haunted'
git clone https://git.sinitax.com/sinitax/cscg24-haunted
Log | Files | Refs | sfeed.txt

HelloWorld.c (6419B)


      1#include "Base.h"
      2#include "ProcessorBind.h"
      3#include <Uefi.h>
      4#include <Library/PcdLib.h>
      5#include <Library/UefiLib.h>
      6#include <Library/UefiApplicationEntryPoint.h>
      7
      8#define INTEL_ASM(x, ...) asm volatile \
      9	(".intel_syntax noprefix;" x ";.att_syntax prefix" : __VA_ARGS__)
     10
     11UINT64
     12gcd(UINT64 a, UINT64 b)
     13{
     14	while (a != b) {
     15		if (a > b) {
     16			a -= b;
     17		} else {
     18			b -= a;
     19		}
     20	}
     21
     22	return a;
     23}
     24
     25UINT64
     26digitsum(UINT64 a)
     27{
     28	UINT64 sum = 0;
     29
     30	while (a > 0) {
     31		sum += a % 10;
     32		a /= 10;
     33	}
     34
     35	return sum;
     36}
     37
     38void
     39register_handler(UINT8 no, UINT64 offset)
     40{
     41	char buf[0x10];
     42	UINT16 cs;
     43
     44	INTEL_ASM("movw %[cs], cs;", [cs]"=r"(cs));
     45
     46	UINT64 lower = ((offset & 0xffff0000UL) << 32)
     47		| (0b1ULL << 47) /* P = 1 */
     48		| (0b1110ULL << 40) /* Interrupt gate */
     49		| ((UINT64)cs << 16) /* Segment */
     50		| (offset & 0xffffUL); /* low offset */
     51	UINT64 upper = (offset >> 32) & 0xffffffff;
     52
     53	INTEL_ASM(
     54		"sidt [rsp];"
     55		"movq rax, 2[rsp];"
     56		"xor ebx, ebx;"
     57		"movb bl, %[no];"
     58		"shl rbx, 4;"
     59		"add rax, rbx;"
     60		"movq [rax], %[lower];"
     61		"movq 8[rax], %[upper];",
     62		[buf]"+m"(buf)
     63		: [lower]"r"(lower), [upper]"r"(upper), [no]"r"(no)
     64		: "rax", "rbx");
     65}
     66
     67EFI_STATUS
     68EFIAPI
     69UefiMain (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
     70{
     71	UINT64 rax, rbx, rcx, rdx, res;
     72	UINT32 eax, ebx;
     73	UINT16 ocs;
     74
     75	Print ((CHAR16 *)PcdGetPtr (PcdHelloWorldPrintString));
     76
     77	// _start is already 0x1000 aligned..
     78	// INTEL_ASM(".align 0x10000;");
     79
     80	*(UINT64 *)(0x4000) = 0xe6ff; // jmp rsi trampoline
     81
     82	INTEL_ASM("jmp after_handler;");
     83
     84	INTEL_ASM(
     85		"handler:"
     86		"movq [0x3ff8], rax;"
     87		"iretq;");
     88
     89	UINT64 addr;
     90	INTEL_ASM("after_handler: lea %[addr], handler[rip]",
     91		[addr]"=r"(addr));
     92
     93	register_handler(0x69, addr);
     94
     95	INTEL_ASM(
     96		// Setup CS+EIP of our segment.
     97		"lea rax, post%=[rip]; push rax;"
     98		"xor eax, eax; movw ax, cs; movd 4[rsp], eax;"
     99		// Set magic value + 1.
    100		"movq rdi, 0xfef0000013ffffff;"
    101		// Loop until interrupt.
    102		"loop%=: jmp loop%=; nop; nop;"
    103		// Switch to original segment.
    104		"movw di, cs; retfd; .code64; post%=:"
    105		// Save registers.
    106		"movw %[ocs], di;"
    107		"push rax; push rbx; push rcx; push rdx;"
    108		"pop %[rdx]; pop %[rcx]; pop %[rbx]; pop %[rax];",
    109		[rax]"=r"(rax), [rbx]"=r"(rbx),
    110		[rcx]"=r"(rcx), [rdx]"=r"(rdx),
    111		[ocs]"=r"(ocs)
    112		: : "rax", "rbx", "rcx", "rdx", "rdi");
    113
    114	for (int i = 0; i < 69; i++) {
    115		res = gcd(rax | (rbx << 32), rcx | (rdx << 32));
    116		eax = res;
    117		ebx = res >> 32;
    118
    119		if (i == 68) break;
    120
    121		INTEL_ASM(
    122			// Setup CS+EIP of our segment.
    123			"lea rax, post%=[rip]; push rax;"
    124			"xor eax, eax; movw ax, cs; movd 4[rsp], eax;"
    125			// Setup CS+EIP of other segment.
    126			"lea rax, pre%=[rip]; push rax;"
    127			"xor eax, eax; movw ax, %[ocs]; movd 4[rsp], eax;"
    128			// Set calculation result.
    129			"movd eax, %[eax]; movd ebx, %[ebx];"
    130			// Switch to other segment.
    131			"retfd; .code32; pre%=:"
    132			// Set magic.
    133			"movd ecx, 0xfefefefe;"
    134			// Loop until interrupt.
    135			"loop%=: jmp loop%=; nop; nop;"
    136			// Switch to original segment.
    137			"movw di, cs; retfd; .code64; post%=:"
    138			// Save registers.
    139			"movw %[ocs], di;"
    140			"push rax; push rbx; push rcx; push rdx;"
    141			"pop %[rdx]; pop %[rcx]; pop %[rbx]; pop %[rax];",
    142			[rdx]"=r"(rdx), [rcx]"=r"(rcx),
    143			[rbx]"=r"(rbx), [rax]"=r"(rax),
    144			[ocs]"+r"(ocs)
    145			: [eax]"r"(eax), [ebx]"r"(ebx)
    146			: "rax", "rbx", "rcx", "rdx", "rdi");
    147	}
    148
    149	INTEL_ASM(
    150		// Setup CS+IP of our segment.
    151		"lea rax, post%=[rip]; movq rsi, rax; push 0x4000;"
    152		"movw ax, cs; movw 2[rsp], ax;"
    153		// Setup CS+EIP of other segment.
    154		"lea rax, pre%=[rip]; push rax;"
    155		"xor eax, eax; movw ax, %[ocs]; movd 4[rsp], eax;"
    156		// Set calculation result.
    157		"movd eax, %[eax]; movd ebx, %[ebx];"
    158		// Switch to other segment.
    159		"retfd; .code32; pre%=:"
    160		// Set magic.
    161		"movd ecx, 0xfefefefe;"
    162		// Loop until interrupt.
    163		"loop%=: jmp loop%=; .rept 256; nop; .endr;"
    164		// Switch to original segment.
    165		".code16; movw di, cs; retfw; .code64; post%=:"
    166		// Fixup stack misalignment.
    167		"add rsp, 4;"
    168		// Save registers.
    169		"movw %[ocs], di;"
    170		"push rax; push rbx; push rcx; push rdx;"
    171		"pop %[rdx]; pop %[rcx]; pop %[rbx]; pop %[rax];",
    172		[rdx]"=r"(rdx), [rcx]"=r"(rcx),
    173		[rbx]"=r"(rbx), [rax]"=r"(rax),
    174		[ocs]"+r"(ocs)
    175		: [eax]"r"(eax), [ebx]"r"(ebx)
    176		: "rax", "rbx", "rcx", "rdx", "rdi", "rsi");
    177
    178	for (int i = 0; i < 420; i++) {
    179		eax = digitsum((rax & 0xffff) | ((rbx & 0xffff) << 16));
    180
    181		if (i == 419) break;
    182
    183		INTEL_ASM(
    184			// Setup CS+IP of our segment.
    185			"lea rax, post%=[rip]; movq rsi, rax; push 0x4000;"
    186			"movw ax, cs; movw 2[rsp], ax;"
    187			// Setup CS+EIP of other segment.
    188			"lea rax, pre%=[rip]; and rax, 0xffff; push rax;"
    189			"xor eax, eax; movw ax, %[ocs]; movd 4[rsp], eax;"
    190			// Set calculation result.
    191			"movd eax, %[eax];"
    192			// Switch to other segment
    193			"retfd; pre%=: .code16; "
    194			// Set magic (movw cl, 0xfefe is not 16-bit mode compat).
    195			"movb cl, 0xfe; movb ch, 0xfe;"
    196			// Loop until interrupt.
    197			"loop%=: jmp loop%=; nop; nop;"
    198			// Switch to original segment.
    199			"movw di, cs; retfw; post%=: .code64;"
    200			// Fixup stack misalignment.
    201			"add rsp, 4;"
    202			// Save registers.
    203			"movw %[ocs], di;"
    204			"push rax; push rbx; push rcx; push rdx;"
    205			"pop %[rdx]; pop %[rcx]; pop %[rbx]; pop %[rax];",
    206			[rdx]"=r"(rdx), [rcx]"=r"(rcx),
    207			[rbx]"=r"(rbx), [rax]"=r"(rax),
    208			[ocs]"+r"(ocs)
    209			: [eax]"r"(eax)
    210			: "rax", "rbx", "rcx", "rdx", "rsi", "rdi");
    211	}
    212
    213	INTEL_ASM(
    214		// Setup CS+EIP of other segment.
    215		"lea rax, pre%=[rip]; and rax, 0xffff; push rax;"
    216		"xor eax, eax; movw ax, %[ocs]; movd 4[rsp], eax;"
    217		// Set calculation result.
    218		"movd eax, %[eax];"
    219		// Switch to other segment
    220		"retfd; pre%=: .code16; "
    221		// Set magic (movw cl, 0xfefe is not 16-bit mode compat).
    222		"movb cl, 0xfe; movb ch, 0xfe;"
    223		// Loop until interrupt.
    224		"loop%=: jmp loop%=; .code64;",
    225		: [eax]"r"(eax), [ocs]"r"(ocs)
    226		: "rax", "rbx", "rcx", "rdx");
    227
    228	INTEL_ASM(
    229		// Move rdx from interrupt.
    230		"movq rdx, [0x3ff8];"
    231		// Set magic.
    232		"mov rcx, 0x12310FFAFFFFFFFF;"
    233		// Loop until interrupt.
    234		"loop2%=: jmp loop2%=;"
    235		// Finally, flag.
    236		"mov rax, 0x420; syscall",
    237		: : "rcx", "rdx");
    238
    239	// Interrupt 0x69 gets called in loop after interrupt code injection.
    240
    241	return EFI_SUCCESS;
    242}