diff --git a/shellblocks/compiler_arch_option.py b/shellblocks/compiler_arch_option.py index d902a5c..14b2605 100644 --- a/shellblocks/compiler_arch_option.py +++ b/shellblocks/compiler_arch_option.py @@ -8,6 +8,7 @@ class CompilerArchOption(Enum): ARMLE = "armle" X86 = "x86" X86_64 = "x86_64" + POWERPCLE = "powerpcle" def get_current_platform(): @@ -28,5 +29,7 @@ def get_current_platform(): return CompilerArchOption.ARMLE if "x86_64-" in machine: return CompilerArchOption.X86_64 + if "powerpc64le-" in machine: + return CompilerArchOption.POWERPCLE return None diff --git a/shellblocks/compiler_archs/__init__.py b/shellblocks/compiler_archs/__init__.py index cf7d23e..0808f6e 100644 --- a/shellblocks/compiler_archs/__init__.py +++ b/shellblocks/compiler_archs/__init__.py @@ -3,6 +3,7 @@ from shellblocks.compiler_archs.arm import CompilerArchARMLE from shellblocks.compiler_archs.x86 import CompilerArchX86 from shellblocks.compiler_archs.x86_64 import CompilerArchX86_64 +from shellblocks.compiler_archs.powerpc import CompilerArchPowerPC from shellblocks.compiler_arch import CompilerArch @@ -17,6 +18,8 @@ def compiler_arch_to_object(arch: CompilerArchOption) -> CompilerArch: return CompilerArchX86() elif arch == CompilerArchOption.X86_64: return CompilerArchX86_64() + elif arch == CompilerArchOption.POWERPCLE: + return CompilerArchPowerPC() raise NotImplementedError() diff --git a/shellblocks/compiler_archs/powerpc.py b/shellblocks/compiler_archs/powerpc.py new file mode 100644 index 0000000..8595030 --- /dev/null +++ b/shellblocks/compiler_archs/powerpc.py @@ -0,0 +1,28 @@ +from typing import List + +from shellblocks.compiler_arch_option import CompilerArchOption +from shellblocks.compiler_archs.gcc import CompilerArchGCC +from shellblocks.utils import sources_location + + +class CompilerArchPowerPC(CompilerArchGCC): + def __init__(self): + super().__init__() + + def get_gcc_flags(self): + return super().get_gcc_flags() + [ + "-m32", + "-mbig", + ] + + def get_headers(self) -> List[str]: + return ["arch/powerpc/utils.h"] + + def get_ldscript_path(self): + return (sources_location / "shellcode_ldscript.ld").as_posix() + + def get_compiler_path(self): + return "powerpc64le-linux-gnu-gcc-10" + + def compiler_arch_option(self) -> [CompilerArchOption]: + return [CompilerArchOption.POWERPCLE] diff --git a/shellblocks/src/arch/powerpc/utils.h b/shellblocks/src/arch/powerpc/utils.h new file mode 100644 index 0000000..6112024 --- /dev/null +++ b/shellblocks/src/arch/powerpc/utils.h @@ -0,0 +1,15 @@ +#ifndef SHELLCODE_BLOCKS_ARCH_POWERPC_UTILS_H +#define SHELLCODE_BLOCKS_ARCH_POWERPC_UTILS_H + +#define NOP_OPCODE (0x60000000) + +#define GET_REL_ADDRESS(OUTPUT, LABEL) \ + __asm__ volatile ( \ + "bl " GET_REL_LABEL(LABEL) "\n\t" \ + "nop\n\t" \ + GET_REL_LABEL(LABEL) ": mr %0, 8\n\t" \ + "addis %0, %0, (" #LABEL " - " GET_REL_LABEL(LABEL) ")\n\t" \ + : "=r" (OUTPUT) : : "8" \ + ) + +#endif // !SHELLCODE_BLOCKS_ARCH_POWERPC_UTILS_H diff --git a/shellblocks/src/arch/utils.h b/shellblocks/src/arch/utils.h index 3800d50..17617be 100644 --- a/shellblocks/src/arch/utils.h +++ b/shellblocks/src/arch/utils.h @@ -7,6 +7,8 @@ #include "x86/utils.h" #elif defined(__arm__) #include "arm/utils.h" +#elif defined(__powerpc__) +#include "powerpc/utils.h" #endif #define REL_ACCESS_STRING __attribute__((section(".text"))) diff --git a/shellblocks/src/shellcode_ldscript.ld b/shellblocks/src/shellcode_ldscript.ld index 12c7104..640ab16 100644 --- a/shellblocks/src/shellcode_ldscript.ld +++ b/shellblocks/src/shellcode_ldscript.ld @@ -9,9 +9,4 @@ SECTIONS { *(.rodata*) } - - /DISCARD/ : - { - *(*) - } } diff --git a/shellblocks/test_arch_helper.py b/shellblocks/test_arch_helper.py index 9a0a683..ec3551d 100644 --- a/shellblocks/test_arch_helper.py +++ b/shellblocks/test_arch_helper.py @@ -1,6 +1,7 @@ from unicorn.mips_const import UC_MIPS_REG_PC, UC_MIPS_REG_29, UC_MIPS_REG_4 from unicorn.arm_const import UC_ARM_REG_PC, UC_ARM_REG_SP, UC_ARM_REG_R0 from unicorn.x86_const import UC_X86_REG_EIP, UC_X86_REG_ESP, UC_X86_REG_RDI +from unicorn.ppc_const import UC_PPC_REG_PC, UC_PPC_REG_1, UC_PPC_REG_3 from shellblocks.compiler_archs import CompilerArchOption @@ -58,6 +59,34 @@ def get_curr_func_arg(self, mu, func_arg): ) +class PowerPCHelper(ArchHelper): + def __init__(self, compiler_arch_option): + super().__init__(compiler_arch_option) + + assert compiler_arch_option in [ + CompilerArchOption.POWERPCLE, + ] + + def get_ret_bytes(self): + val = 0x4E800020 + return val.to_bytes(4, 'little') + + def get_curr_pc(self, mu): + return mu.reg_read(UC_PPC_REG_PC) + + def set_curr_sp(self, mu, new_stack): + mu.reg_write(UC_PPC_REG_1, new_stack) + + def get_curr_sp(self, mu): + return mu.reg_read(UC_PPC_REG_1) + + def get_curr_func_arg(self, mu, func_arg): + if func_arg == 0: + return mu.reg_read(UC_PPC_REG_3) + + raise NotImplementedError(f"Getting {func_arg} func arg") + + class ARMHelper(ArchHelper): def __init__(self, compiler_arch_option): super().__init__(compiler_arch_option) diff --git a/tests/conftest.py b/tests/conftest.py index d947c4a..f260138 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,14 +10,16 @@ UC_ARCH_ARM, UC_ARCH_X86, UC_MODE_ARM, + UC_ARCH_PPC, UC_MODE_32, UC_MODE_64, UC_MODE_BIG_ENDIAN, UC_MODE_LITTLE_ENDIAN, + UC_MODE_PPC32, ) -from shellblocks.test_arch_helper import MIPSHelper, ARMHelper, X86Helper +from shellblocks.test_arch_helper import MIPSHelper, ARMHelper, X86Helper, PowerPCHelper from shellblocks.compiler_archs import CompilerArchOption, compiler_arch_to_object @@ -52,6 +54,8 @@ def arch_helper(compiler_arch_option): return ARMHelper(compiler_arch_option) if compiler_arch_option in [CompilerArchOption.X86, CompilerArchOption.X86_64]: return X86Helper(compiler_arch_option) + if compiler_arch_option in [CompilerArchOption.POWERPCLE]: + return PowerPCHelper(compiler_arch_option) else: raise NotImplementedError("Arch unimplemented error!") @@ -69,6 +73,8 @@ def get_mu_instance(): return Uc(UC_ARCH_X86, UC_MODE_32) elif CompilerArchOption.X86_64 == compiler_arch_option: return Uc(UC_ARCH_X86, UC_MODE_64) + elif CompilerArchOption.POWERPCLE == compiler_arch_option: + return Uc(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN) else: raise NotImplementedError("Arch unimplemented error!")