Skip to content

Commit

Permalink
Merge pull request #504 from S2E/issue/503-cgc
Browse files Browse the repository at this point in the history
Updated CGC binary support
  • Loading branch information
vitalych authored Jun 2, 2024
2 parents 6b10450 + 9632516 commit f9815b1
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 33 deletions.
2 changes: 0 additions & 2 deletions s2e_env/commands/new_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,6 @@ def handle(self, *args, **options):
# It provides a class that is instantiated with the current
# command-line arguments and options
proj_class = options.pop('project_class', None)
if not proj_class:
proj_class = _get_project_class(**options)

if options['target']:
_handle_with_file(options.pop('target'), options.pop('target_args'), proj_class, *args, **options)
Expand Down
19 changes: 18 additions & 1 deletion s2e_env/commands/project_creation/base_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,13 @@ class BaseProject(AbstractProject):

supported_tools = []

def __init__(self, bootstrap_template, lua_template, image_override=None):
def __init__(self, bootstrap_template, lua_template, image_override=None, misc_templates=None):
super().__init__()

self._bootstrap_template = bootstrap_template
self._lua_template = lua_template
self._image_override = image_override
self._misc_templates = misc_templates

def _configure(self, target, *args, **options):
if target.is_empty():
Expand Down Expand Up @@ -231,6 +232,7 @@ def _create(self, config, force=False):
self._create_launch_script(project_dir, config)
self._create_lua_config(project_dir, config)
self._create_bootstrap(project_dir, config)
self._create_misc_templates(project_dir, config)

# Even though the AbstractProject will save the project description, we
# need it to be able to generate recipes below
Expand Down Expand Up @@ -354,3 +356,18 @@ def _create_bootstrap(self, project_dir, config):
template = 'bootstrap.sh'
output_path = os.path.join(project_dir, template)
render_template(context, template, output_path)

def _create_misc_templates(self, project_dir, config):
"""
Render any other optional scripts.
"""
if not self._misc_templates:
return

context = config.copy()
context['env_dir'] = self.env_path()

for template in self._misc_templates:
output_path = os.path.join(project_dir, template)
executable = template.endswith('.sh')
render_template(context, template, output_path, executable=executable)
2 changes: 1 addition & 1 deletion s2e_env/commands/project_creation/cgc_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class CGCProject(BaseProject):
supported_tools = ['pov']

def __init__(self):
super().__init__('bootstrap.cgc.sh', 's2e-config.cgc.lua')
super().__init__('bootstrap.cgc.sh', 's2e-config.cgc.lua', None, ['verify-pov.sh'])

def _is_valid_image(self, target, os_desc):
return is_valid_arch(target.arch, os_desc) and 'decree' in os_desc['binary_formats']
Expand Down
6 changes: 5 additions & 1 deletion s2e_env/commands/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,13 @@ def get_recipe_path(self, recipe_type, arch, platform, name, gp_reg):
filename = f'{filename}.rcp'
return self.project_path('recipes', filename)

# pylint: disable=too-many-locals
def handle(self, *args, **options):
logging.getLogger('pwnlib').setLevel('ERROR')

target = self.project_desc.get('target', {})
os = target.get('os', None)

img_os_desc = self.image['os']

archs = []
Expand All @@ -318,7 +322,7 @@ def handle(self, *args, **options):
handler(fp, arch, platform, gp_reg)

# Specific for decree
if 'decree' in img_os_desc['binary_formats']:
if os == 'decree':
type2_handlers = [(0, type2_decree_shellcode_i386_0), (1, type2_decree_shellcode_i386_1)]

for i, handler in type2_handlers:
Expand Down
1 change: 0 additions & 1 deletion s2e_env/server/web_service_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,3 @@ def process(data, analysis):

if data_type == 'stats':
WebServiceInterfacePlugin.handle_stats(analysis, data)
return
30 changes: 5 additions & 25 deletions s2e_env/templates/bootstrap.cgc.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
# CGC has a different way of making seeds symbolic,
# override default behavior.
function make_seeds_symbolic {
echo 0
}

function execute_target {
local TARGET
local SEED_FILE
Expand All @@ -12,35 +6,21 @@ function execute_target {
SEED_FILE="$2"

if [ "x${SEED_FILE}" = "x" ]; then
./${TARGET} > /tmp/out 2>&1
$CGCLOAD --enable-s2e ./${TARGET} > /tmp/out 2>&1
else
# Make the seed file concolic and submit it to the cb-test application.
# Note: CGC files don't need to be in a ram disk, as they will be made
# symbolic at the syscall level. See DecreeMonitor for details.
${S2ECMD} get "${SEED_FILE}"
${CGCCMD} concolic on

chmod +x ${SEED_FILE}
cb-test --directory $(pwd) --xml ${SEED_FILE} --cb ${TARGET} --should_core --timeout 3600 2>&1
cat "${SEED_FILE}" | $CGCLOAD --enable-s2e --enable-seeds ./${TARGET} > /tmp/out 2>&1
fi
}

function target_init {
# Patch cb-test so that it works without core dumps
sudo sed -i 's/resource.RLIM_INFINITY/0/g' /usr/bin/cb-test

# Some binaries have strange headers, allow them here
echo 1 | sudo tee /proc/sys/cgc/relaxed_headers

# Start the DecreeMonitor kernel module
# Start the LinuxMonitor kernel module
sudo modprobe s2e
}

function target_tools {
echo "${TARGET_TOOLS_ROOT}/cgccmd"
echo "${TARGET_TOOLS32_ROOT}/cgcload"
}

S2ECMD=./s2ecmd
CGCLOAD="${TARGET_TOOLS32_ROOT}/cgcload"
COMMON_TOOLS="s2ecmd"

CGCCMD=${TARGET_TOOLS_ROOT}/cgccmd
41 changes: 39 additions & 2 deletions s2e_env/templates/s2e-config.cgc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,30 @@ This is CGC-specific configuration. The default settings are very close to
those that were used during the CGC final event.
]]--


-------------------------------------------------------------------------------
-- LinuxMonitor is a plugin that monitors Linux events and exposes them
-- to other plugins in a generic way. Events include process load/termination,
-- thread events, signals, etc.
--
-- LinuxMonitor requires a custom Linux kernel with S2E extensions. This kernel
-- (and corresponding VM image) can be built with S2E tools. Please refer to
-- the documentation for more details.

add_plugin("LinuxMonitor")
pluginsConfig.LinuxMonitor = {
-- Kill the execution state when it encounters a segfault
terminateOnSegfault = true,

-- Kill the execution state when it encounters a trap
terminateOnTrap = true,
}

-------------------------------------------------------------------------------
-- This plugin is to be used together with the Decree Linux Kernel.
-- The Decree kernel has a custom binary loader for challenge binaries (CBs).
-- This plugin is to monitor events from Decree binaries.
-- S2E does not use the old CGC Linux kernel to run Decree binaries. Instead,
-- it uses a custom user-space loader that emulates Decree syscalls. Decree binaries
-- run otherwise like any other statically-linked Linux binaries.
-- That loader is instrumented in order to communicate important events
-- to DecreeMonitor. Instrumented events include CB loading/unloading, syscall
-- invocation, etc.
Expand Down Expand Up @@ -80,3 +101,19 @@ add_plugin("DecreePovGenerator")
-- Note: this plugin is currently only enabled for Decree, as it does not
-- support Linux properly (probably a signal issue).
add_plugin("StackMonitor")


-------------------------------------------------------------------------------
-- Override default config
pluginsConfig.ProcessExecutionDetector = {
moduleNames = {
"cgcload",
},
}

pluginsConfig.ModuleExecutionDetector = {
mod_0 = {
moduleName = "cgcload",
},
logLevel="info"
}
19 changes: 19 additions & 0 deletions s2e_env/templates/verify-pov.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/sh

# This script verifies that the generated POVs actually work.

set -xe

ENV_DIR="{{ env_dir }}"
INSTALL_DIR="$ENV_DIR/install"
GUEST_TOOLS32="${ENV_DIR}/install/bin/guest-tools32"

CFLAGS="-L${GUEST_TOOLS32}/lib -I${ENV_DIR}/source/s2e/guest/linux/include"

for v in s2e-last/*.c; do
echo "======= CHECKING POV $v ======="
DIR="$(dirname $v)"
POV="$(basename $v .c)"
gcc -O0 -g -m32 -o "$DIR/$POV" $CFLAGS "$v" -lpov -lcgc
$GUEST_TOOLS32/povtest "--pov=$DIR/${POV}" -- $GUEST_TOOLS32/cgcload {{ target.path }}
done
3 changes: 3 additions & 0 deletions s2e_env/tui/tui.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ def set_size(self, w=None, h=None):
Width and Height can be set to None to expand the window
to the size of the parent container.
"""
mw = 0
mh = 0

if w is None or h is None:
form = self.get_parent()
if form is None:
Expand Down

0 comments on commit f9815b1

Please sign in to comment.