From d1edb4fa3a5f8c2a62532a908d2e9c3da7083ce1 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Wed, 22 Oct 2014 11:23:15 +0200 Subject: [PATCH] Initial commit: Simple Injection Target --- .gitignore | 6 ++ Makefile | 38 +++++++++++++ bochs-experiment-runner.py | 113 +++++++++++++++++++++++++++++++++++++ grub.cfg | 7 +++ linker.ld | 70 +++++++++++++++++++++++ main.c | 33 +++++++++++ startup.s | 59 +++++++++++++++++++ 7 files changed, 326 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 bochs-experiment-runner.py create mode 100644 grub.cfg create mode 100644 linker.ld create mode 100644 main.c create mode 100644 startup.s diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..792c1ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o +*/state/* +*.iso +*.elf +*.pb +main/* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0e5d553 --- /dev/null +++ b/Makefile @@ -0,0 +1,38 @@ +all: main/system.iso + +%/system.elf: %/system.o startup.o + gcc -Wl,-T linker.ld $^ -m32 -static -nostdlib -Wl,--build-id=none -o $@ + +%/system.o: %.c + mkdir -p $(shell dirname $@) + gcc $< -o $@ -O2 -std=c11 -m32 -c -ffunction-sections + +startup.o: startup.s + gcc startup.s -m32 -c -o startup.o -ffunction-sections + +%/system.iso: %/system.elf + rm -rf $(shell dirname $<)/grub + mkdir -p $(shell dirname $<)/grub/boot/grub + cp grub.cfg $(shell dirname $<)/grub/boot/grub + cp $< $(shell dirname $<)/grub/boot/system.elf + grub-mkrescue -o $@ $(shell dirname $<)/grub + + +trace-%: %/system.elf %/system.iso + python bochs-experiment-runner.py -e $< -i $(shell dirname $<)/system.iso -1 \ + -f /proj/i4ciao/tools/fail/fail-x86-tracing -- \ + -Wf,--start-symbol=os_main \ + -Wf,--save-symbol=os_main \ + -Wf,--end-symbol=stop_trace \ + -Wf,--state-file=$(shell dirname $<)/state \ + -Wf,--trace-file=$(shell dirname $<)/trace.pb -Wf,--elf-file=$< -q + +import-%: %/trace.pb + import-trace -t $< -i mem -e $(shell dirname $<)/system.elf -v $(shell dirname $<) -b mem + import-trace -t $< -i regs -e $(shell dirname $<)/system.elf -v $(shell dirname $<) -b regs --flags + import-trace -t $< -i regs -e $(shell dirname $<)/system.elf -v $(shell dirname $<) -b ip --no-gp --ip + import-trace -v $(shell dirname $<) -b %% + + +# Do never remove implicitly generated stuff +.SECONDARY: diff --git a/bochs-experiment-runner.py b/bochs-experiment-runner.py new file mode 100644 index 0000000..d8f9759 --- /dev/null +++ b/bochs-experiment-runner.py @@ -0,0 +1,113 @@ +#!/usr/bin/python + +import os, sys +from optparse import OptionParser +from subprocess import * +from tempfile import mkstemp, mkdtemp +import shutil + + +def parseArgs(): + parser = OptionParser() + parser.add_option("-e", "--elf-file", dest="elf_file", + help="elf file to be executed", metavar="ELF") + parser.add_option("-i", "--iso-file", dest="iso_file", + help="iso file to be executed", metavar="ISO") + parser.add_option("-f", "--fail-client", dest="fail_client", + help="fail-client to be executed", metavar="ISO") + parser.add_option("-m", "--memory", dest="memory", default="16", + help="memory for the bochs VM", metavar="SIZE") + + parser.add_option("-b", "--bios", dest="bios", default="/proj/i4ciao/tools/fail/BIOS-bochs-latest", + help="bios image for bochs", metavar="BIOS") + + parser.add_option("-V", "--vgabios", dest="vgabios", default="/proj/i4ciao/tools/fail/vgabios.bin", + help="vgabios image for bochs", metavar="VGABIOS") + + parser.add_option("-1", "--once", + action="store_false", dest="forever", default=True, + help="fail-client to be executed") + + + (options, args) = parser.parse_args() + + if not (options.elf_file and options.iso_file and options.fail_client): + parser.error("elf, iso and fail-client are required") + + return options, args + +def execute(options, args, bochsrc, statedir): + command = "env FAIL_ELF_PATH=%s FAIL_STATEDIR=%s %s -q -f %s %s" %\ + (options.elf_file, statedir, options.fail_client, bochsrc, " ".join(args)) + print "executing: " + command + p = Popen(command, shell=True) + p.wait() + + return p.returncode + +def main(options, args): + bochsrc_args = { + "memory": options.memory, + "bios": options.bios, + "vgabios": options.vgabios, + "iso": options.iso_file + } + + bochsrc_text = """ +config_interface: textconfig +display_library: nogui +romimage: file="{bios}" +cpu: count=1, ips=5000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def" +cpuid: mmx=1, sep=1, sse=sse4_2, xapic=1, aes=1, movbe=1, xsave=1, cpuid_limit_winnt=0 +memory: guest={memory}, host={memory} +vgaromimage: file="{vgabios}" +vga: extension=vbe +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata1: enabled=0, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 +ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 +ata0-slave: type=cdrom, path="{iso}", status=inserted +boot: cdrom +clock: sync=none, time0=946681200 +floppy_bootsig_check: disabled=0 +panic: action=fatal +error: action=fatal +info: action=ignore +debug: action=ignore +pass: action=ignore +debugger_log: - +parport1: enabled=0 +vga_update_interval: 300000 +keyboard_serial_delay: 250 +keyboard_paste_delay: 100000 +private_colormap: enabled=0 +i440fxsupport: enabled=0, slot1=pcivga +""".format(**bochsrc_args) + + bochsrc = mkstemp() + fd = os.fdopen(bochsrc[0], "w") + fd.write(bochsrc_text) + fd.close() + bochsrc = bochsrc[1] + + statedir = mkdtemp() + + if options.forever: + while True: + res = execute(options, args, bochsrc, statedir) + if res != 0: + break + + ret = 0 + else: + ret = execute(options, args, bochsrc, statedir) + + os.unlink(bochsrc) + shutil.rmtree(statedir) + sys.exit(ret) + +if __name__ == "__main__": + (options, args) = parseArgs() + main(options, args) + + diff --git a/grub.cfg b/grub.cfg new file mode 100644 index 0000000..7875a7c --- /dev/null +++ b/grub.cfg @@ -0,0 +1,7 @@ +set timeout=0 +set default=0 + +menuentry "CoRedOS" { + multiboot /boot/system.elf + boot +} diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..3d8e8c3 --- /dev/null +++ b/linker.ld @@ -0,0 +1,70 @@ +/* Kernel entry function */ +ENTRY(_start) + +OUTPUT_FORMAT(elf32-i386) + +SECTIONS { + + /DISCARD/ : { + *(".text.inlined*") + *(.comment) + *(.eh_frame) + *(.note.gnu.build-id) + } + + /* Set kernel start address */ + . = 0x100000; + + /* Code and readonly data */ + .text : { + /* fill gaps with int3 opcode to detect invalid jumps */ + FILL(0xcc) + + /* multiboot header */ + multiboot_header = .; + KEEP (*(".rodata.multiboot")) + + /* /\* fixed address for IRQ handlers *\/ */ + /* . = 0x1000; */ + + /* /\* start of interrupt handlers *\/ */ + /* _stext_irqs = .; */ + + /* /\* IRQ Handlers *\/ */ + /* KEEP (*(".text.irqhandlers*")) /\* ASM *\/ */ + /* KEEP (*(".text.irq_handler*")) /\* C *\/ */ + /* *(".text.isrs*") /\* C *\/ */ + /* *(".text.isr_*") /\* C *\/ */ + /* KEEP (*(".text.OSEKOS_ISR*")) */ + /* KEEP (*(".text.idt")) /\* ASM *\/ */ + + /* /\* sysenter handler *\/ */ + /* KEEP (*(".text.sysenter_syscall")) */ + + /* _etext_irqs = .; */ + /* . += 16; /\* padding after data, workaround for import-trace *\/ */ + + KEEP (*(".text.startup")) + *(".text*") + *(".rodata*") + } + + /* Data and Stacks */ + . = 0x200000; + .data : { + KEEP (*(".startup_stack")) + KEEP (*(".kernel_stack")) + *(".data*") + *(COMMON); + } + + /* Memory-mapped I/O APIC */ + _sioapic = 0xFEC00000; + ioapic = 0xFEC00000; + _eioapic = 0xFEC00FFF; + + /* Memory-mapped Local APIC */ + _slapic = 0xFEE00000; + lapic = 0xFEE00000; + _elapic = 0xFEE00FFF; +} diff --git a/main.c b/main.c new file mode 100644 index 0000000..e9c7da3 --- /dev/null +++ b/main.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + + +volatile int __dummy; +void __attribute__ ((noinline)) fail_marker(); +void __attribute__ ((noinline)) fail_marker() +{ + __dummy = 100; +} + +void __attribute__ ((noinline)) stop_trace(); +void __attribute__ ((noinline)) stop_trace() +{ + __dummy = 100; +} + + +int array[] = {1, 1, 2, 3, 5, 8, 13, 21}; +void os_main() { + int sum = 0; + + for (int i = 0; i < sizeof(array)/sizeof(*array); i++) { + sum = (array[i] * 23) + 1; + } + + if (sum != 1250) + fail_marker(); + stop_trace(); +} + diff --git a/startup.s b/startup.s new file mode 100644 index 0000000..fdd4f8d --- /dev/null +++ b/startup.s @@ -0,0 +1,59 @@ +## Bare bone boot.s from wiki.osdev.org + +# multiboot header +.section .rodata.multiboot +.align 4 + +# magic number +.long 0x1BADB002 + +# flags: align, meminfo +.long 0x3 + +# checksum: -(magic+flags) +.long -(0x1BADB002 + 0x3) + + + +# the initial kernel stack +.section .kernel_stack +.global os_stack +.size os_stack, 4096 +#.Lstack_bottom: +os_stack: +.byte 0 +#.skip 16384 # 16 KiB +.skip 4094 # 4 KiB +.byte 0 +.Lstack_top: + + + +# The linker script specifies _start as the entry point to the kernel and the +# bootloader will jump to this position once the kernel has been loaded. It +# doesn't make sense to return from this function as the bootloader is gone. +.section .text.startup +.global _start +.type _start, @function +_start: + # Welcome to kernel mode! + # To set up a stack, we simply set the esp register to point to the top of + # our stack (as it grows downwards). + movl $.Lstack_top, %esp + # We are now ready to actually execute C code. (see ./startup.cc) + call os_main + + # In case the function returns, we'll want to put the computer into an + # infinite loop. To do that, we use the clear interrupt ('cli') instruction + # to disable interrupts, the halt instruction ('hlt') to stop the CPU until + # the next interrupt arrives, and jumping to the halt instruction if it ever + # continues execution, just to be safe. We will create a local label rather + # than real symbol and jump to there endlessly. + cli + hlt +.Lhang: + jmp .Lhang + +# Set the size of the _start symbol to the current location '.' minus its start. +# This is useful when debugging or when you implement call tracing. +.size _start, . - _start