1
0
mirror of https://git.FreeBSD.org/ports.git synced 2024-12-12 03:00:28 +00:00

The sandsifter audits x86 processors for hidden instructions and

hardware bugs, by systematically generating machine code to search
through a processor's instruction set, and monitoring execution for
anomalies. Sandsifter has uncovered secret processor instructions from
every major vendor; ubiquitous software bugs in disassemblers,
assemblers, and emulators; flaws in enterprise hypervisors; and both
benign and security-critical hardware bugs in x86 chips.

WWW: https://github.com/xoreaxeaxeax/sandsifter

PR:		221132
Submitted by:	rozhuk.im AT gmail.com
Reviewed by:	swills
This commit is contained in:
Rene Ladan 2017-09-30 15:13:32 +00:00
parent 457a9b9565
commit 48192f57b0
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=450997
9 changed files with 237 additions and 0 deletions

View File

@ -1119,6 +1119,7 @@
SUBDIR += samhain-client
SUBDIR += samhain-server
SUBDIR += sancp
SUBDIR += sandsifter
SUBDIR += sasp
SUBDIR += scamp
SUBDIR += scanhill

View File

@ -0,0 +1,41 @@
# $FreeBSD$
PORTNAME= sandsifter
PORTVERSION= 0.1
CATEGORIES= security
MAINTAINER= rene@FreeBSD.org
COMMENT= Processor fuzzer for x86 CPUs
BUILD_DEPENDS= ${LOCALBASE}/include/capstone/capstone.h:devel/capstone3
RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}capstone>0:devel/py-capstone
USES= gmake python localbase shebangfix
ONLY_FOR_ARCH= amd64 i386
ONLY_FOR_ARCH_RAESON=Designed for x86
USE_GITHUB= yes
GH_ACCOUNT= xoreaxeaxeax
GH_TAGNAME= dff63246fed84d90118441b8ba5b5d3bdd094427
SHEBANG_FILES= sifter.py summarize.py
OPTIONS_DEFINE= DOCS
PORTDOCS= references/*
do-install:
(cd ${WRKSRC} && ${COPYTREE_SHARE} gui ${STAGEDIR}${DATADIR})
(cd ${WRKSRC} && ${COPYTREE_SHARE} pyutil ${STAGEDIR}${DATADIR})
${INSTALL_PROGRAM} ${WRKSRC}/injector ${STAGEDIR}${PREFIX}/bin
${INSTALL_SCRIPT} ${WRKSRC}/sifter.py ${STAGEDIR}${DATADIR}
${INSTALL_SCRIPT} ${WRKSRC}/summarize.py ${STAGEDIR}${DATADIR}
${RLN} ${STAGEDIR}${DATADIR}/sifter.py ${STAGEDIR}${PREFIX}/bin/sifter
${RLN} ${STAGEDIR}${DATADIR}/summarize.py ${STAGEDIR}${PREFIX}/bin/summarize
${MKDIR} ${STAGEDIR}${DOCSDIR}
${INSTALL_DATA} ${WRKSRC}/README.md ${STAGEDIR}${DOCSDIR}
post-install-DOCS-on:
${INSTALL_DATA} ${WRKSRC}/references/* ${STAGEDIR}${DOCSDIR}
.include <bsd.port.mk>

View File

@ -0,0 +1,3 @@
TIMESTAMP = 1505751266
SHA256 (xoreaxeaxeax-sandsifter-0.1-dff63246fed84d90118441b8ba5b5d3bdd094427_GH0.tar.gz) = 010d662705bb67035e3d6b93a0fbe0bcf7ab2b5ba93e6eb977eb614c7dec3691
SIZE (xoreaxeaxeax-sandsifter-0.1-dff63246fed84d90118441b8ba5b5d3bdd094427_GH0.tar.gz) = 5284438

View File

@ -0,0 +1,11 @@
--- Makefile.orig 2017-07-27 19:17:30 UTC
+++ Makefile
@@ -32,7 +32,7 @@
all: injector
injector: injector.o
- $(CC) $(CFLAGS) $< -O3 -Wall -l:libcapstone.a -o $@ -pthread
+ $(CC) $(CFLAGS) $(LIBS) $(LDFLAGS) $< -Wall -l:libcapstone.a -o $@ -pthread
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@ -Wall

View File

@ -0,0 +1,107 @@
--- injector.c.orig 2017-07-27 19:17:30 UTC
+++ injector.c
@@ -77,10 +77,24 @@ cs_insn *capstone_insn;
/* 32 vs 64 */
-#if __x86_64__
- #define IP REG_RIP
+#ifdef __linux__
+# define PAGE_SIZE 4096
+# define EFL gregs[REG_EFL]
+# if __x86_64__
+# define IP gregs[REG_RIP]
+# else
+# define IP gregs[REG_EIP]
+# endif
#else
- #define IP REG_EIP
+# include <pthread_np.h>
+ typedef cpuset_t cpu_set_t;
+# if __x86_64__
+# define IP mc_rip
+# define EFL mc_rflags
+# else
+# define IP mc_eip
+# define EFL mc_eflags
+# endif
#endif
/* leave state as 0 */
@@ -155,7 +169,6 @@ state_t inject_state={
/* x86/64 */
#define UD2_SIZE 2
-#define PAGE_SIZE 4096
#define TF 0x100
/* injection */
@@ -293,6 +306,10 @@ ignore_op_t opcode_blacklist[MAX_BLACKLIST]={
{ "\xcd\x80", "int 0x80" },
/* as will syscall */
{ "\x0f\x05", "syscall" },
+ /* int 92 on FreeBSD triggers DTrace, which will trigger SIGSYS */
+ { "\xcd\x92", "int 0x92" },
+ /* int 93 on FreeBSD is used by Xen */
+ { "\xcd\x93", "int 0x93" },
/* ud2 is an undefined opcode, and messes up a length differential search
* b/c of the fault it throws */
{ "\x0f\xb9", "ud2" },
@@ -850,7 +867,7 @@ void inject(int insn_size)
void state_handler(int signum, siginfo_t* si, void* p)
{
fault_context=((ucontext_t*)p)->uc_mcontext;
- ((ucontext_t*)p)->uc_mcontext.gregs[IP]+=UD2_SIZE;
+ ((ucontext_t*)p)->uc_mcontext.IP+=UD2_SIZE;
}
void fault_handler(int signum, siginfo_t* si, void* p)
@@ -863,7 +880,7 @@ void fault_handler(int signum, siginfo_t* si, void* p)
/* make an initial estimate on the instruction length from the fault address */
insn_length=
- (uintptr_t)uc->uc_mcontext.gregs[IP]-(uintptr_t)packet-preamble_length;
+ (uintptr_t)uc->uc_mcontext.IP-(uintptr_t)packet-preamble_length;
if (insn_length<0) {
insn_length=JMP_LENGTH;
@@ -880,9 +897,13 @@ void fault_handler(int signum, siginfo_t* si, void* p)
(signum==SIGSEGV||signum==SIGBUS)?(uint32_t)(uintptr_t)si->si_addr:(uint32_t)-1
};
+#ifdef __linux__
memcpy(uc->uc_mcontext.gregs, fault_context.gregs, sizeof(fault_context.gregs));
- uc->uc_mcontext.gregs[IP]=(uintptr_t)&resume;
- uc->uc_mcontext.gregs[REG_EFL]&=~TF;
+#else
+ memcpy(&uc->uc_mcontext, &fault_context, sizeof(fault_context));
+#endif
+ uc->uc_mcontext.IP=(uintptr_t)&resume;
+ uc->uc_mcontext.EFL&=~TF;
}
void configure_sig_handler(void (*handler)(int, siginfo_t*, void*))
@@ -1341,7 +1362,13 @@ void pin_core(void)
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(config.core,&mask);
- if (sched_setaffinity(0, sizeof(mask), &mask)) {
+#ifdef __linux__
+ if (sched_setaffinity(0, sizeof(mask), &mask))
+#else
+ if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID,
+ -1, sizeof(mask), &mask))
+#endif
+ {
printf("error: failed to set cpu\n");
exit(1);
}
@@ -1439,7 +1466,7 @@ int main(int argc, char** argv)
null_p=mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (null_p==MAP_FAILED) {
- printf("null access requires running as root\n");
+ printf("null access requires running as root, %i\n", errno);
exit(1);
}
}

View File

@ -0,0 +1,44 @@
--- sifter.py.orig 2017-09-22 12:42:26 UTC
+++ sifter.py
@@ -26,11 +26,12 @@ import argparse
import code
import copy
from ctypes import *
+import sysctl
-INJECTOR = "./injector"
+INJECTOR = "injector"
arch = ""
-OUTPUT = "./data/"
+OUTPUT = os.getenv("HOME") + "/.sandsifter/"
LOG = OUTPUT + "log"
SYNC = OUTPUT + "sync"
TICK = OUTPUT + "tick"
@@ -679,7 +680,7 @@ class Gui:
time.sleep(self.TIME_SLICE)
def get_cpu_info():
- with open("/proc/cpuinfo", "r") as f:
+ with open("/compat/linux/proc/cpuinfo", "r") as f:
cpu = [l.strip() for l in f.readlines()[:7]]
return cpu
@@ -808,9 +809,16 @@ def main():
if not os.path.exists(OUTPUT):
os.makedirs(OUTPUT)
+ real_injector, errors = \
+ subprocess.Popen(
+ ['which', INJECTOR],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE
+ ).communicate()
+ real_injector = real_injector.replace('\n', '') # strip newline from shell output
injector_bitness, errors = \
subprocess.Popen(
- ['file', INJECTOR],
+ ['file', real_injector],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
).communicate()

View File

@ -0,0 +1,9 @@
The sandsifter audits x86 processors for hidden instructions and
hardware bugs, by systematically generating machine code to search
through a processor's instruction set, and monitoring execution for
anomalies. Sandsifter has uncovered secret processor instructions from
every major vendor; ubiquitous software bugs in disassemblers,
assemblers, and emulators; flaws in enterprise hypervisors; and both
benign and security-critical hardware bugs in x86 chips.
WWW: https://github.com/xoreaxeaxeax/sandsifter

View File

@ -0,0 +1,5 @@
*** ATTENTION ***
Before using this tool you should do the following as root:
# sysctl security.bsd.map_at_zero=1
# mount -t linprocfs linproc /compat/linux/proc

View File

@ -0,0 +1,16 @@
bin/injector
bin/sifter
bin/summarize
%%PORTDOCS%%%%DOCSDIR%%/README.md
%%PORTDOCS%%%%DOCSDIR%%/domas_breaking_the_x86_isa.pdf
%%PORTDOCS%%%%DOCSDIR%%/domas_breaking_the_x86_isa_wp.pdf
%%PORTDOCS%%%%DOCSDIR%%/sandsifter.gif
%%PORTDOCS%%%%DOCSDIR%%/screenshot.png
%%PORTDOCS%%%%DOCSDIR%%/summarizer.png
%%DATADIR%%/gui/__init__.py
%%DATADIR%%/gui/gui.py
%%DATADIR%%/pyutil/__init__.py
%%DATADIR%%/pyutil/colors.py
%%DATADIR%%/pyutil/progress.py
%%DATADIR%%/sifter.py
%%DATADIR%%/summarize.py