[{"data":1,"prerenderedAt":54},["ShallowReactive",2],{"publications-sem86-qrs26":3,"papers-sem86-qrs26-01-introduction":40},{"id":4,"title":5,"authors":6,"awards":7,"bibtex":11,"body":12,"date":27,"description":28,"extension":29,"link":30,"meta":31,"navigation":32,"path":33,"pdf":34,"seo":35,"slug":36,"stem":37,"venue":38,"__hash__":39},"publications\u002Fpublications\u002Fsem86-qrs26.md","Sem86: A Full-System Emulator Without Hard-Coded Semantics","Jos Craaijo, Freek Verbeek, Binoy Ravindran",[8],{"name":9,"url":10},"Best Presentation Award","https:\u002F\u002Fqrs26.techconf.org\u002Ftrack\u002Faward_presentation","",{"type":13,"value":14,"toc":24},"minimark",[15],[16,17,18,19,23],"p",{},"Emulation can be used to run legacy software, analyze malware in a sandboxed environment, or run software compiled for different architectures.\nAn emulator is based on instruction semantics.\nThere is, however, not a single instruction semantics to be followed, as x86 allows undefined behavior.\nIn order to make accurate CPU-specific emulators,\nwe argue the need for an emulator that can easily switch between different semantics.\nHowever, all existing emulators contain hard-coded semantics.\nWe present Sem86, an x86 emulator that loads semantics at runtime from data in an input file.\nWe implement all necessary hardware needed to emulate typical x86 operating systems such as Windows 98, Windows XP and Windows 7.\nAdditionally, we implement a sound card, network card and support for high-resolution display output.\nSem86 can automatically ",[20,21,22],"em",{},"bisect"," instruction execution to determine at which point different semantics would diverge.\nWe demonstrate this by constructing a toy malware example that exploits undefined instruction behavior to detect whether it is running in an emulator,\nand show that Sem86 can pinpoint the exact instruction that is used.",{"title":11,"searchDepth":25,"depth":25,"links":26},2,[],"2026-07-22","Emulation can be used to run legacy software, analyze malware in a sandboxed environment, or run software compiled for different architectures.\nAn emulator is based on instruction semantics.\nThere is, however, not a single instruction semantics to be followed, as x86 allows undefined behavior.\nIn order to make accurate CPU-specific emulators,\nwe argue the need for an emulator that can easily switch between different semantics.\nHowever, all existing emulators contain hard-coded semantics.\nWe present Sem86, an x86 emulator that loads semantics at runtime from data in an input file.\nWe implement all necessary hardware needed to emulate typical x86 operating systems such as Windows 98, Windows XP and Windows 7.\nAdditionally, we implement a sound card, network card and support for high-resolution display output.\nSem86 can automatically bisect instruction execution to determine at which point different semantics would diverge.\nWe demonstrate this by constructing a toy malware example that exploits undefined instruction behavior to detect whether it is running in an emulator,\nand show that Sem86 can pinpoint the exact instruction that is used.","md","https:\u002F\u002Fqrs26.techconf.org\u002F",{},true,"\u002Fpublications\u002Fsem86-qrs26","\u002Ffiles\u002Fsem86.pdf",{"title":5,"description":28},"sem86-qrs26","publications\u002Fsem86-qrs26","QRS'26","2isYelaLp7jOW_ygpxJBHzUdEprIalEWZTRkgsYVd-U",{"id":41,"title":42,"body":43,"date":43,"description":43,"extension":44,"html":45,"meta":46,"navigation":32,"next":47,"path":50,"previous":43,"seo":51,"slug":43,"stem":52,"__hash__":53},"papers\u002Fpublications\u002Fsem86-qrs26\u002F01-introduction.html","Introduction",null,"html","\u003Cstyle>\u002F* Alignment *\u002F\nmtable.right-align mtd,\nmtable mtd.right-align,\nmtable.left-align mtd.right-align,\nmtable.aligned mtd:nth-child(odd) {\n  justify-items: end;\n  text-align: right;\n}\nmtable.cases mtd,\nmtable.left-align mtd,\nmtable mtd.left-align,\nmtable.aligned mtd:nth-child(even),\nmath:is(:not([display])) > mtable.multiline-equation mtd {\n  justify-items: start;\n  text-align: left;\n}\nmtable.cases mtd,\nmtable.aligned mtd,\nmtable mtd.flushed,\nmtable mtd.left-flush {\n  padding-left: 0;\n}\nmtable.cases mtd,\nmtable.aligned mtd,\nmtable mtd.flushed,\nmtable mtd.right-flush {\n  padding-right: 0;\n}\n\n\u002F* Tables *\u002F\nmtable {\n  math-style: inherit;\n}\nmtd {\n  math-depth: auto-add;\n  math-style: compact;\n  math-shift: compact;\n}\n\n\u002F* Equations *\u002F\nmtable.multiline-equation mtd {\n  math-depth: inherit;\n  math-style: inherit;\n  math-shift: inherit;\n  padding: 0;\n}\nmath > mtable.multiline-equation mtr:not(:last-child) mtd {\n  padding-bottom: 0.5em;\n}\n\n\u002F* Fractions *\u002F\nmfrac {\n  padding-inline: 0;\n  margin-inline: 0.1em;\n}\n\n\u002F* Accents *\u002F\nmover[accent=\"true\" i] > :first-child {\n  font-feature-settings: \"dtls\";\n}\nmover.dotted[accent=\"true\" i] > :first-child {\n  font-feature-settings: \"dtls\" 0;\n}\n\n\u002F* Other rules for scriptlevel, displaystyle and math-shift *\u002F\nmunder > :nth-child(2),\nmunderover > :nth-child(2) {\n  math-shift: compact\n}\nmunder[accentunder=\"true\" i] > :not(:first-child),\nmover[accent=\"true\" i] > :not(:first-child) {\n  math-depth: inherit;\n  math-style: inherit;\n  math-shift: inherit;\n}\u003C\u002Fstyle>\u003Cdiv id=\"previous-page\" style=\"display: none\">\u003C\u002Fdiv>\u003Cdiv id=\"next-page\" style=\"display: none\">\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F02-related-work#loc-1\">Related Work\u003C\u002Fa>\u003C\u002Fdiv>\u003Ch2 id=\"loc-1\">1 Introduction\u003C\u002Fh2>\u003Cp>Malware often attempts to frustrate analysis by disabling itself when it detects that it is running inside an emulator \u003Cspan id=\"loc-2\">[\u003C\u002Fspan>\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-2\" role=\"doc-biblioref\">1\u003C\u002Fa>–\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-3\" role=\"doc-biblioref\">5\u003C\u002Fa>]. Some emulator detection techniques make use of \u003Cem>undefined\u003C\u002Fem> instruction behavior. These outputs are unspecified in CPU reference manuals, and are often implemented differently on different CPU architectures and emulators.\u003C\u002Fp>\u003Cp>Existing emulators \u003Cspan id=\"loc-3\">[\u003C\u002Fspan>\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-4\" role=\"doc-biblioref\">6\u003C\u002Fa>–\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-6\" role=\"doc-biblioref\">8\u003C\u002Fa>] do not accurately implement undefined behavior \u003Cspan id=\"loc-4\">[\u003C\u002Fspan>\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-7\" role=\"doc-biblioref\">9\u003C\u002Fa>, \u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-8\" role=\"doc-biblioref\">10\u003C\u002Fa>]. Most existing formal semantics \u003Cspan id=\"loc-5\">[\u003C\u002Fspan>\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-9\" role=\"doc-biblioref\">11\u003C\u002Fa>–\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-12\" role=\"doc-biblioref\">14\u003C\u002Fa>] simply mark such outputs as “undefined”, and do not provide specific implementations. This leads to differences in behavior, which malware exploits to detect whether it is running inside an emulator. Such differences are actively used by real-world malware. For example, malware was encountered that uses the output of undefined flags from the \u003Ccode>IMUL\u003C\u002Fcode> instruction to detect emulation [\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-3\" role=\"doc-biblioref\">5\u003C\u002Fa>].\u003C\u002Fp>\u003Cp>Since implementations of undefined behavior can differ between CPUs, there exists no single “correct” semantics. Ideally, an emulator would be able to easily switch between different semantics, such that different CPU-specific semantics can be used. In other words, we argue the need for an emulator that can accurately – thus including undefined behavior – emulate many different real-world CPUs. Such an emulator should, e.g., run the Intel Celeron differently from the AMD Athlon even though they are both x86 architectures, as they implement undefined behavior differently.\u003C\u002Fp>\u003Cp>Emulators usually hardcode semantics, which means that the emulator needs to be reprogrammed and then recompiled from source to change the semantics. This is unfeasible if one wants to switch between many different semantics.\u003C\u002Fp>\u003Cp>We present \u003Cspan style=\"font-variant-caps: small-caps\">Sem86\u003C\u002Fspan>, an x86 emulator without hard-coded semantics. Instead, semantics are provided to the emulator as data in an input file, which makes switching between different semantics trivial. Instruction semantics are encoded in a simple format, that allows for conversion from and to other formats, such as SMT-LIB \u003Cspan id=\"loc-6\">[\u003C\u002Fspan>\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-13\" role=\"doc-biblioref\">15\u003C\u002Fa>]. All source code will be published under an open-source license upon acceptance of this paper.\u003C\u002Fp>\u003Cp>Despite not having hard-coded semantics, \u003Cspan style=\"font-variant-caps: small-caps\">Sem86\u003C\u002Fspan> is \u003Cmath>\u003Cmn>1.91\u003C\u002Fmn>\u003Cmo form=\"infix\" lspace=\"0.2222222222222222em\" rspace=\"0em\">×\u003C\u002Fmo>\u003C\u002Fmath> as fast as Bochs and achieves 42.4% of QEMU’s performance. It implements all necessary hardware to boot real x86 operating systems that support Pentium 5-era hardware, such as Windows 98, Windows XP and Windows 7. It also implements several optional hardware components for audio, high-resolution display output and internet access.\u003C\u002Fp>\u003Cp>We construct a toy example that uses the IMUL instruction to detect emulation, and show that \u003Cspan style=\"font-variant-caps: small-caps\">Sem86\u003C\u002Fspan> emulates this program differently when provided with different semantics. Additionally, \u003Cspan style=\"font-variant-caps: small-caps\">Sem86\u003C\u002Fspan> is able to \u003Cem>bisect\u003C\u002Fem> execution of the program to identify at exactly which instruction this emulator detection takes place.\u003C\u002Fp>\u003Cp>A key question then is where we can obtain CPU-specific semantics that include semantics even for undefined behavior. To the best of our knowledge, the only source for such semantics is libLISA \u003Cspan id=\"loc-7\">[\u003C\u002Fspan>\u003Ca href=\"\u002Fpublications\u002Fsem86-qrs26\u002F06-bibliography#loc-14\" role=\"doc-biblioref\">16\u003C\u002Fa>]. That tool uses program synthesis to derive instruction semantics from a CPU, by running millions of observations per instruction. They actually synthesize different undefined behavior for different x86-64 architectures. The ideal setup then is to use libLISA to synthesize instruction semantics for a set of CPUs, and use \u003Cspan style=\"font-variant-caps: small-caps\">Sem86\u003C\u002Fspan> to obtain a trustworthy CPU-specific emulator for each of these. Currently, we provide a handwritten set of semantics inspired by libLISA semantics, but in the near future we aim to replace these handwritten semantics with synthesized ones taken ad verbatim from libLISA.\u003C\u002Fp>\u003Cp>As part of this work we discovered an emulation bug in Bochs. This bug caused wrong instructions to be executed under specific conditions, due to insufficient cache invalidation. We have reported this bug, which has since been fixed by the developers of Bochs.\u003C\u002Fp>",{},{"url":48,"title":49},"\u002Fpublications\u002Fsem86-qrs26\u002F02-related-work","Related Work","\u002Fpublications\u002Fsem86-qrs26\u002F01-introduction",{"title":42},"publications\u002Fsem86-qrs26\u002F01-introduction","8q0UVUvDzZZZuCCAAyLLRKOEDP3ZtuPGocfuLb3UqkU",1787086053581]