From 9e9382036ccba94ebb26d0ac30f364489d92a579 Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Sun, 1 Sep 2024 13:50:13 +0300 Subject: [PATCH 1/5] shellblocks: primitive: Use mno-shared to avoid use of $gp The compilation of the print() primitive in newer compilers used the $gp register for keeping stuff. Using -mno-shared prevents this. --- shellblocks/shellcode_primitive.py | 1 + 1 file changed, 1 insertion(+) diff --git a/shellblocks/shellcode_primitive.py b/shellblocks/shellcode_primitive.py index 9ef7746..223e705 100644 --- a/shellblocks/shellcode_primitive.py +++ b/shellblocks/shellcode_primitive.py @@ -50,6 +50,7 @@ def generate(self, path: Path): "mips-linux-gnu-gcc-9", "-nostdlib", "-ffreestanding", + "-mno-shared", "-c", self.sources[0], "-o", "final.o", "-O3" From e460cb87600d2b32bf2096bf1966d8f8a3718bc6 Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Sun, 1 Sep 2024 14:57:14 +0300 Subject: [PATCH 2/5] shellblocks: src: Add utils_asm header for assembly primitives --- shellblocks/src/utils_asm.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 shellblocks/src/utils_asm.h diff --git a/shellblocks/src/utils_asm.h b/shellblocks/src/utils_asm.h new file mode 100644 index 0000000..b4f9f2d --- /dev/null +++ b/shellblocks/src/utils_asm.h @@ -0,0 +1,14 @@ +#ifndef SHELLCODE_BLOCKS_UTILS_ASM_H +#define SHELLCODE_BLOCKS_UTILS_ASM_H + +#define GET_PC(dst) \ + bal get_ip_reference; \ + nop; \ +get_ip_reference: \ + move dst, $ra + +#define GET_ADDRESS(dst, label, base) \ + move dst, base; \ + addiu dst, (label - get_ip_reference) + +#endif // !SHELLCODE_BLOCKS_UTILS_ASM_H From 9d706232bf84f170d5dbddb1e5c9b5e6d72d55d3 Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Sun, 1 Sep 2024 14:58:02 +0300 Subject: [PATCH 3/5] shellblocks: primitives: print: Use noreorder and cleaner code --- shellblocks/primitives/print.py | 2 +- shellblocks/src/print.S | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/shellblocks/primitives/print.py b/shellblocks/primitives/print.py index 7be8dc5..171344b 100644 --- a/shellblocks/primitives/print.py +++ b/shellblocks/primitives/print.py @@ -5,7 +5,7 @@ class ShellcodePrimitivePrint(ShellcodePrimitive): def __init__(self, nickname: str, print_function: int, print_string: str): super().__init__( nickname, - ["print.S", "utils.h"], + ["print.S", "utils_asm.h"], "print.S", "print.h" ) diff --git a/shellblocks/src/print.S b/shellblocks/src/print.S index a88bb1d..3903b58 100644 --- a/shellblocks/src/print.S +++ b/shellblocks/src/print.S @@ -1,4 +1,7 @@ #include "print.h" +#include "utils_asm.h" + +.set noreorder .global start start: @@ -6,13 +9,10 @@ start: addiu $sp, -4 sw $ra, 0($sp) - // Get $pc using bal - bal code - nop -code: - // bal somehow compiles to "bal + nop" so 2 opcodes - addiu $a0, $ra, (print_string - code + 4) - nop + // Calculate address of `print_string` + // relative to current $pc + GET_PC($v0) + GET_ADDRESS($a0, print_string, $v0) lui $v0, %hi(PRINT_FUNCTION_ADDRESS) addiu $v0, %lo(PRINT_FUNCTION_ADDRESS) @@ -27,6 +27,7 @@ code: // Jump over the printed string, to ensure we can run // another primitive after this one. b end_of_code + nop print_string: .asciiz PRINT_STRING @@ -34,3 +35,4 @@ print_string: end_of_code: nop + From 25c7326cbb31c3ab8bde79cf3de7d5f6fa69f9e1 Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Sun, 1 Sep 2024 14:35:48 +0300 Subject: [PATCH 4/5] shellblocks: primitives: goto: Use noreorder --- shellblocks/src/goto.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shellblocks/src/goto.S b/shellblocks/src/goto.S index a2cfa93..2371799 100644 --- a/shellblocks/src/goto.S +++ b/shellblocks/src/goto.S @@ -1,5 +1,7 @@ #include "goto.h" +.set noreorder + .global start start: lui $v0, %hi(GOTO_ADDRESS) From 3a491793bd4c2071f6650ebddd73c3d061a6c9f9 Mon Sep 17 00:00:00 2001 From: Shay Margolis Date: Thu, 12 Sep 2024 20:50:07 +0300 Subject: [PATCH 5/5] tests: jump_hook: Add is_pic() test --- tests/test_jump_hook.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/test_jump_hook.py b/tests/test_jump_hook.py index b750fc5..25632a1 100644 --- a/tests/test_jump_hook.py +++ b/tests/test_jump_hook.py @@ -9,6 +9,12 @@ SECTOR_SIZE = 0x2000 +@pytest.mark.parametrize('shellcode_run_addr', [ + (0x82000010), + (0xbc100010), + (0xbcd00010), + (0x91100118), +]) @pytest.mark.parametrize('jump_hook_location', [ 0x81000010, 0xbc000010, @@ -21,11 +27,12 @@ 0xbcf00070, 0x910f0218, ]) -def test_jump_hook_sanity(temp_dir_path, jump_hook_location, jump_hook_goto): +def test_jump_hook_sanity(temp_dir_path, shellcode_run_addr, jump_hook_location, jump_hook_goto): # Generate shellcode # ------------------ shellcode_address = 0xbfc00000 jump_hook_sector = int(jump_hook_location/SECTOR_SIZE) * SECTOR_SIZE + shellcode_run_sector = int(shellcode_run_addr/SECTOR_SIZE) * SECTOR_SIZE step = ShellcodeStep( "first_step", @@ -57,15 +64,15 @@ def test_jump_hook_sanity(temp_dir_path, jump_hook_location, jump_hook_goto): # -------------------- mu = Uc(UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_BIG_ENDIAN) - mu.mem_map(shellcode_address, 0x2000) + mu.mem_map(shellcode_run_sector, 0x2000) mu.mem_map(jump_hook_sector, 0x2000) # write machine code to be emulated to memory - mu.mem_write(shellcode_address, shellcode) + mu.mem_write(shellcode_run_addr, shellcode) mu.mem_write(jump_hook_sector, b"\x00" * 0x1000) # emulate code in infinite time & unlimited instructions - mu.emu_start(shellcode_address, shellcode_address + len(shellcode)) + mu.emu_start(shellcode_run_addr, shellcode_run_addr + len(shellcode)) assert mu.mem_read(jump_hook_location, len(EXPECTED_HOOK)) == EXPECTED_HOOK assert mu.mem_read(jump_hook_location+len(EXPECTED_HOOK), 1) == (b"\x00")