From 7942eeae9f7640b06c8a1dc46530200350e056af Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Sun, 16 Feb 2025 10:04:05 +0200 Subject: [PATCH 1/5] shellcode_step: Make base_address optional --- shellblocks/shellcode_step.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/shellblocks/shellcode_step.py b/shellblocks/shellcode_step.py index 8fe7b73..259bd80 100644 --- a/shellblocks/shellcode_step.py +++ b/shellblocks/shellcode_step.py @@ -8,7 +8,13 @@ class ShellcodeStep: - def __init__(self, nickname: str, base_address: int, primitives: [ShellcodePrimitive], max_len: int): + def __init__( + self, + nickname: str, + primitives: [ShellcodePrimitive], + max_len: int, + base_address: int = 0 + ): self.nickname = nickname self.base_address = base_address self.primitives = primitives From 63113ab8975362cf21e95bd6ac37077b98004f21 Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Sun, 16 Feb 2025 10:07:02 +0200 Subject: [PATCH 2/5] readme: Update ShellcodeStep constructor --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 90201be..4a4ca72 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ A final "Shellcode Structure" example: ```python first_step = ShellcodeStep( "first_step", - 0xbfc00000, [ ShellcodePrimitiveMemcpy("copy_next_stage", 0x80abcdef, 0x8f0ed0b0, 0x100), ShellcodePrimitivePrint("print_debug", 0x80901234, "This is a print!\n"), From 06f44558ffa1697f0c99430b18665498a81667e3 Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Sun, 16 Feb 2025 10:07:20 +0200 Subject: [PATCH 3/5] primitives, tests: Adapt to base_address being optional --- shellblocks/primitives/jump_hook.py | 4 ++-- tests/test_goto.py | 8 ++++---- tests/test_jump_hook.py | 12 ++++++------ tests/test_memcpy.py | 4 ++-- tests/test_memset.py | 4 ++-- tests/test_print.py | 4 ++-- tests/test_step.py | 4 ++-- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/shellblocks/primitives/jump_hook.py b/shellblocks/primitives/jump_hook.py index 8a1cdee..26e18ed 100644 --- a/shellblocks/primitives/jump_hook.py +++ b/shellblocks/primitives/jump_hook.py @@ -24,14 +24,14 @@ def __init__(self, nickname: str, hook_address: int, goto_address: int): def generate(self, path: Path, compiler: CompilerArch): step = ShellcodeStep( self.nickname, - 0x0, # This should be PIC [ ShellcodePrimitiveGoto( self.nickname, self.goto_address ), ], - 0x1000 + 0x1000, + base_address=0x0, # This should be PIC ) out_file = step.generate(path / self.nickname / "goto_temp", compiler) diff --git a/tests/test_goto.py b/tests/test_goto.py index 8b87ccd..aa2f189 100644 --- a/tests/test_goto.py +++ b/tests/test_goto.py @@ -24,11 +24,11 @@ def test_goto_sanity(get_mu, temp_dir_path, arch_helper, compiler_arch, goto_pag step = ShellcodeStep( "first_step", - shellcode_address, [ ShellcodePrimitiveGoto("copy_next_stage", goto_address), ], - 0x1000 + 0x1000, + base_address=shellcode_address, ) out_file = step.generate(temp_dir_path / step.nickname, compiler_arch) @@ -64,11 +64,11 @@ def test_goto_is_pic(get_mu, temp_dir_path, arch_helper, compiler_arch, shellcod step = ShellcodeStep( "first_step", - shellcode_address, [ ShellcodePrimitiveGoto("copy_next_stage", goto_address), ], - 0x1000 + 0x1000, + base_address=shellcode_address, ) out_file = step.generate(temp_dir_path / step.nickname, compiler_arch) diff --git a/tests/test_jump_hook.py b/tests/test_jump_hook.py index 9466462..7df88e8 100644 --- a/tests/test_jump_hook.py +++ b/tests/test_jump_hook.py @@ -21,11 +21,11 @@ def generate_memset_to_goto(temp_dir_path, step = ShellcodeStep( "first_step", - shellcode_address, [ expected_goto_primitive, ], - 0x1000 + 0x1000, + base_address=shellcode_address, ) out_file = step.generate(temp_dir_path / step.nickname, compiler_arch) @@ -39,11 +39,11 @@ def generate_memset_to_goto(temp_dir_path, step = ShellcodeStep( "first_step", - shellcode_address, [ expected_memset_primitive, ], - 0x1000 + 0x1000, + base_address=shellcode_address, ) out_file = step.generate(temp_dir_path / step.nickname, compiler_arch) @@ -95,11 +95,11 @@ def test_jump_hook_sanity( step = ShellcodeStep( "first_step", - shellcode_address, [ jump_hook_pritimive, ], - 0x1000 + 0x1000, + base_address=shellcode_address ) out_file = step.generate(temp_dir_path / step.nickname, compiler_arch) diff --git a/tests/test_memcpy.py b/tests/test_memcpy.py index 8369703..5398f1f 100644 --- a/tests/test_memcpy.py +++ b/tests/test_memcpy.py @@ -45,7 +45,6 @@ def memcpy_get_shellcode(temp_dir_path, compiler_arch, memcpy_helper, copy_len): step = ShellcodeStep( "first_step", - helper.shellcode_address, [ ShellcodePrimitiveMemcpy( "copy_next_stage", @@ -54,7 +53,8 @@ def memcpy_get_shellcode(temp_dir_path, compiler_arch, memcpy_helper, copy_len): copy_len ), ], - 0x1000 + 0x1000, + base_address=helper.shellcode_address, ) out_file = step.generate(temp_dir_path / step.nickname, compiler_arch) diff --git a/tests/test_memset.py b/tests/test_memset.py index 7b09de0..def5781 100644 --- a/tests/test_memset.py +++ b/tests/test_memset.py @@ -53,7 +53,6 @@ def memset_get_shellcode(temp_dir_path, compiler_arch, memset_helper, copy_bytes step = ShellcodeStep( "first_step", - helper.shellcode_address, [ ShellcodePrimitiveMemset( "copy_next_stage", @@ -61,7 +60,8 @@ def memset_get_shellcode(temp_dir_path, compiler_arch, memset_helper, copy_bytes copy_bytes ), ], - 0x1000 * len(copy_bytes) + 0x1000 * len(copy_bytes), + base_address=helper.shellcode_address ) out_file = step.generate(temp_dir_path / step.nickname, compiler_arch) diff --git a/tests/test_print.py b/tests/test_print.py index 7795b2b..9869e35 100644 --- a/tests/test_print.py +++ b/tests/test_print.py @@ -44,11 +44,11 @@ def print_shellcode(compiler_arch, temp_dir_path, print_function_addr, string_to step = ShellcodeStep( "first_step", - shellcode_address, [ ShellcodePrimitivePrint("print_stuff", print_function_addr, string_to_print), ], - 0x1000 + 0x1000, + base_address=shellcode_address, ) out_file = step.generate(temp_dir_path / step.nickname, compiler_arch) diff --git a/tests/test_step.py b/tests/test_step.py index 6f0c226..5d4ed16 100644 --- a/tests/test_step.py +++ b/tests/test_step.py @@ -7,7 +7,6 @@ def test_step_too_large_fails(temp_dir_path): step = ShellcodeStep( "first_step", - 0x1000, [ ShellcodePrimitiveMemcpy( f"copy_next_stage{i}", @@ -17,7 +16,8 @@ def test_step_too_large_fails(temp_dir_path): ) for i in range(6) ], - 0x10 + 0x10, + base_address=0x1000, ) with pytest.raises(Exception): From 09a4d0cf3a7b06923dce8c9b00e3b16bf8f4b09d Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Sun, 16 Feb 2025 10:08:49 +0200 Subject: [PATCH 4/5] readme: Update supported architectures --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a4ca72..dce99f0 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,13 @@ This repo allows you to concatenate shellcodes, running from different address spaces and links between them. Each shellcode will ensure the next will run, and will constitute from various primitives. -For starters, we will only support MIPS (le/be). +Supported architectures: + +- X86 and X64 +- Mips (LE and BE) +- Arm 32bit + +Adding another architecture is very simple! ## Shellcode primitives From 5af6d53de1adf9b772dbf5d799435e5384eb4bd4 Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Sun, 16 Feb 2025 10:12:19 +0200 Subject: [PATCH 5/5] readme: Add primitive example and update summary --- README.md | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dce99f0..d4bbc52 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ ## What is this repo? -This repo allows you to concatenate shellcodes, running from different address spaces and links between them. -Each shellcode will ensure the next will run, and will constitute from various primitives. +Allows you to write PIC and fast shellcodes in C! keeping your logic simple, easy to expand, test and maintain. +Shellcodes are seperated to "primitives", each one provides a behavior, and to create a full grown shellcode you can concatenate multiple primitives, or to create one primtives doing all of your logic. Supported architectures: @@ -15,6 +15,42 @@ Supported architectures: Adding another architecture is very simple! +## What does this mean? + +For example, see our implementation of goto: + +```c +void start(void) { + void (*goto_address)() = (void (*)())(GOTO_ADDRESS); + + goto_address(); +} +``` + +Our implementation of memcpy: + +```c +void __attribute__((noreturn)) start(void) { + u8 *src = (u8 *)MEMCPY_SOURCE_ADDRESS; + u8 *dst = (u8 *)MEMCPY_DEST_ADDRESS; + u32 len = (u32)MEMCPY_LEN; + + u8 *end = src + len; + + while (src < end - 1) { + *dst = *src; + src++; + dst++; + } + + *dst = *src; + + __builtin_unreachable(); +} +``` + +Super easy and to write even more complex code! + ## Shellcode primitives - Memcpy (Src Addr, Dst Addr, Len)