Git Product home page Git Product logo

sashs / ropper Goto Github PK

View Code? Open in Web Editor NEW
1.8K 55.0 208.0 2.46 MB

Display information about files in different file formats and find gadgets to build rop chains for different architectures (x86/x86_64, ARM/ARM64, MIPS, PowerPC, SPARC64). For disassembly ropper uses the awesome Capstone Framework.

Home Page: https://scoding.de/ropper

License: BSD 3-Clause "New" or "Revised" License

Python 99.81% Shell 0.01% Dockerfile 0.17%
rop exploitation binary gadget-finder gadgets rop-chains

ropper's Introduction

Ropper

Build Status

You can use ropper to display information about binary files in different file formats and you can search for gadgets to build rop chains for different architectures (x86/X86_64, ARM/ARM64, MIPS/MIPS64, PowerPC/PowerPC64, SPARC64). For disassembly ropper uses the awesome Capstone Framework.

Install

Install Capstone with PyPi:

$ sudo pip install capstone

Install filebytes with PyPi:

$ sudo pip install filebytes

Optional (not needed to run ropper just to look for gadgets):

Install Keystone:

$ sudo pip install keystone-engine

Install and execute Ropper

$ python setup.py install
$ ropper

You can also install Ropper with pip

$ pip install ropper

If you want, you can use Ropper without installation

$ ./Ropper.py

If you don't want to install filebytes, filebytes is a submodule of the ropper repository. This means you don't need to install filebytes and ropper.

$ git clone https://github.com/sashs/ropper.git
$ cd ropper
$ git submodule init
$ git submodule update
$ ./Ropper.py

THIS FEATURE IS STILL UNDER DEVELOPEMENT! Ropper has a semantic search command, which offers the possiblity to search for gadgets.

$ ropper --file <afile> --semantic "<any constraint>"

The following optional dependencies are needed to use semantic search:

Install pyvex

$ sudo pip install pyvex

Install z3py

$ python scripts/mk_make.py
$ cd build
$ make
$ sudo make install

Currently Possible Constraints

reg == reg     -  assign register to another
reg == number  -  assign number to register
reg == [reg]   -  assign memory to register
reg += number/reg/[reg]
reg -= number/reg/[reg]
reg *= number/reg/[reg]
reg /= number/reg/[reg]

Constraint Example

eax==1 !ebx    - set eax to 1 and look for gadgets which does not clobber ebx

semantic_search

Usage

usage: Ropper.py [-h] [--help-examples] [-v] [--console]
             [-f <file> [<file> ...]] [-r] [-a <arch>]
             [--section <section>] [--string [<string>]] [--hex]
             [--asm [<asm> [H|S|R] ...]] [--disasm <opcode>]
             [--disassemble-address <address:length>] [-i] [-e]
             [--imagebase] [-c] [-s] [-S] [--imports] [--symbols]
             [--set <option>] [--unset <option>] [-I <imagebase>] [-p]
             [-j <reg>] [--stack-pivot] [--inst-count <n bytes>]
             [--search <regex>] [--quality <quality>] [--opcode <opcode>]
             [--instructions <instructions>] [--type <type>] [--detailed]
             [--all] [--cfg-only] [--chain <generator>] [-b <badbytes>]
             [--nocolor] [--clear-cache] [--no-load] [--analyse <quality>]
             [--semantic constraint]
             [--count-of-findings <count of gadgets>] [--single]

You can use ropper to display information about binary files in different file formats
    and you can search for gadgets to build rop chains for different architectures

supported filetypes:
  ELF
  PE
  Mach-O
  Raw

supported architectures:
  x86 [x86]
  x86_64 [x86_64]
  MIPS [MIPS, MIPS64]
  ARM/Thumb [ARM, ARMTHUMB]
  ARM64 [ARM64]
  PowerPC [PPC, PPC64]
  SPARC [SPARC64]

available rop chain generators:
  execve (execve[=<cmd>], default /bin/sh) [Linux x86, x86_64]
  mprotect  (mprotect=<address>:<size>) [Linux x86, x86_64]
  virtualprotect (virtualprotect=<address iat vp>:<size>) [Windows x86]

options:
  -h, --help            show this help message and exit
  --help-examples       Print examples
  -v, --version         Print version
  --console             Starts interactive commandline
  -f <file> [<file> ...], --file <file> [<file> ...]
                        The file to load
  -r, --raw             Loads the file as raw file
  -a <arch>, --arch <arch>
                        The architecture of the loaded file
  --section <section>   The data of this section should be printed
  --string [<string>]   Looks for the string <string> in all data sections
  --hex                 Prints the selected sections in a hex format
  --asm [<asm> [H|S|R] ...]
                        A string to assemble and a format of the output
                        (H=HEX, S=STRING, R=RAW, default: H)
  --disasm <opcode>     Opcode to disassemble (e.g. ffe4, 89c8c3, ...)
  --disassemble-address <address:length>
                        Disassembles instruction at address <address>
                        (0x12345678:L3). The count of instructions to
                        disassemble can be specified (0x....:L...)
  -i, --info            Shows file header [ELF/PE/Mach-O]
  -e                    Shows EntryPoint
  --imagebase           Shows ImageBase [ELF/PE/Mach-O]
  -c, --dllcharacteristics
                        Shows DllCharacteristics [PE]
  -s, --sections        Shows file sections [ELF/PE/Mach-O]
  -S, --segments        Shows file segments [ELF/Mach-O]
  --imports             Shows imports [ELF/PE]
  --symbols             Shows symbols [ELF]
  --set <option>        Sets options. Available options: aslr nx
  --unset <option>      Unsets options. Available options: aslr nx
  -I <imagebase>        Use this imagebase for gadgets
  -p, --ppr             Searches for 'pop reg; pop reg; ret' instructions
                        [only x86/x86_64]
  -j <reg>, --jmp <reg>
                        Searches for 'jmp reg' instructions (-j reg[,reg...])
                        [only x86/x86_64]
  --stack-pivot         Prints all stack pivot gadgets
  --inst-count <n bytes>
                        Specifies the max count of instructions in a gadget
                        (default: 6)
  --search <regex>      Searches for gadgets
  --quality <quality>   The quality for gadgets which are found by search (1 =
                        best)
  --opcode <opcode>     Searches for opcodes (e.g. ffe4 or ffe? or ff??)
  --instructions <instructions>
                        Searches for instructions (e.g. "jmp esp", "pop eax;
                        ret")
  --type <type>         Sets the type of gadgets [rop, jop, sys, all]
                        (default: all)
  --detailed            Prints gadgets more detailed
  --all                 Does not remove duplicate gadgets
  --cfg-only            Filters out gadgets which fail the Microsoft CFG
                        check. Only for PE files which are compiled with CFG
                        check enabled (check DllCharachteristics) [PE]
  --chain <generator>   Generates a ropchain [generator parameter=value[
                        parameter=value]]
  -b <badbytes>, --badbytes <badbytes>
                        Set bytes which should not be contained in gadgets
  --nocolor             Disables colored output
  --clear-cache         Clears the cache
  --no-load             Don't load the gadgets automatically when starting the
                        console (--console)
  --analyse <quality>   just used for the implementation of semantic search
  --semantic constraint
                        semantic search for gadgets
  --count-of-findings <count of gadgets>
                        Max count of gadgets which will be printed with
                        semantic search (0 = undefined, default: 5)
  --single              No multiple processes are used for gadget scanning

example uses:
  [Generic]
  ./Ropper.py
  ./Ropper.py --file /bin/ls --console

  [Informations]
  ./Ropper.py --file /bin/ls --info
  ./Ropper.py --file /bin/ls --imports
  ./Ropper.py --file /bin/ls --sections
  ./Ropper.py --file /bin/ls --segments
  ./Ropper.py --file /bin/ls --set nx
  ./Ropper.py --file /bin/ls --unset nx
  ./Ropper.py --file /bin/ls --inst-count 5
  ./Ropper.py --file /bin/ls --search "sub eax" --badbytes 000a0d
  ./Ropper.py --file /bin/ls --search "sub eax" --detail
  ./Ropper.py --file /bin/ls --filter "sub eax"
  ./Ropper.py --file /bin/ls --inst-count 5 --filter "sub eax"
  ./Ropper.py --file /bin/ls --opcode ffe4
  ./Ropper.py --file /bin/ls --opcode ffe?
  ./Ropper.py --file /bin/ls --opcode ??e4
  ./Ropper.py --file /bin/ls --detailed
  ./Ropper.py --file /bin/ls --ppr --nocolor
  ./Ropper.py --file /bin/ls --jmp esp,eax
  ./Ropper.py --file /bin/ls --type jop
  ./Ropper.py --file /bin/ls --chain execve
  ./Ropper.py --file /bin/ls --chain "execve cmd=/bin/sh" --badbytes 000a0d
  ./Ropper.py --file /bin/ls --chain "mprotect address=0xbfdff000 size=0x21000"
  ./Ropper.py --file /bin/ls /lib/libc.so.6 --console

  [Assemble/Disassemble]
  ./Ropper.py --asm "jmp esp"
  ./Ropper.py --asm "mov eax, ecx; ret"
  ./Ropper.py --disasm ffe4

  [Search]
  ./Ropper.py --file /bin/ls --search <searchstring>
  ?     any character
  %     any string

  Example:

  ./Ropper.py --file /bin/ls --search "mov e?x"
  0x000067f1: mov edx, dword ptr [ebp + 0x14]; mov dword ptr [esp], edx; call eax
  0x00006d03: mov eax, esi; pop ebx; pop esi; pop edi; pop ebp; ret ;
  0x00006d6f: mov ebx, esi; mov esi, dword ptr [esp + 0x18]; add esp, 0x1c; ret ;
  0x000076f8: mov eax, dword ptr [eax]; mov byte ptr [eax + edx], 0; add esp, 0x18; pop ebx; ret ;

  ./Ropper.py --file /bin/ls --search "mov [%], edx"
  0x000067ed: mov dword ptr [esp + 4], edx; mov edx, dword ptr [ebp + 0x14]; mov dword ptr [esp], edx; call eax;
  0x00006f4e: mov dword ptr [ecx + 0x14], edx; add esp, 0x2c; pop ebx; pop esi; pop edi; pop ebp; ret ;
  0x000084b8: mov dword ptr [eax], edx; ret ;
  0x00008d9b: mov dword ptr [eax], edx; add esp, 0x18; pop ebx; ret ;

  ./Ropper.py --file /bin/ls --search "mov [%], edx" --quality 1
  0x000084b8: mov dword ptr [eax], edx; ret ;; ret ;

Use ropper in Scripts

#!/usr/bin/env python
from ropper import RopperService

# not all options need to be given
options = {'color' : False,     # if gadgets are printed, use colored output: default: False
            'badbytes': '00',   # bad bytes which should not be in addresses or ropchains; default: ''
            'all' : False,      # Show all gadgets, this means to not remove double gadgets; default: False
            'inst_count' : 6,   # Number of instructions in a gadget; default: 6
            'type' : 'all',     # rop, jop, sys, all; default: all
            'detailed' : False} # if gadgets are printed, use detailed output; default: False

rs = RopperService(options)

##### change options ######
rs.options.color = True
rs.options.badbytes = '00'
rs.options.badbytes = ''
rs.options.all = True


##### open binaries ######
# it is possible to open multiple files
rs.addFile('test-binaries/ls-x86')
rs.addFile('ls', bytes=open('test-binaries/ls-x86','rb').read()) # other possiblity
rs.addFile('ls_raw', bytes=open('test-binaries/ls-x86','rb').read(), raw=True, arch='x86')

##### close binaries ######
rs.removeFile('ls')
rs.removeFile('ls_raw')


# Set architecture of a binary, so it is possible to look for gadgets for a different architecture
# It is useful for ARM if you want to look for ARM gadgets or Thumb gadgets
# Or if you opened a raw file
ls = 'test-binaries/ls-x86'
rs.setArchitectureFor(name=ls, arch='x86')
rs.setArchitectureFor(name=ls, arch='x86_64')
rs.setArchitectureFor(name=ls, arch='ARM')
rs.setArchitectureFor(name=ls, arch='ARMTHUMB')
rs.setArchitectureFor(name=ls, arch='ARM64')
rs.setArchitectureFor(name=ls, arch='MIPS')
rs.setArchitectureFor(name=ls, arch='MIPS64')
rs.setArchitectureFor(name=ls, arch='PPC')
rs.setArchitectureFor(name=ls, arch='PPC64')
rs.setArchitectureFor(name=ls, arch='SPARC64')
rs.setArchitectureFor(name=ls, arch='x86')


##### load gadgets ######

# load gadgets for all opened files
rs.loadGadgetsFor() 

# load gadgets for only one opened file
ls = 'test-binaries/ls-x86'
rs.loadGadgetsFor(name=ls)

# change gadget type
rs.options.type = 'jop'
rs.loadGadgetsFor() 

rs.options.type = 'rop'
rs.loadGadgetsFor() 

# change instruction count
rs.options.inst_count = 10
rs.loadGadgetsFor() 

##### print gadgets #######
rs.printGadgetsFor() # print all gadgets
rs.printGadgetsFor(name=ls)

##### Get gadgets ######
gadgets = rs.getFileFor(name=ls).gadgets


##### search pop pop ret ######
pprs = rs.searchPopPopRet(name=ls) # looks for ppr only in 'test-binaries/ls-x86'
pprs = rs.searchPopPopRet()        # looks for ppr in all opened files
for file, ppr in pprs.items():
    for p in ppr:
        print p

##### load jmp reg ######
jmp_regs = rs.searchJmpReg(name=ls, regs=['esp', 'eax']) # looks for jmp reg only in 'test-binaries/ls-x86'
jmp_regs = rs.searchJmpReg(regs=['esp', 'eax'])
jmp_regs = rs.searchJmpReg()                             # looks for jmp esp in all opened files
for file, jmp_reg in jmp_regs.items():
    for j in jmp_reg:
        print j


##### search opcode ######
ls = 'test-binaries/ls-x86'
gadgets_dict = rs.searchOpcode(opcode='ffe4', name=ls)
gadgets_dict = rs.searchOpcode(opcode='ffe?')
gadgets_dict = rs.searchOpcode(opcode='??e4')

for file, gadgets in gadgets_dict.items():
    for g in gadgets:
        print g

##### search instructions ######
ls = 'test-binaries/ls-x86'
for file, gadget in rs.search(search='mov e?x', name=ls):
    print file, gadget

for file, gadget in rs.search(search='mov [e?x%]'):
    print file, gadget    

result_dict = rs.searchdict(search='mov eax')
for file, gadgets in result_dict.items():
    print file
    for gadget in gadgets:
        print gadget

##### assemble instructions ######
hex_string = rs.asm('jmp esp')
print '"jmp esp" assembled to hex string =', hex_string
raw_bytes = rs.asm('jmp esp', format='raw')
print '"jmp esp" assembled to raw bytes =', raw_bytes
string = rs.asm('jmp esp', format='string')
print '"jmp esp" assembled to string =',string
arm_bytes = rs.asm('bx sp', arch='ARM')
print '"bx sp" assembled to hex string =', arm_bytes

##### disassemble bytes #######
arm_instructions = rs.disasm(arm_bytes, arch='ARM')
print arm_bytes, 'disassembled to "%s"' % arm_instructions

# Change the imagebase, this also change the imagebase for all loaded gadgets of this binary
rs.setImageBaseFor(name=ls, imagebase=0x0)

# reset image base
rs.setImageBaseFor(name=ls, imagebase=None)

gadgets = rs.getFileFor(name=ls).gadgets

# gadget address
print hex(gadgets[0].address)

# get instruction bytes of gadget
print bytes(gadgets[0].bytes).encode('hex')

# remove all gadgets containing bad bytes in address
rs.options.badbytes = '000a0d'  # gadgets are filtered automatically

Project page

http://scoding.de/ropper

Screenshots

load

x86

arm

mips

ppc

ropchain

header

ropper's People

Contributors

0ki avatar aagallag avatar anthraxx avatar aquynh avatar baltazarortiz avatar bet4it avatar bignerd95 avatar cbayet-synacktiv avatar ddlws avatar doronz88 avatar eternaleclipse avatar kristal-g avatar layderv avatar mkrasnitski avatar moshekaplan avatar oddrabbit avatar poniponiponiponiponiponiponiponiponi avatar robertlarsen avatar rsashs avatar rsesek avatar sashs avatar shxdow avatar thebitshifter avatar thorkill avatar tomg404 avatar xairy avatar xvilka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ropper's Issues

Installation only possible if capstone gets compiled on the system

Hey Sasha,

first thanks for the great tool. I was introduced to it by Saumil while doing a training he gave.

I would like to use the tool on windows as well, not only on my linux machines. I tried to install it using the small guide you show in your README.md.

I have the requirement that I don't want to install cygwin to compile Capstone because I guess that is not necessary, right ? There is precompiled binary windows package which can be installed as following:

pip install capstone-windows

Basically I thought that you mind accept this as well but the installer unfortunately failed. See the error message here:

Installed c:\python27\lib\site-packages\ropper-1.9.2-py2.7.egg Processing dependencies for ropper==1.9.2 Searching for capstone Reading https://pypi.python.org/simple/capstone/ Best match: capstone 3.0.4 Downloading https://pypi.python.org/packages/e7/29/e9ad2a12c38f19e9ca8aff05122e5b9e271da6ecbfb6c4e20aee381b49ff/capstone-3.0.4.tar.gz#md5=3437fa632c89531a7d800a3f8c04fbe3 Processing capstone-3.0.4.tar.gz Writing c:\users\xxx\appdata\local\temp\easy_install-wou9zr\capstone-3.0.4\setup.cfg Running capstone-3.0.4\setup.py -q bdist_egg --dist-dir c:\users\xxx\appdata\local\temp\easy_install-wou9zr\capstone-3.0.4\egg-dist-tmp-qch518 'cmake' is not recognized as an internal or external command, operable program or batch file. 'nmake' is not recognized as an internal or external command, operable program or batch file. error: Setup script exited with error: can't copy 'src\build\capstone.dll': doesn't exist or not a regular file

I can see that nmake is missing which makes sense, I don't have it installed. But again I don't want to compile Capstone from scratch.

Can you eventually modify the setup in a way that it accepts the capstone-windows distribution as well ? Or maybe I'm missing something basic here !?

Thank you for your efforts!

mitp0sh of [PDX]

Fail to load ImageBase for relative path files

If a file is loaded in ropper with a relative path (i.e. "../test/a.out") the base address of all gadgets is wrong.
To reproduce

from ropper import RopperService
rs = RopperService()
rs.addFile("../test/a.out")
rs.loadGadgetsFor(name="../test/a.out")
ropper_gadgets = rs.getFileFor(name="../test/a.out").gadgets
g = ropper_gadgets[0]
print g.imageBase

It results in 0

This is due to the fact that g.imageBase is calling

@property
    def imageBase(self):
        return Gadget.IMAGE_BASES.get(self._fileName,0)

and Gadget.IMAGE_BASES is set as

{'../test/a.out': 134512640L}

while self._fileName is set to "a.out"

some gadgets may not be found

Hi, I have noticed that some gadgets may not be shown under certain circumstances.

an example would be provided by this simple program:

#include <unistd.h>
#include <sys/types.h>

static int64_t test()
{
    return -1;
}

int main()
{
    return test();
}

This should have the following gadget (depending on representation the content could also be a -1):

mov rax,0xffffffffffffffff
pop rbp
ret

the output of objdump:

objdump -d ./test -Mintel|grep ret -B3
--
  4004a7:   48 89 e5                mov    rbp,rsp
  4004aa:   48 c7 c0 ff ff ff ff    mov    rax,0xffffffffffffffff
  4004b1:   5d                      pop    rbp
  4004b2:   c3                      ret    

search via ropper (not its also not available via listing all gadgets with the gadgets command:

(ropper) file ./test
[INFO] File loaded.

(ropper) badbytes
[INFO] badbytes cleared
[INFO] Filter gadgets of all opened files
[INFO] Filtering gadgets finished
[INFO] Gadgets have to be reloaded

(ropper) load
[INFO] Loading gadgets for section: PHDR
[LOAD] loading... 100%
[INFO] Loading gadgets for section: LOAD
[LOAD] loading... 100%
[INFO] deleting double gadgets...
[LOAD] clearing up... 100%
[INFO] gadgets loaded.

(ropper) search mov rax
[INFO] Search in gadgets of file './test'
[INFO] Searching for gadgets: mov rax
[LOAD] searching gadgets... 100%

Gadgets
=======
0 gadgets found

Error on generating execve ropchain

I am getting error on running ropper -f bin --chain execve

The binary is static x86 32-bit

[ERROR] Please report this error on https://github.com/sashs/ropper
[ERROR] Traceback (most recent call last):
File "/home/aditya/ropper/ropper/console.py", line 53, in cmd
func(self, text)
File "/home/aditya/ropper/ropper/console.py", line 488, in __handleOptions
self.__generateChain(options.chain)
File "/home/aditya/ropper/ropper/console.py", line 365, in __generateChain
raise e
NameError: global name 'regs' is not defined

Build ROP chain for X86_64 Problem

Ropper is really great tool. Now I try to use it to build ROP chain for x86_64 binary. I always meet one error: "[ERROR] generator execve is for arch ArchitectureX86_64 not available". I also check /ropper/ropchian/arch, there is only x86. So it is only support to build rop chain for x86 binary, right?
Thanks.
Pengfei

Gadget with multiple pops is incorrectly padded

The same gadget that's been causing trouble in Issue #67 is also being handled incorrectly when it comes to padding the pops that aren't being used. The following is appearing in an execve chain:

rop += rebase_0(0x0000000000078ec6) # 0x0000000000478ec6: pop rax; pop rdx; pop rbx; ret; 
rop += p(0xdeadbeefdeadbeef)
rop += p(0xdeadbeefdeadbeef)
rop += p(0x000000000000003b)

rax is supposed to be getting the 0x3b value, but the ordering of the padding results in rbx actually getting this value and rax getting 0xdeadbeef.

Make install_requires meaningful.

Description

Since you exported many symbols in ropper/__init__.py and also kept VERSION in it, import ropper in setup.py will fail when the user does not installed capstone and filebytes, which means install_requires is of no use and every user has to install them manually.

Simply speaking, pip install ropper or python setup.py install will never work unless the user has manually installed capstone and filebytes, which is, as a matter of fact, inconvenient.

Sample Output

$ pip freeze                                                                                                                         :(
$ pip install ropper
Collecting ropper
  Using cached ropper-1.8.0.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-z6hx5_9l/ropper/setup.py", line 2, in <module>
        import ropper
      File "/tmp/pip-build-z6hx5_9l/ropper/ropper/__init__.py", line 20, in <module>
        from .console import Console
      File "/tmp/pip-build-z6hx5_9l/ropper/ropper/console.py", line 20, in <module>
        from ropper.loaders.loader import Loader,Type
      File "/tmp/pip-build-z6hx5_9l/ropper/ropper/loaders/__init__.py", line 20, in <module>
        from . import elf
      File "/tmp/pip-build-z6hx5_9l/ropper/ropper/loaders/elf.py", line 21, in <module>
        from ropper.loaders.loader import *
      File "/tmp/pip-build-z6hx5_9l/ropper/ropper/loaders/loader.py", line 24, in <module>
        from ropper.arch import *
      File "/tmp/pip-build-z6hx5_9l/ropper/ropper/arch.py", line 26, in <module>
        from capstone import *
    ImportError: No module named 'capstone'

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-z6hx5_9l/ropper/

ropper cannot find exec chain in calc.exe

ropper --file calc.exe --chain execve
[INFO] Load gadgets from cache
[LOAD] removing double gadgets... 100%

[INFO] ROPchain Generator for syscall execve:

[INFO]
write command into data section
eax 0xb
ebx address to cmd
ecx address to null
edx address to null

[ERROR] 'PE' object has no attribute 'sections'
[ERROR] Please report this error on https://github.com/sashs/ropper

NameError: global name 'regs' is not defined

[ERROR] Traceback (most recent call last):
File "build/bdist.linux-x86_64/egg/ropper/console.py", line 53, in cmd
func(self, text)
File "build/bdist.linux-x86_64/egg/ropper/console.py", line 485, in __handleOptions
self.__generateChain(options.chain)
File "build/bdist.linux-x86_64/egg/ropper/console.py", line 363, in __generateChain
raise e
NameError: global name 'regs' is not defined

Filebytes module missing

Hi!

I followed the instructions to just run Ropper without installation, but it doesn't work:

master@mind:~$ git clone https://github.com/sashs/ropper.git
Cloning into 'ropper'...
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 3507 (delta 5), reused 11 (delta 5), pack-reused 3493
Receiving objects: 100% (3507/3507), 2.28 MiB | 950.00 KiB/s, done.
Resolving deltas: 100% (2464/2464), done.
master@mind:~$ cd ropper/
master@mind:~/ropper$ git sub
submodule   subtree
master@mind:~/ropper$ git submodule init
Submodule 'filebytes' (https://github.com/sashs/filebytes.git) registered for path 'filebytes'
master@mind:~/ropper$ git submodule update
Cloning into '/home/master/ropper/filebytes'...
Submodule path 'filebytes': checked out 'dafdbe6ab642041bfdedd8d09676944e80e13ce2'
master@mind:~/ropper$ ./Ropper.py
Traceback (most recent call last):
  File "./Ropper.py", line 21, in <module>
    import ropper
  File "/home/master/ropper/ropper/__init__.py", line 19, in <module>
    from filebytes.pe import ImageDirectoryEntry
ImportError: No module named filebytes.pe

I don't understand why it doesn't work anymore. It has worked for sure in the past, but after the new git pull I had this issue. Even creating a new clone of the repo doesn't seem to help (as you can see above).

Gadget with multiple pops is incorrectly categorized

Given the instructions pop rax; pop rdx; pop rbx; ret; , the Gadget object categorizes it as (LOAD_REG, 3, {'dst': 'rax'}).

However, this misses the rdx and rbx destinations, so the gadget will be incorrectly used in chains by the ropchain _createDependenceChain function if the chain is not supposed to have rdx or rbx in it.

Working on a fix in gadget.py's category function, but not super familiar with the codebase so I'm less clear on the best approach for this one.

Enhancement: Memory scanning, core dump parsing

Currently it is possible to scan memory only by dumping it manually to a file and using the --raw option. A useful feature would be the ability to parse core dump files (gdb can generate core dumps using the gcore command, WinDBG has a similar command called .dump) and scan executable pages in the entire process memory for gadgets. This can also be used to access the process state, register, stack etc and as suggested in #40.

Use of __import__

__import__('ropper').start(sys.argv[1:])

From __import__'s help:

    Import a module. Because this function is meant for use by the Python
    interpreter and not for general use it is better to use
    importlib.import_module() to programmatically import a module.

Besides, importing with a string could cause problems with static code analysis tools and IDEs so it's usually a good idea to avoid them when possible.

Why not just import ropper?

Limit memory/cpu usage

TLDR: Ropper may take enormous amount of memory (e.g. ~4GB for a 200MB binary) and fails on fork with OOM (out of mem):

dc@ubuntu:~/train/snote_pwn/snote$ ropper -f vmlinux 
 
[INFO] Load gadgets for section: LOAD
[LOAD] loading... 100%
[INFO] Load gadgets for section: LOAD
[ERROR] Please report this error on https://github.com/sashs/ropper
[ERROR] Traceback (most recent call last):
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/console.py", line 53, in cmd
    func(self, text)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/console.py", line 492, in __handleOptions
    self.__loadGadgets()
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/console.py", line 290, in __loadGadgets
    self.__searchGadgetsFor(self.currentFileName)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/console.py", line 294, in __searchGadgetsFor
    self.__rs.loadGadgetsFor(binary)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/service.py", line 622, in loadGadgetsFor
    load_gadgets(fc)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/service.py", line 607, in load_gadgets
    f.allGadgets = self.__ropper.searchGadgets(f.loader, instructionCount=self.options.inst_count, gtype=gtype)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/rop.py", line 277, in searchGadgets
    newGadgets = self._searchGadgetsForked(section=section, binary=binary, instruction_count=instructionCount, gtype=gtype)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/rop.py", line 361, in _searchGadgetsForked
    processes[cpu].start()
  File "/usr/lib/python2.7/multiprocessing/process.py", line 130, in start
    self._popen = Popen(self)
  File "/usr/lib/python2.7/multiprocessing/forking.py", line 121, in __init__
    self.pid = os.fork()
OSError: [Errno 12] Cannot allocate memory

It would be nice to have an option to either limiting number of proceses or just a single process mode.

Colon in filename, cannot git clone on windows

Since NTFS does not allow : in filenames, git fails to clone the repository:

$ git clone https://github.com/sashs/Ropper
Cloning into 'Ropper'...
remote: Enumerating objects: 83, done.
remote: Counting objects: 100% (83/83), done.
remote: Compressing objects: 100% (52/52), done.
remote: Total 3450 (delta 38), reused 59 (delta 30), pack-reuRecsed 3367
Receiving objects: 100% (3450/3450), 2.30 MiB | 1.21 MiB/s, done.
Resolving deltas: 100% (2410/2410), done.
Checking connectivity... done.
error: unable to create file test-binaries/hang-mutate_bytes2:3da2c4818ffe26a52b06b348969026f3:.exe (Invalid argument)
fatal: unable to checkout working tree
warning: Clone succeeded, but checkout failed.
You can inspect what was checked out with 'git status'
and retry the checkout with 'git checkout -f HEAD'

Ropper tries to work on previously opened path

Ropper tries to open a previously opened path, if currently passed filename and previously opened filename are the same.

Steps to reproduce:

rm -r ~/.ropper
cp /bin/ls /tmp/myfile
~/Ropper/Ropper.py -f /tmp/myfile --chain execve
mkdir /tmp/a
mv /tmp/myfile /tmp/a/myfile
~/Ropper/Ropper.py -f /tmp/a/myfile --chain execve
[INFO] Load gadgets from cache
[LOAD] loading... 100%

...

[INFO] syscall opcode not found
[ERROR] Please report this error on https://github.com/sashs/ropper
[ERROR] Traceback (most recent call last):
  File "/home/user/Ropper/ropper/console.py", line 53, in cmd
    func(self, text)
  File "/home/user/Ropper/ropper/console.py", line 485, in __handleOptions
    self.__generateChain(options.chain)
  File "/home/user/Ropper/ropper/console.py", line 363, in __generateChain
    raise e
KeyError: '/tmp/myfile'

The reason for this probably has to do with the way the cache is handled in ~/.ropper/cache.

bug ropchain generation breaks history commands

Hi again Sashs,
I hope you are having a nice day :)

When generating a ropchain, then checking history command (UP keypress) once, then returning back (DOWN keypress), the history command will contain a broken command instead of a blank one.
Example:
(a.dll/PE/x86)> ropchain virtualprotect address=0x123456

[INFO] Ropchain Generator for VirtualProtect:

[INFO] eax 0x90909090
ecx old protection (writable addr)
edx 0x40 (RWE)
ebx size
esp address
ebp return address (jmp esp)
esi pointer to VirtualProtect
edi ret (rop nop)

[INFO] Try to create gadget to fill esi with content of IAT address: 0x123456
[INFO] Try to create chain which fills registers without delete content of previous filled registers
[*] Try permuation 3 / 720
[INFO] Look for pushad gadget
[INFO] generating rop chain

!/usr/bin/env python

Generated by ropper ropchain generator

from struct import pack
[...removed...]
rop = ''
[...removed...]
rop += shellcode

print(rop)

[INFO] rop chain generated!
(a.dll/PE/x86)> ropchain vi

The "ropchain vi" was obtained after pressing "UP" then "DOWN" keys :)

Have fun,

multiple file opening at once

Hi,

Great project !

Is it possible to implement a feature that allows multiple file opening ?

  • multiple files in one line
  • usage of wildcards.

Thank you :)

AVR Support

Is AVR Support planned? Would be cool for Arduino exploitation.

I know that it's currently not supported because I just tried it and got the following error message:

Please report this error on https://github.com/sashs/ropper
Stacktrace:
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/ropper/loaders/elf.py", line 53, in _loadDefaultArch
    return getArch( (machine,cls, end ),self._binary.elfHeader.header.e_entry)
  File "/usr/lib/python3.6/site-packages/ropper/loaders/elf.py", line 124, in getArch
    arch = ARCH[params[0]]
KeyError: (<filebytes.enum.IntEnumElement object at 0x7f8d419dfac8>, <filebytes.enum.IntEnumElement object at 0x7f8d419e1208>, 1)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/ropper/__init__.py", line 42, in start
    Console(app_options).start()
  File "/usr/lib/python3.6/site-packages/ropper/console.py", line 175, in start
    self.__loadFile(file)
  File "/usr/lib/python3.6/site-packages/ropper/console.py", line 194, in __loadFile
    arch=self.__options.arch)
  File "/usr/lib/python3.6/site-packages/ropper/service.py", line 495, in addFile
    loader = Loader.open(name, bytes=bytes, raw=raw, arch=arch)
  File "/usr/lib/python3.6/site-packages/ropper/loaders/loader.py", line 158, in open
    return subclass(fileName, bytes)
  File "/usr/lib/python3.6/site-packages/ropper/loaders/elf.py", line 36, in __init__
    super(ELF, self).__init__(filename, bytes, arch)
  File "/usr/lib/python3.6/site-packages/ropper/loaders/loader.py", line 74, in __init__
    self._arch = self._loadDefaultArch()
  File "/usr/lib/python3.6/site-packages/ropper/loaders/elf.py", line 55, in _loadDefaultArch
    raise RopperError(e)
ropper.common.error.RopperError: (<filebytes.enum.IntEnumElement object at 0x7f8d419dfac8>, <filebytes.enum.IntEnumElement object at 0x7f8d419e1208>, 1)

I still think that this should issue an error message and not get the program to crash.

Opening this isssue because first output line told me to.

file feature speed enhancement

Hi,
For big projects (many files to load), it is better to define all files then load then in one shot.
I think, i should be better if it is possible to enable/disable automating gadgets loading/calculation when "opening a new file" with "file" command :)

Thank you,

Ropper fails on a kernel module

TLDR: Ropper fails to work on an ELF which is also a kernel module.

dc@ubuntu:~/train/snote_pwn/snote$ ropper -f ./snote.ko 
[ERROR] Please report this error on https://github.com/sashs/ropper
[ERROR] Traceback (most recent call last):
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/console.py", line 53, in cmd
    func(self, text)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/console.py", line 492, in __handleOptions
    self.__loadGadgets()
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/console.py", line 290, in __loadGadgets
    self.__searchGadgetsFor(self.currentFileName)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/console.py", line 294, in __searchGadgetsFor
    self.__rs.loadGadgetsFor(binary)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/service.py", line 622, in loadGadgetsFor
    load_gadgets(fc)
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/service.py", line 595, in load_gadgets
    Gadget.IMAGE_BASES[f.loader.checksum] = f.loader.imageBase
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/loaders/loader.py", line 138, in imageBase
    return self._getImageBase()
  File "/home/dc/.local/lib/python2.7/site-packages/ropper/loaders/elf.py", line 44, in _getImageBase
    return self._binary.imageBase
  File "/home/dc/.local/lib/python2.7/site-packages/filebytes/elf.py", line 869, in imageBase
    return self.segments[0].header.p_vaddr - self.segments[0].header.p_offset
IndexError: list index out of range

Here is the module with changed extension, please remove the .zip:
snote.ko.zip

multiple test regressions in 1.8.0

When running the test suite (with python3) I get the following errors, which make it impossible to release the 1.8.0 version: OverflowError: cannot fit 'int' into an index-sized integer

I have created a bug report for the affected library: sashs/filebytes#2

PS: the tests were running on i686 (32bit) because of the packaging process

BND prefix not supported and therefore missing gadgets

I am using ropper 1.11.3 and noticed the following when comparing it to ROPgadget:

ropper does not seem to find gadgets / instructions that utilize the BND prefix. For instance, in libc-2.15.so, the following gadget will not be found:

0x00186042 : pop ebx ; jmp dword ptr [edx]

In fact, this gadget corresponds to these two assembly instructions:

pop    ebx
bnd jmp DWORD PTR [edx]

I guess it is due to the bnd prefix, but this has yet to be confirmed.

Imagebase ignored when called from command line

Thanks for providing this great tool.
I just observed a difference in the program's behaviour when being called from the command line rather than the console. The provided image base argument (-I <imagebase) seems to be ignored, whereas for the console it works as expected.

ropper -f ./libc-2.15.so -I 0x5555e000

Gadgets

0x0017cbd5: aad 0; add byte ptr [eax - 0xd], bh; out dx, eax; call
dword ptr [eax];
0x000b9132: aad 0; add byte ptr [eax], al; call dword ptr gs:[0x10];
0x000eca1f: aad 0; add byte ptr [eax], al; call eax;
0x000b915d: aad 0; add byte ptr [eax], al; ror eax, 9; xor eax, dword ptr gs:[0x18]; mov dword ptr [esp], edx; call eax;
0x00168b55: aad 0; add byte ptr [edx + edx8], al; out dx, al; jmp esp;
0x0017c751: aad 0; add byte ptr [esp + edx
8], bl; out dx, eax; call dword ptr [edi + 2];
0x00003696: aad 0x21; lea esi, dword ptr [edx]; wait; mov word ptr [edx - 0x4a],
dr1; sbb eax, dword ptr [0x572808a8]; call dword ptr [esi + 0x6f];
0x0006952f: aad 0x29; int 0x29; ret 0xe75;

Cache save error

While saving cache, if there is an exception thrown while making directory (

os.makedirs(temp)
), cache_file variable is undefined and is used later (
if os.path.exists(cache_file+'_%d' % i):
).

[Errno 13] Permission denied: '/home/user/.ropper'
[ERROR] Please report this error on https://github.com/sashs/ropper
[ERROR] Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/ropper/console.py", line 53, in cmd
    func(self, text)
  File "/usr/local/lib/python2.7/dist-packages/ropper/console.py", line 487, in __handleOptions
    self.__loadGadgets()
  File "/usr/local/lib/python2.7/dist-packages/ropper/console.py", line 287, in __loadGadgets
    self.__searchGadgetsFor(self.currentFileName)
  File "/usr/local/lib/python2.7/dist-packages/ropper/console.py", line 291, in __searchGadgetsFor
    self.__rs.loadGadgetsFor(binary)
  File "/usr/local/lib/python2.7/dist-packages/ropper/service.py", line 621, in loadGadgetsFor
    load_gadgets(fc)
  File "/usr/local/lib/python2.7/dist-packages/ropper/service.py", line 609, in load_gadgets
    self.__saveCache(f)
  File "/usr/local/lib/python2.7/dist-packages/ropper/service.py", line 342, in __saveCache
    if os.path.exists(cache_file+'_%d' % i):
UnboundLocalError: local variable 'cache_file' referenced before assignment

Bad bytes are ignored

I tried to generate a ropchain, but the generated chain contains bad characters.

ropper --file ~/Documents/mybinary -a x86 -b 000a2009 --chain execve=/bin/sh

I stored it to loc.py and called the script.. It seems like the -b or --badbytes argument has no effect.

parallels@ubuntu:~/Documents$ python loc.py | xxd | grep 09
0000010: bdfd 0908 660a 0c08 6e2f 7368 9a48 0708  ....f...n/sh.H..
0000020: 6410 0f08 bdfd 0908 0053 0508 9a48 0708  d........S...H..
0000030: 6810 0f08 bdfd 0908 d181 0408 6010 0f08  h...........`...
parallels@ubuntu:~/Documents$ python loc.py | xxd | grep 0a
0000000: 660a 0c08 2f2f 6269 9a48 0708 6010 0f08  f...//bi.H..`...
0000010: bdfd 0908 660a 0c08 6e2f 7368 9a48 0708  ....f...n/sh.H..
0000050: 660a 0c08 f5ff ffff 672c 0608 604f 0708  f.......g,..`O..
0000060: 0a                                       .
parallels@ubuntu:~/Documents$ python loc.py | xxd | grep 00
0000000: 660a 0c08 2f2f 6269 9a48 0708 6010 0f08  f...//bi.H..`...
0000010: bdfd 0908 660a 0c08 6e2f 7368 9a48 0708  ....f...n/sh.H..
0000020: 6410 0f08 bdfd 0908 0053 0508 9a48 0708  d........S...H..
0000030: 6810 0f08 bdfd 0908 d181 0408 6010 0f08  h...........`...
0000040: 28e1 0e08 6810 0f08 9a48 0708 6810 0f08  (...h....H..h...
0000050: 660a 0c08 f5ff ffff 672c 0608 604f 0708  f.......g,..`O..
0000060: 0a     

(still) Missing call/jmp gadgets in msvcrt71.dll

For the exploitlab we need to find a "call" gadgets in msvcrt71.dll. But even with the newest ropper, it does neither find "call" or "jmp" gadgets:

krafty@kraftyness:/opt/bins/java_6u20$ sudo pip install ropper --upgrade
Requirement already up-to-date: ropper in /usr/local/lib/python2.7/site-packages
Requirement already up-to-date: filebytes>=0.9.12 in /usr/local/lib/python2.7/site-packages (from ropper)
You are using pip version 8.1.0, however version 8.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
krafty@kraftyness:/opt/bins/java_6u20$ ropper
(ropper)> type rop
(ropper)> file msvcr71.dll
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] File loaded.
(msvcr71.dll/PE/x86)> search call
[INFO] Searching for gadgets: call

(msvcr71.dll/PE/x86)> search jmp
[INFO] Searching for gadgets: jmp

(msvcr71.dll/PE/x86)> 

Also print jump delay slot

It would be useful when getting the disassembly for the gadgets to also get the instruction at the jump delay slot (on archs that have it) since this will also affect the execution.

What I get:

....
0x00410ab8: addiu $a0, $sp, 0x18; lw $ra, 0x24($sp); lw $s0, 0x20($sp); jr $ra;
....

What I would like:

....
0x00410ab8: addiu $a0, $sp, 0x18; lw $ra, 0x24($sp); lw $s0, 0x20($sp); jr $ra; addiu $sp, $sp, 0x28;
....

--search Not working in first run

Try search two or more gadgets

  1. Drop the any caches:
rm -rf ~/.ropper ~/.cache
  1. Run ropper
% ropper --nocolor --file /bin/ls --search "xor eax, 0xa2ed; movzx eax, cl;"
[INFO] Load gadgets for section: LOAD
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: xor eax, 0xa2ed; movzx eax, cl;

No found any gadgets!

  1. Run ropper with cache:
% ropper --nocolor --file /bin/ls --search "xor eax, 0xa2ed; movzx eax, cl;" 
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: xor eax, 0xa2ed; movzx eax, cl;

[INFO] File: /bin/ls
0x0000000000010dda: xor eax, 0xa2ed; movzx eax, cl; movsxd rax, dword ptr [rsi + rax*4]; add rax, rsi; jmp rax; 

Try search one gadgets

  1. Drop the any caches:
rm -rf ~/.ropper ~/.cache
  1. Run ropper
% ropper --nocolor --file /bin/ls --search "xor eax, 0xa2ed"                
[INFO] Load gadgets for section: LOAD
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: xor eax, 0xa2ed

[INFO] File: /bin/ls
0x0000000000010dda: xor eax, 0xa2ed; movzx eax, cl; movsxd rax, dword ptr [rsi + rax*4]; add rax, rsi; jmp rax; 


Found gadget without cache!

  1. Run ropper with cache:
% ropper --nocolor --file /bin/ls --search "xor eax, 0xa2ed"                
[INFO] Load gadgets for section: LOAD
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: xor eax, 0xa2ed

[INFO] File: /bin/ls
0x0000000000010dda: xor eax, 0xa2ed; movzx eax, cl; movsxd rax, dword ptr [rsi + rax*4]; add rax, rsi; jmp rax; 

Test file /bin/ls

OSError: [Errno 12] Cannot allocate memory

when i use this commend : ropper -f vmlinux --search "iretq"

[INFO] Load gadgets for section: LOAD
[ERROR] Please report this error on https://github.com/sashs/ropper
[ERROR] Traceback (most recent call last):
File "build/bdist.linux-x86_64/egg/ropper/console.py", line 62, in cmd
func(self, text)
File "build/bdist.linux-x86_64/egg/ropper/console.py", line 501, in __handleOptions
self.__loadGadgets()
File "build/bdist.linux-x86_64/egg/ropper/console.py", line 299, in __loadGadgets
self.__searchGadgetsFor(self.currentFileName)
File "build/bdist.linux-x86_64/egg/ropper/console.py", line 303, in __searchGadgetsFor
self.__rs.loadGadgetsFor(binary)
File "build/bdist.linux-x86_64/egg/ropper/service.py", line 631, in loadGadgetsFor
load_gadgets(fc)
File "build/bdist.linux-x86_64/egg/ropper/service.py", line 616, in load_gadgets
f.allGadgets = self.__ropper.searchGadgets(f.loader, instructionCount=self.options.inst_count, gtype=gtype)
File "build/bdist.linux-x86_64/egg/ropper/rop.py", line 286, in searchGadgets
newGadgets = self._searchGadgetsForked(section=section, binary=binary, instruction_count=instructionCount, gtype=gtype)
File "build/bdist.linux-x86_64/egg/ropper/rop.py", line 370, in _searchGadgetsForked
processes[cpu].start()
File "/usr/lib/python2.7/multiprocessing/process.py", line 130, in start
self._popen = Popen(self)
File "/usr/lib/python2.7/multiprocessing/forking.py", line 121, in init
self.pid = os.fork()
OSError: [Errno 12] Cannot allocate memory

Execve ropchain uses incorrect addresses

When running --file "simple" --chain "execve" on an example binary I've been working with, the following chain is created:

#!/usr/bin/env python
# Generated by ropper ropchain generator #
from struct import pack

p = lambda x : pack('Q', x)

IMAGE_BASE_0 = 0x0000000000400000 # /home/baltazar/haccs/ta2/examples/rop/simple/old/ta2_simple_old
rebase_0 = lambda x : p(x + IMAGE_BASE_0)

rop = ''

rop += rebase_0(0x0000000000005a88) # 0x0000000000405a88: pop r13; ret; 
rop += '//bin/sh'
rop += rebase_0(0x0000000000000a37) # 0x0000000000400a37: pop rdi; ret; 
rop += rebase_0(0x00000000002cb080)
rop += rebase_0(0x000000000005cda5) # 0x000000000045cda5: mov qword ptr [rdi], r13; pop rbx; pop rbp; pop r12; pop r13; ret; 
rop += p(0xdeadbeefdeadbeef)
rop += p(0xdeadbeefdeadbeef)
rop += p(0xdeadbeefdeadbeef)
rop += p(0xdeadbeefdeadbeef)
rop += rebase_0(0x0000000000005a88) # 0x0000000000405a88: pop r13; ret; 
rop += p(0x0000000000000000)
rop += rebase_0(0x0000000000000a37) # 0x0000000000400a37: pop rdi; ret; 
rop += rebase_0(0x00000000002cc088)
rop += rebase_0(0x000000000005cda5) # 0x000000000045cda5: mov qword ptr [rdi], r13; pop rbx; pop rbp; pop r12; pop r13; ret; 
rop += p(0xdeadbeefdeadbeef)
rop += p(0xdeadbeefdeadbeef)
rop += p(0xdeadbeefdeadbeef)
rop += p(0xdeadbeefdeadbeef) 
rop += rebase_0(0x0000000000000a37) # 0x0000000000400a37: pop rdi; ret;  
rop += rebase_0(0x00000000002cc080)  # Incorrect
rop += rebase_0(0x00000000000009e4) # 0x00000000004009e4: pop rsi; ret;  
rop += rebase_0(0x00000000002cc088)
rop += rebase_0(0x0000000000043116) # 0x0000000000443116: pop rdx; ret; 
rop += rebase_0(0x00000000002cc088)
rop += rebase_0(0x000000000006ec74) # 0x000000000046ec74: pop rax; ret; 
rop += p(0x000000000000003b)
rop += rebase_0(0x0000000000067ae5) # 0x0000000000467ae5: syscall; ret; 
print rop

The line labeled "Incorrect" should be rop += rebase_0(0x00000000002cb080) so that the syscall uses the '/bin/sh' string as its filename argument.

I've submitted a pull request with a fix that passes the tests, let me know if there are any issues!

stack_pivot enhancement

Hi,
1- Don't you consider the following gadgets as stack pivot ?

  • add esp, %; ret%
  • sub esp, %; ret%
  • pop%pop%pop esp%ret%

2- shall you filter the stack pivot output, in order to remove lines with "leave; ret%" except if there is a modification to ebp ?

3- is it possible to add a context before generating stack pivot ? we can, for example, set registers, some memory values, distance between esp and out controlled stack buffer, ... This will allow filtering some invalid instructions like mov esp, [eax] when eax = 0x00.

4- loock backward (will fill an other issue ticket ;-)) will allow checking previous instructions. This would be helpful for analyzing "xchg eax, esp; ret;" like gadgets :)

Thank you,

Getting '[ERROR] list index out of range' when trying to load file

Running Ropper on Windows, with capstone-windows 3.0.4, then entering the command file C:\Users\MyUser\test.exe results in the output:

[INFO] Load gadgets from cache
[LOAD] loading... 0%[ERROR] list index out of range

Then entering the command search "% ?di" results in the output:
[INFO] Searching for gadgets: "% ?di"
[ERROR] object of type 'NoneType' has no len()
[ERROR] Please report this error on https://github.com/sashs/ropper

Additionally, running the command ropper.py --file C:\Users\MyUser\test.exe -- search "% ?di" results in a continuous loop of this error:
[INFO] Load gadgets from cache
[LOAD] loading... 0%[ERROR] list index out of range
[ERROR] Please report this error on https://github.com/sashs/ropper

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\MyUser\Python\lib\multiprocessing\forking.py", line 347, in main
    self = load(from_parent)
  File "C:\Users\MyUser\Python\lib\pickle.py", line 1378, in load
    return Unpickler(file).load()
  File "C:\Users\MyUser\Python\lib\pickle.py", line 858, in load
    dispatch[key](self)
  File "C:\Users\MyUser\Python\lib\pickle.py", line 880, in load_eof
    raise EOFError
EOFError

chain genration

[ERROR] Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/ropper/console.py", line 53, in cmd
func(self, text)
File "/usr/local/lib/python3.5/dist-packages/ropper/console.py", line 479, in __handleOptions
self.__generateChain(options.chain)
File "/usr/local/lib/python3.5/dist-packages/ropper/console.py", line 363, in __generateChain
raise e
File "/usr/local/lib/python3.5/dist-packages/ropper/console.py", line 348, in __generateChain
chain = self.__rs.createRopChain(generator, str(self.currentFile.arch) ,options)
File "/usr/local/lib/python3.5/dist-packages/ropper/service.py", line 756, in createRopChain
return generator.create(options)
File "/usr/local/lib/python3.5/dist-packages/ropper/ropchain/arch/ropchainx86_64.py", line 693, in create
chain += self._printRebase()
File "/usr/local/lib/python3.5/dist-packages/ropper/ropchain/arch/ropchainx86_64.py", line 55, in _printRebase
imageBase = Gadget.IMAGE_BASES[binary]
KeyError

project notion (create, save, restore)

Hi,
Is it possible to have a project notion in ropper ?
This will allow to open multiple files, generate gadgets then save the project to later usage without generating again all the stuff.
Thank you :)

Typo error in Usage section

  Example:

  ropper.py --file /bin/ls --search "mov [%], ecx"
  0x000067ed: mov dword ptr [esp + 4], edx; mov edx, dword ptr [ebp + 0x14]; mov dword ptr [esp], edx; call eax;
  0x00006f4e: mov dword ptr [ecx + 0x14], edx; add esp, 0x2c; pop ebx; pop esi; pop edi; pop ebp; ret ;
  0x000084b8: mov dword ptr [eax], edx; ret ;
  0x00008d9b: mov dword ptr [eax], edx; add esp, 0x18; pop ebx; ret ;

It should be

ropper.py --file /bin/ls --search "mov [%], edx"

:D

ppr enhancement

Hi,
You should maybe include gadgets like:

  • call [ebp+0c]
  • add esp, 0x8; ret
  • add esp, 0x4; pop ???; ret;
  • ...

Thank you,

Look|disass backward

Hi,
Is it possible to implement a search or a global option that allows printing the N previous instructions of printed gadgets?
This will help rapid analysis of stack_pivot and search results.

Thank you

add option for ptr in execve

I'm using ropper and it's a really useful tool, but most of the time when trying to generate the execve chain it fail on finding write-what-where gadget. I've looked at the code and it seems that it only needs it for writing binary path to memory. Most of the time when it ropper fails I can load a string to known memory location or in the case of "/bin/sh" it's sometime just found as data in the binary.

I suggest adding a --chain "execve cmd_addr=0xdeadbabe" to ropper.
What do you think?

context based calculations

Hi,
It's maybe better to create a new issue/ticket for the context :)
As explained in #33 , it should significantly increase the relevance of the results if we can define the context of execution. The context can be:

  • cpu context (registers)
  • stack dump + stack base adress

This will allow skipping the generation of gadgets that:

  • dereference null pointers (eax = 0x00 and mov esp, [eax])
  • dereference pointers outside of adressable memory (mov eax, [esp-0x8f123456])
  • ...

It would be great also if we can provide the "crash pattern", this will allow the calculation of the stack pivot offset then print more accurate gadgets for that...

It could even go far from that by performing an automatic check of each gadget to verify if it will reach the desired esp/ebp values ;)

Have fun :)

Getting print format error on rop chain generation

Running:
ropper --file which nc --chain execve

ends with:
...
[*] Try permuation 23 / 24

[*] Try permuation 24 / 24

[INFO]

[INFO] Cannot create chain which fills all registers

[INFO]

[INFO] Look for syscall gadget

[INFO] No syscall gadget found!

[INFO] Look for syscall opcode
[ERROR] %x format: a number is required, not str
[ERROR] Please report this error on https://github.com/sashs/ropper

So I'm reporting it ;)

search feature enfancement

Hi,
Is it possible to allow some extended regexp search in the "search" feature?
This, in order to exclude a certain pattern (eg. add esp, 0x1234; leave; ret; without ebp modification, which is just useless when looking for a stack pivot).
It will also allow defining range for values, like searching for values between 0x3 and 0x123 could be : search mov eax, 0x[3-123] or similar/better expression :-)

Thank you

Data section's address is not calculated properly

I have an executable, on which i generated an execve rop chain using ropper, but it caused a segfault.
I debugged that segfault for a bit, and got to the conclusion ropper tried to write "/bin/sh" to a place
it thought was the data section, but really isn't. I think the faulty line is line 626 in ropchainx86_64.py:

chain_tmp += self._createCommand(cmd,section.offset+0x1000)[0]

section.offset is used, and according to my understanding, this is the section's sh_offset member. but upon
some docs, it apears this field is an offset from the beginning of the file, and not an rva in memory!
i confirmed this using:
readelf -S pass_protected
which returned:
[Nr] Name Type Address Offset
....
[24] .data PROGBITS 00000000006c1060 000c1060

and the image base is actually 0x400000 (compiled without PIE), not 0x600000 (confirms that
the offset is not really the rva).
The segfault message from dmesg said that the segfault occured while trying to write to 0x4c2060,
which explains that perfectly (that is the section's offset + 0x1000, as calculated by ropper), while the
data section really begins at 0x6c1060.
Added the file whose data section address is not calculated properly.
pass_protected.zip

Add --offset option to specify an arbitrary offset to the base address

Hi @sashs,

First kudos for the tool, I'm a super big fan (the search command saves me too much time ๐Ÿ˜„ ). One of the features I used in one of my tool was the --offset option I PR-ed to ROPgadget which allows to specify an offset to the gadget offset, like this:

ROPgadget.py --binary ./test-suite-binaries/Linux_lib64.so --offset 0xdeadbeef00000000

I couldn't find such option in ropper but maybe I missed it out. Does it exist (in master/dev)? Would you be ok to add this option? I can probably PR it if you don't have time.

Keep up the good work!

Cheers,

missing call esp gadget on Mac OS X

Hi,

I tried to search "call esp" gadget. It was not found.
On the other hand, I used "ropchain virtualprotect" command then "call esp" gadget found in the gadgets.

(a.exe/PE/x86)> search call esp;
[INFO] Searching for gadgets: call esp;

(a.exe/PE/x86)> ropchain virtualprotect address=0x0056D39Ca

...(skipped)
p = lambda x : pack('I', x)
shellcode = '\xcc'*100
IMAGE_BASE_0 = 0x00400000 # 9f59a606c57217d98a5eea6846c8113aca07b203e0dcf17877b34a8b2308ade6.exe
rebase_0 = lambda x : p(x + IMAGE_BASE_0)

rop = ''
...(skipped)
rop += rebase_0(0x00001bd2) # 0x00401bd2: pop ebp; ret;
rop += rebase_0(0x00023090) # <= VA 0x423090 is "call esp" (I checked it on IDA Pro)
...(skipped)

So the gadget is missing in just search command. Is that bug?
I use version 1.11.2 on Mac OS X. I installed it from pip.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.