GithubHelp home page GithubHelp logo

boyan-milanov / ropium Goto Github PK

View Code? Open in Web Editor NEW
350.0 13.0 47.0 11.74 MB

ROPium is a tool that helps you building ROP exploits by finding and chaining gadgets together

Python 1.94% C++ 96.46% Dockerfile 0.12% Makefile 0.43% C 1.04%
gadget rop-chain rop-gadgets semantic chaining-gadgets rop-exploits exploit-development binary-exploitation security security-vulnerability

ropium's Introduction




About

ROPium (ex-ROPGenerator) is a library/tool that makes ROP-exploits easy. It automatically extracts and analyses gadgets from binaries and lets you find ROP-chains with semantic queries. ROPium supports X86 and X64 architectures, soon to be extended with ARM.

Key features:

  • Effortless: ROPium works out-of-the-box with a smooth Command Line Interface
  • Python API: It is easy to integrate ROPium in script thanks to its python API
  • Automatic chaining: ROPium automatically combines gadgets to create complex ROP-chains
  • Advanced features: ROPium supports function calls for various ABIs, syscalls, ...
  • Semantic queries: ROPium queries are quick and convenient to write : rax=rbx+8, [rdi+0x20]=rax, rsi=[rbx+16], 0x08040212(1, 2, rax), [0xdeadbeaf] = "/bin/sh\x00", sys_execve(0xdeadbeef, 0, 0), sys_0x1(0), ...

Content

Installation

First install the Capstone disassembly framework:

  sudo apt-get install libcapstone-dev

You also need the latest ROPgadget release:

  git clone https://github.com/JonathanSalwan/ROPgadget && cd ROPgadget
  python setup.py install --user 

To use the CLI tool, install prompt_toolkit:

  pip3 install prompt_toolkit

Finally install ROPium:

  git clone https://github.com/Boyan-MILANOV/ropium && cd ropium
  make
  make test
  sudo make install 

Getting started

CLI tool

Thanks to a Command-Line-Interface wrapper, you can use ROPium interactively to quickly build ropchains:

Python API

Do you need to integrate ropchains directly in your scripts ? Good news, ROPium has a python API !

Loading a binary and finding ropchains:

from ropium import *
rop = ROPium(ARCH.X64)
rop.load('/lib/x86_64-linux-gnu/libc-2.27.so')

chain = rop.compile('rbx = [rax + 0x20]')

Dumping a ropchain in various formats:

>>> print( chain.dump() )

0x000000000009a851 (sub rax, 0x10; ret)
0x0000000000130018 (mov rax, qword ptr [rax + 0x30]; ret)
0x0000000000052240 (push rax; pop rbx; ret)

>>> print(chain.dump('python'))

from struct import pack
off = 0x0
p = ''
p += pack('<Q', 0x000000000009a851+off) # sub rax, 0x10; ret
p += pack('<Q', 0x0000000000130018+off) # mov rax, qword ptr [rax + 0x30]; ret
p += pack('<Q', 0x0000000000052240+off) # push rax; pop rbx; ret

>>> print(chain.dump('raw'))

b'Q\xa8\t\x00\x00\x00\x00\x00\x18\x00\x13\x00\x00\x00\x00\x00@"\x05\x00\x00\x00\x00\x00'

Set constraints on ropchains:

# Bytes that should not appear in the ropchain
rop.bad_bytes = [0x00, 0x0a, 0x0b]

# Register that should not be clobbered by the ropchain
rop.keep_regs = ['rsi', 'rdx']

# Enable/Forbid ropchain to dereference registers that might hold invalid addresses
# Safe mode is 'True' by default
rop.safe_mem = False

# Specify which ABI you want to use when calling functions
rop.abi = ABI.X86_CDECL

# Specify which system to target when doing syscalls
rop.os = OS.LINUX

Docker

If needed you can run ROPium in a docker container. The container can be generated from the Dockerfile as follows:

# Create your docker image (this will take time!)
docker build . --tag ropium

# Run the image in interactive mode, bind mounting the file to analyze
docker run --rm -it -v /FULL/HOST/PATH/FILE:/tmp/FILE:ro ropium

(ropium)> load -a X86 /tmp/FILE

The actual image is around 200 MB based on a Debian Stretch with a Python 3.7.3 installed.

Contact

Boyan MILANOV - boyan.milanov (at) hotmail (dot) fr

Licence

ROPium is provided under the MIT licence.

Special thanks

Contributors:

ROPium uses the following awesome projects:

ropium's People

Contributors

bet4it avatar boyan-milanov avatar clslgrnc avatar kyle-kyle avatar migounette avatar mu00d8 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

ropium's Issues

it doesn't work on ubuntu16.04

I install it and its dependencies.But when I load a binary,it will report an error.ROPgadget4ROPGenerator doesn't have --dump.

Concurrency

It looks like there is a concurrency problem. When I run several instances of ropium at the same time then results are unstable.

The reason at least is that ROPgadget output captured at the same file.

string gadget_file = string(".raw_gadgets.ropium");

Invalid memory address dereference in find()

An issue was discovered in ROPium 3.1. An invalid memory address dereference was discovered in find(). The vulnerability causes a segmentation fault and application crash.

POC

aidai@ubuntu:~/Desktop$ ropium

ROPium - v3.1

(ropium)> find                                                                  

	[!] You must load a binary before finding ropchains

(ropium)> load -a X64 aidai                                                     

	[!] Skipped: aidai (file doesn't exist)

(ropium)> find                                                                  
Segmentation fault (core dumped)
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────[ REGISTERS ]──────────────────────────────────
 RAX  0x7
 RBX  0x1e26bf0 —▸ 0x1e105b0 —▸ 0x7f58fe11a900 —▸ 0x7f58fde45b90 ◂— mov    rax, qword ptr [rip + 0x2d50f9]
 RCX  0x0
 RDX  0x9
 RDI  0x1e26bf0 —▸ 0x1e105b0 —▸ 0x7f58fe11a900 —▸ 0x7f58fde45b90 ◂— mov    rax, qword ptr [rip + 0x2d50f9]
 RSI  0x0
 R8   0x2
 R9   0x0
 R10  0x100
 R11  0x7ffdeddde370 —▸ 0x7ffdeddde380 —▸ 0x1ecbee0 ◂— add    byte ptr [rax], al
 R12  0x1c509e0 ◂— add    byte ptr [rax], al
 R13  0x7ffdeddde640 ◂— 0x0
 R14  0x9
 R15  0x1c50a10 ◂— add    dword ptr [rax], eax
 RBP  0x1c509e0 ◂— add    byte ptr [rax], al
 RSP  0x7ffdeddde608 —▸ 0x7f58fdec0145 ◂— test   al, al
 RIP  0x7f58fdeb5c40 ◂— mov    ecx, dword ptr [rsi]
───────────────────────────────────[ DISASM ]───────────────────────────────────
 ► 0x7f58fdeb5c40    mov    ecx, dword ptr [rsi]
   0x7f58fdeb5c42    mov    eax, 1
   0x7f58fdeb5c47    cmp    ecx, 0x13
   0x7f58fdeb5c4a    je     0x7f58fdeb5c53
    ↓
   0x7f58fdeb5c53    ret    
 
   0x7f58fdeb5c55    nop    dword ptr [rax]
   0x7f58fdeb5c58    sub    edx, 7
   0x7f58fdeb5c5b    cmp    edx, 1
   0x7f58fdeb5c5e    setbe  al
   0x7f58fdeb5c61    ret    
 
   0x7f58fdeb5c62    nop    dword ptr [rax]
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp  0x7ffdeddde608 —▸ 0x7f58fdec0145 ◂— test   al, al
01:0008│      0x7ffdeddde610 —▸ 0x7f58fa641950 ◂— or     dword ptr [rax], eax /* '\t' */
02:0010│      0x7ffdeddde618 ◂— 0x2fa629d68
03:0018│      0x7ffdeddde620 ◂— 0x0
... ↓
06:0030│      0x7ffdeddde638 ◂— 0x56056b
07:0038│ r13  0x7ffdeddde640 ◂— 0x0
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
 ► f 0     7f58fdeb5c40
   f 1     7f58fdec0145
   f 2     7f58fa641950
   f 3        2fa629d68
   f 4                0
────────────────────────────────────────────────────────────────────────────────

Status check

In the README it says ARM is coming soon - what's the status on this?

Some constants need rebase

I'm using the latest ubuntu 18.04 and ROPGenerator.
When I try the cmd syscall in exploit mode, some of the constants need rebase because the generated payload uses it as the address to be written.
See the screenshot.
image
P.S. When I exit the ROPGenerator, my personal preference is to press Ctrl+D. But in that way, Python will throw an annoying EOFError. If you can fix that I'll be very grateful.
Anyway, thanks for the great tool.

Build issue: Invalid use of incomplete type

I'm getting an error when trying to build (see below). This same error (invalid use of incomplete type) is repeated across many files. Any idea?

┌──(kali㉿kali)-[~/ropium]
└─$ make 
g++ -O2 -Wno-narrowing `python3-config --cflags` -DPYTHON_BINDINGS -Ibindings/python -std=c++11 -fpermissive -fPIC -I ./libropium/include -I ./libropium/dependencies/murmur3 -Wno-write-strings -Wno-sign-compare -Wno-reorder  -c libropium/database/database.cpp -o libropium/database/database.o -lcapstone `python3-config --libs`
In file included from libropium/database/database.cpp:1:

./libropium/include/database.hpp: In instantiation of ‘bool BaseDB<K>::_check_key_match(const K&, const K&, bool*, int) [with K = std::tuple<short unsigned int, short unsigned int>]’:
./libropium/include/database.hpp:109:39:   required from ‘PossibleGadgets* BaseDB<K>::get_possible(K, bool*, int) [with K = std::tuple<short unsigned int, short unsigned int>]’
libropium/database/database.cpp:316:32:   required from here
./libropium/include/database.hpp:95:33: error: invalid use of incomplete type ‘struct std::array<long int, 2>’
   95 |         auto a1 = tuple_to_array(key1);
      |                   ~~~~~~~~~~~~~~^~~~~~
In file included from ./libropium/include/database.hpp:5:
/usr/include/c++/12/tuple:1595:45: note: declaration of ‘struct std::array<long int, 2>’
 1595 |   template<typename _Tp, size_t _Nm> struct array;
      |                                             ^~~~~
./libropium/include/database.hpp:96:33: error: invalid use of incomplete type ‘struct std::array<long int, 2>’
   96 |         auto a2 = tuple_to_array(key2);
      |                   ~~~~~~~~~~~~~~^~~~~~
/usr/include/c++/12/tuple:1595:45: note: declaration of ‘struct std::array<long int, 2>’
 1595 |   template<typename _Tp, size_t _Nm> struct array;
      |                                             ^~~~~
In file included from ./libropium/include/database.hpp:7:
./libropium/include/utils.hpp: In instantiation of ‘std::vector<long int> tuple_to_vector(Tuple&&) [with Tuple = const std::tuple<short unsigned int, short unsigned int>&]’:
./libropium/include/database.hpp:110:52:   required from ‘PossibleGadgets* BaseDB<K>::get_possible(K, bool*, int) [with K = std::tuple<short unsigned int, short unsigned int>]’
libropium/database/database.cpp:316:32:   required from here
./libropium/include/utils.hpp:127:32: error: invalid use of incomplete type ‘struct std::array<long int, 2>’
  127 |     auto array = tuple_to_array(tuple);
      |                  ~~~~~~~~~~~~~~^~~~~~~
/usr/include/c++/12/tuple:1595:45: note: declaration of ‘struct std::array<long int, 2>’
 1595 |   template<typename _Tp, size_t _Nm> struct array;
      |                                             ^~~~~
./libropium/include/database.hpp: In instantiation of ‘bool BaseDB<K>::_check_key_match(const K&, const K&, bool*, int) [with K = std::tuple<short unsigned int, short unsigned int, int, short unsigned int>]’:
./libropium/include/database.hpp:109:39:   required from ‘PossibleGadgets* BaseDB<K>::get_possible(K, bool*, int) [with K = std::tuple<short unsigned int, short unsigned int, int, short unsigned int>]’
libropium/database/database.cpp:320:33:   required from here
./libropium/include/database.hpp:95:33: error: invalid use of incomplete type ‘struct std::array<long int, 4>’
   95 |         auto a1 = tuple_to_array(key1);
      |                   ~~~~~~~~~~~~~~^~~~~~
/usr/include/c++/12/tuple:1595:45: note: declaration of ‘struct std::array<long int, 4>’
 1595 |   template<typename _Tp, size_t _Nm> struct array;
      |                                             ^~~~~
./libropium/include/database.hpp:96:33: error: invalid use of incomplete type ‘struct std::array<long int, 4>’
   96 |         auto a2 = tuple_to_array(key2);
      |                   ~~~~~~~~~~~~~~^~~~~~
/usr/include/c++/12/tuple:1595:45: note: declaration of ‘struct std::array<long int, 4>’
 1595 |   template<typename _Tp, size_t _Nm> struct array;
      |                                             ^~~~~
./libropium/include/utils.hpp: In instantiation of ‘std::vector<long int> tuple_to_vector(Tuple&&) [with Tuple = const std::tuple<short unsigned int, short unsigned int, int, short unsigned int>&]’:
./libropium/include/database.hpp:110:52:   required from ‘PossibleGadgets* BaseDB<K>::get_possible(K, bool*, int) [with K = std::tuple<short unsigned int, short unsigned int, int, short unsigned int>]’
libropium/database/database.cpp:320:33:   required from here
./libropium/include/utils.hpp:127:32: error: invalid use of incomplete type ‘struct std::array<long int, 4>’
  127 |     auto array = tuple_to_array(tuple);
      |                  ~~~~~~~~~~~~~~^~~~~~~
/usr/include/c++/12/tuple:1595:45: note: declaration of ‘struct std::array<long int, 4>’
 1595 |   template<typename _Tp, size_t _Nm> struct array;
      |                                             ^~~~~
./libropium/include/database.hpp: In instantiation of ‘bool BaseDB<K>::_check_key_match(const K&, const K&, bool*, int) [with K = std::tuple<short unsigned int, long int>]’:
./libropium/include/database.hpp:109:39:   required from ‘PossibleGadgets* BaseDB<K>::get_possible(K, bool*, int) [with K = std::tuple<short unsigned int, long int>]’
libropium/database/database.cpp:324:32:   required from here
./libropium/include/database.hpp:95:33: error: invalid use of incomplete type ‘struct std::array<long int, 2>’
   95 |         auto a1 = tuple_to_array(key1);
      |                   ~~~~~~~~~~~~~~^~~~~~
/usr/include/c++/12/tuple:1595:45: note: declaration of ‘struct std::array<long int, 2>’
 1595 |   template<typename _Tp, size_t _Nm> struct array;
      |                                             ^~~~~
...
make: *** [Makefile:83: libropium/database/database.o] Error 1

Crash when generate shellcode (memcpy missing in PLT)

Hi,

There is a crash when I try to generate a shellcode. I think this is due to the fact the the tested binary doesn't have the memcpy in its PLT table.

$ sudo ROPGenerator
[sudo] password for fraf:

▒▒▒▒▒▒▒╗░▒▒▒▒▒▒╗░▒▒▒▒▒▒  ═════════════════════════
▒▒╔══▒▒║▒▒╔═══▒▒╗▒▒╔══▒╗
▒▒▒▒▒▒╔╝▒▒║   ▒▒║▒▒▒▒▒▒║ G  E  N  E  R  A  T  O  R
▒▒╔══▒▒╗╚▒▒▒▒▒▒╔╝▒▒╔═══╝
╚═╝  ╚═╝ ╚═════╝ ╚═╝     ════════════════════ v1.2



(main)> load my_binary

[+] Extracting gadgets from file 'my_binary'
  % ELF 32-bits detected
  % Executing ROPgadget as: ROPgadget
  % Finished : 140 gadgets generated
[+] Creating gadget database
        % Gadgets analyzed : 140
  % Successfully translated : 115
  % Computation time : 0:00:00.495802
[+] Initializing Semantic Engine
        % Optimization rate : 92%
  % Computation time : 0:00:00.390653

(main)> exploit
(exploit)> pwn --help

  ________________________

  'pwn' command
  (Generate full exploits)
  ________________________


  Usage:
    pwn [OPTIONS] <subcommand> [SUBCOMMAND_OPTIONS]

  Subcommands:
  (For more info use 'pwn <subcommand> -h')

    deliver-shellcode  Inject a shellcode an execute it

  Options:

    -b,--bad-bytes <bytes>   Bad bytes for payload.
           Expected format is a list of bytes
           separated by comas (e.g '-b 0A,0B,2F')

    -m,--max-length <int>  Max length of the ROPChain in bytes

    -pb,--padding-byte <byte> Byte for payload padding

    -pl,--padding-len <int>  Length of payload padding

    -off,--offset <int>  Offset to add to gadget addresses

    -f,--output-format <fmt> Output format for ropchains.
           Expected format is one of the
           following: console,python

    -o,--output-file <file>  Save payload in a file

    -h,--help    Show this help

  Examples:
    No examples yet

(exploit)> shellcode -l X86

  _________________________________

  Available shellcodes for arch X86
  _________________________________


  (1) Linux x86 exec /bin/sh (ragg2)
  '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\...' - 24 bytes

(exploit)> pwn --bad-bytes 0a --padding-len 128 --output-format python deliver-shellcode --address 0xffffd040

  _________________________________

  Available shellcodes for arch X86
  _________________________________


  (1) Linux x86 exec /bin/sh (ragg2)
  '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\...' - 24 bytes

  > Select a shellcode:
        > 1

[+] Building exploit: deliver-shellcode strategy

  % Building chain to copy shellcode in memory
  ERROR DEBUG The file has no .rela.plt section
Traceback (most recent call last):
  File "/usr/local/bin/ROPGenerator", line 4, in <module>
    __import__('pkg_resources').run_script('ropgenerator==1.1', 'ROPGenerator')
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 661, in run_script
    self.require(requires)[0].run_script(script_name, ns)
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 1441, in run_script
    exec(code, namespace, namespace)
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/EGG-INFO/scripts/ROPGenerator", line 5, in <module>
    Main.main()
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Main.py", line 77, in main
    if( not exploit_mode()):
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/exploit/Main.py", line 58, in exploit_mode
    pwn(args[1:])
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/exploit/Pwn.py", line 267, in pwn
    payload = dshell(args[i+1:], constraint, assertion, lmax=clmax)
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/exploit/pwn/DeliverShellcode.py", line 146, in dshell
    res = build_dshell(shellcode, constraint, assertion, address, limit, lmax)
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/exploit/pwn/DeliverShellcode.py", line 178, in build_dshell
    (shellcode_address, STRtoMEM_chain) = STRtoMEM(shellcode, address, constraint, assertion, limit=limit, lmax=lmax, addr_str=addr_str, hex_info=True, optimizeLen=optimizeLen)
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/exploit/HighLevelUtils.py", line 42, in STRtoMEM
    (addr,chain) = STRtoMEM_memcpy(string, address, constraint, assertion, limit, lmax, addr_str, hex_info)
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/exploit/HighLevelUtils.py", line 141, in STRtoMEM_memcpy
    (func_name, func_addr ) = getFunctionAddress('memcpy')
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/exploit/Scanner.py", line 95, in getFunctionAddress
    relasec_addr = relasec.header['sh_addr']
AttributeError: 'NoneType' object has no attribute 'header'

$

Regards,

Ouccr an error while starting

Traceback (most recent call last):
File "/usr/local/bin/ROPGenerator", line 4, in
import('pkg_resources').run_script('ropgenerator==1.2', 'ROPGenerator')
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/init.py", line 739, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/local/lib/python2.7/dist-packages/pkg_resources/init.py", line 1494, in run_script
exec(code, namespace, namespace)
File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.2-py2.7.egg/EGG-INFO/scripts/ROPGenerator", line 3, in
import ropgenerator.Main as Main
File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.2-py2.7.egg/ropgenerator/Main.py", line 9, in
from ropgenerator.Load import load
File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.2-py2.7.egg/ropgenerator/Load.py", line 9, in
from ropgenerator.exploit.Scanner import initScanner
File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.2-py2.7.egg/ropgenerator/exploit/Scanner.py", line 5, in
from ropgenerator.exploit.ZwoELF import ElfParser
ImportError: No module named ZwoELF

std::out_of_range is thrown when loading specific 64-bit executables

Hello,

Loading an x64 executable with a base address that doesn't fit in 32 bits will make the code throw an std::out_of_range exception during the call to std::stoi in raw_gadgets_from_file, particularly in the following line:

raw.addr = std::stoi(addr_str, 0, 16);

This happens because std::stoi does not support converting integers that are larger than 32 bits. When parsing executables mentioned above, the gadget addresses won't fit into 32 bits and will cause the exception to be thrown.

I have fixed the issue locally by replacing the std::stoi call with std::stoll or std::stoull. Given that the destination operand is a uint64_t type, I believe using std::stoull would be more correct.

-                    raw.addr = std::stoi(addr_str, 0, 16);
+                    raw.addr = std::stoull(addr_str, 0, 16);

Attached is an excerpt from the .ropium_raw_gadgets.0 temporary file that's generated by ropium during gadget processing. To reproduce the issue, one can make a test with the following line:

raw_gadgets_from_file("ropium_raw_gadgets.txt");

ropium_raw_gadgets.txt

consider releasing 3.3

Hi there,

I seems there have only been 5 commits since 3.2, but there are 3 bug fixes that seem interesting.
As the commit traffic on this repo is quite low, i thought it may be worth bumping to 3.3 and tagging another git tag 🐱
cheers

Segmentation Fault

I run command to build in README.rd and then run ROPgenerator, I get SIGSEGV error.
So I run

$ strace ROPGenerator 
...strip...
...strip...

▒▒▒▒▒▒╗░▒▒▒▒▒▒╗░▒▒▒▒▒▒  ═════════════════════════       
▒▒╔══▒▒║▒▒╔═══▒▒╗▒▒╔══▒╗
▒▒▒▒▒▒╔╝▒▒║   ▒▒║▒▒▒▒▒▒║ G  E  N  E  R  A  T  O  R
▒▒╔══▒▒╗╚▒▒▒▒▒▒╔╝▒▒╔═══╝ 
╚═╝  ╚═╝ ╚═════╝ ╚═╝     ════════════════════ v2.0          

) = 546
write(1, "\n", 1
)                       = 1
openat(AT_FDCWD, "/home/cothan/.ROPGenerator/.ROPGenerator.log", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 7
write(7, "ROPGenerator - Logs\n\n", 21) = 21
close(7)                                = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x1} ---
futex(0x7f35458bdf80, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f35440351a0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x1} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)


Step to reproduce

sudo apt install python3-dev
sudo apt install cmake
apt-get install python3-pytest 
apt-get install python3-pybind11

  git clone https://github.com/programa-stic/barf-project && cd barf-project
  python3 setup.py install --user

 pip install capstone
  git clone https://github.com/JonathanSalwan/ROPgadget && cd ROPgadget
  python setup.py install --user 

git clone https://github.com/Boyan-MILANOV/ropgenerator && cd ropgenerator
  python3 setup.py install --user
  ROPGenerator 

Any recommendation to fix the problem, can you make a prebuilt binary instead?

Adding support for return 2 csu

Support for return2csu

I think this is fairly simple, we need ROPgadget to search for ROP chain in sym.__libc_csu_init and sym.__libc_csu_fini section, so that the ROP chain will be taken into account.

element "LDM" already exists

Traceback (most recent call last):
  File "/home/kylebot/.virtualenvs/ropgenerator/bin/ROPGenerator", line 7, in <module>
    exec(compile(f.read(), __file__, 'exec'))
  File "/home/kylebot/src/ropgenerator/ROPGenerator", line 3, in <module>
    import ropgenerator.main.Main as Main
  File "/home/kylebot/src/ropgenerator/ropgenerator/main/Main.py", line 6, in <module>
    from ropgenerator.main.Load import load, loaded_binary
  File "/home/kylebot/src/ropgenerator/ropgenerator/main/Load.py", line 19, in <module>
    from ropgenerator.main.Scanner import init_scanner, find_opcode
  File "/home/kylebot/src/ropgenerator/ropgenerator/main/Scanner.py", line 7, in <module>
    from ropgenerator.core.Architecture import *
  File "/home/kylebot/src/ropgenerator/ropgenerator/core/Architecture.py", line 1, in <module>
    from ropgenerator_core_ import\
ImportError: IROperation: element "LDM" already exists!

ModuleNotFoundError

when I type "ropium" in the terminal, an error occur: from ropium import * No module named "ropium"

[QoL] Add way to specify ROPgagdet parameters

Hi Boyan !

It'd be nice to be able to specify some ROPGadget arguments when using the "load" command.

For example, using a small 'depth' parameter can be useful when working on "big" binaries (looking at you, vmlinux...)

Cheers,
Blyska

Crash: PY_SSIZE_T_CLEAN macro must be defined for '#' formats

There seems to be a breaking change in python 3.10 (see https://docs.python.org/3.10/whatsnew/3.10.html#id2 ) where PY_SSIZE_T_CLEAN needs to be defined. See error below I receive when attempting to run ropium,

(ropium)> load -a X86 myfile.dll

Traceback (most recent call last):
  File "/usr/bin/ropium", line 524, in <module>
    main()
  File "/usr/bin/ropium", line 84, in main
    load(args[1:])
  File "/usr/bin/ropium", line 205, in load
    compiler.load(f)
SystemError: PY_SSIZE_T_CLEAN macro must be defined for '#' formats

TypeError @Conditions.py:344

Hi Boyan,

First of all, thanks for the tool, keep up the good work ;)

Python throws a TypeError when trying to load a kernel executable.
Arch: x86, 32bits

Temporarily fixed the issue by adding a pair of None-checks @Condition.py:394.
Not sure if it's semantically reliable in any way though.

Cheers,
Blyska


"Crashdump"

Logged from file x86translator.py, line 243
% |████████████ | 042%Traceback (most recent call last):
[...]
File "[...]/scripts/ROPGenerator", line 5, in
   Main.main()
File "[...]/Main.py", line 66, in main
   load(args[1:])
File "[...]/Load.py", line 193, in load
   build(gadgetList)
File "[...]/Database.py", line 553, in build
   gadget = Gadget([addr], raw)
File "[...]/Gadget.py", line 75, in init
   self.semantics = self.graph.getSemantics()
File "[...]/Graph.py", line 128, in getSemantics
   semantics.simplifyConditions()
File "[...]/Semantics.py", line 239, in simplifyConditions
   if( p.cond.isTrue()):
File "[...]/Conditions.py", line 460, in isTrue
    res = self.customSimplify()
File "[...]/Conditions.py", line 398, in customSimplify
   res = simplifyArrayEquality( leftArray, rightArray, self.cond)
File "[...]/Conditions.py", line 344, in simplifyArrayEquality
   for i in range(0,len(a1)):
TypeError: object of type 'NoneType' has no len()

rdx was overwriten in example gif

I think example GIF does a very good impression of the tool.
However, in the discussion with my friends, we spot an error in the GIF, probably in the tool too, is the command

find [rdx+32]=rax, where rdx was overwritten, which lead to unexpected location.

Line 1, line 4 should be something else rather than rdx.

image

I also tried to reproduce this in libc.so.2.27 but the tool hang forever at similar find query.

My ROPium version is v3.1

AttributeError: Cond instance has no attribute 'replaceMemAcc'

I'm facing below error when load vmlinux, any idea?

File "/home/jiangenj/.local/bin/ROPGenerator", line 4, in
import('pkg_resources').run_script('ropgenerator==1.1', 'ROPGenerator')
File "/home/jiangenj/.local/lib/python2.7/site-packages/pkg_resources/init.py", line 664, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/home/jiangenj/.local/lib/python2.7/site-packages/pkg_resources/init.py", line 1444, in run_script
exec(code, namespace, namespace)
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/EGG-INFO/scripts/ROPGenerator", line 5, in
Main.main()
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Main.py", line 66, in main
load(args[1:])
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Load.py", line 193, in load
build(gadgetList)
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Database.py", line 565, in build
gadget = Gadget([addr], raw)
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Gadget.py", line 75, in init
self.semantics = self.graph.getSemantics()
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Graph.py", line 122, in getSemantics
node.getSemantics( semantics, self )
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Graph.py", line 255, in getSemantics
res += [SPair(p.expr.replaceMemAcc(a.label, pair.expr), Cond(CT.AND, p.cond,pair.cond)) for p in resPrec ]
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 855, in replaceMemAcc
return Convert( self.size, self.args[0].replaceMemAcc( addr, expr ), self.signed)
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 490, in replaceMemAcc
newArgs = [arg.replaceMemAcc( addr, expr ) for arg in self.args]
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 855, in replaceMemAcc
return Convert( self.size, self.args[0].replaceMemAcc( addr, expr ), self.signed)
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 490, in replaceMemAcc
newArgs = [arg.replaceMemAcc( addr, expr ) for arg in self.args]
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 490, in replaceMemAcc
newArgs = [arg.replaceMemAcc( addr, expr ) for arg in self.args]
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 855, in replaceMemAcc
return Convert( self.size, self.args[0].replaceMemAcc( addr, expr ), self.signed)
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 855, in replaceMemAcc
return Convert( self.size, self.args[0].replaceMemAcc( addr, expr ), self.signed)
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 855, in replaceMemAcc
return Convert( self.size, self.args[0].replaceMemAcc( addr, expr ), self.signed)
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 490, in replaceMemAcc
newArgs = [arg.replaceMemAcc( addr, expr ) for arg in self.args]
File "/home/jiangenj/.local/lib/python2.7/site-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Expressions.py", line 1177, in replaceMemAcc
return ITE( self.cond.replaceMemAcc(addr,expr), self.iftrue.replaceMemAcc(addr,expr), self.iffalse.replaceMemAcc(addr,expr))
AttributeError: Cond instance has no attribute 'replaceMemAcc'
Alarm clock

Only starts with root account.

Hi,

It's not possible for me to launch the program in user. Only possible with the root account (sudo).
I installed with sudo too, as it was not possible to do it in user.

$ ROPGenerator
Traceback (most recent call last):
  File "/usr/local/bin/ROPGenerator", line 4, in <module>
    __import__('pkg_resources').run_script('ropgenerator==1.1', 'ROPGenerator')
  File "/home/fraf/.local/lib/python2.7/site-packages/pkg_resources/__init__.py", line 661, in run_script
    self.require(requires)[0].run_script(script_name, ns)
  File "/home/fraf/.local/lib/python2.7/site-packages/pkg_resources/__init__.py", line 1441, in run_script
    exec(code, namespace, namespace)
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/EGG-INFO/scripts/ROPGenerator", line 3, in <module>
    import ropgenerator.Main as Main
  File "/usr/local/lib/python2.7/dist-packages/ropgenerator-1.1-py2.7.egg/ropgenerator/Main.py", line 5, in <module>
    from prompt_toolkit import PromptSession, ANSI
ImportError: cannot import name PromptSession
$

But the same import in user work:

$ python
Python 2.7.15+ (default, Aug 31 2018, 11:56:52)
[GCC 8.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from prompt_toolkit import PromptSession, ANSI
>>> 
$

Regards,

Exploit mode

There was exploit mode in the previous version. What can I use now to construct a syscall ropchain as before?

exploit
syscall -c LINUX execve("/bin/sh\\x00", 0, 0) -f python 

Concatenation of two ropchains

How can I concatenate two ropchains?

For example

chain1 = rop.compile('[0xdeadbeef] = 0x67676767')
chain2 = rop.compile('sys_execve(0xdeadbeef, 0, 0)')

I could only find out the dump method of chains.

feature request: make customized constraints easy

I now want to generate a rop chain, so that for each gadget, the last word is printable.

My thought is that I can provide a script and ropgenerator can take it as a constraint plugin and apply the constraint.

Do you think this is hard to implement?

ModuleNotFoundError: No module named 'ropium'

Hello

Fresh installation, got this error:

$ make
g++ -O2 -Wno-narrowing `python3-config --cflags` -DPYTHON_BINDINGS -Ibindings/python -std=c++11 -fpermissive -fPIC -I ./libropium/include -I ./libropium/dependencies/murmur3 -Wno-write-strings -Wno-sign-compare -Wno-reorder  -o ./bin/libropium.so -shared ./libropium/symbolic/expression.o ./libropium/symbolic/simplification.o ./libropium/symbolic/symbolic.o ./libropium/ir/ir.o ./libropium/arch/arch.o ./libropium/arch/archX86.o ./libropium/arch/disassembler.o ./libropium/ropchain/assertion.o ./libropium/ropchain/constraint.o ./libropium/ropchain/gadget.o ./libropium/ropchain/ropchain.o ./libropium/utils/utils.o ./libropium/database/database.o ./libropium/compiler/compiler.o ./libropium/compiler/il.o ./libropium/compiler/strategy_graph.o ./libropium/compiler/strategy_rules.o ./libropium/compiler/systems.o ./libropium/dependencies/murmur3/murmur3.o -lcapstone `python3-config --libs`
g++ -O2 -Wno-narrowing `python3-config --cflags` -DPYTHON_BINDINGS -Ibindings/python -std=c++11 -fpermissive -fPIC -I ./libropium/include -I ./libropium/dependencies/murmur3 -Wno-write-strings -Wno-sign-compare -Wno-reorder  -o ./bin/tests ./tests/test_all.o ./tests/test_compiler.o ./tests/test_database.o ./tests/test_expression.o ./tests/test_gadgets.o ./tests/test_il.o ./tests/test_ir.o ./tests/test_simplification.o ./tests/test_strategy.o ./libropium/symbolic/expression.o ./libropium/symbolic/simplification.o ./libropium/symbolic/symbolic.o ./libropium/ir/ir.o ./libropium/arch/arch.o ./libropium/arch/archX86.o ./libropium/arch/disassembler.o ./libropium/ropchain/assertion.o ./libropium/ropchain/constraint.o ./libropium/ropchain/gadget.o ./libropium/ropchain/ropchain.o ./libropium/utils/utils.o ./libropium/database/database.o ./libropium/compiler/compiler.o ./libropium/compiler/il.o ./libropium/compiler/strategy_graph.o ./libropium/compiler/strategy_rules.o ./libropium/compiler/systems.o ./libropium/dependencies/murmur3/murmur3.o -lcapstone `python3-config --libs`
g++ -O2 -Wno-narrowing `python3-config --cflags` -DPYTHON_BINDINGS -Ibindings/python -std=c++11 -fpermissive -fPIC -I ./libropium/include -I ./libropium/dependencies/murmur3 -Wno-write-strings -Wno-sign-compare -Wno-reorder  -o ./bin/ropium.so -shared ./bindings/py_arch.o ./bindings/py_module.o ./bindings/py_ropchain.o ./bindings/py_ropium.o ./bindings/utils.o ./libropium/symbolic/expression.o ./libropium/symbolic/simplification.o ./libropium/symbolic/symbolic.o ./libropium/ir/ir.o ./libropium/arch/arch.o ./libropium/arch/archX86.o ./libropium/arch/disassembler.o ./libropium/ropchain/assertion.o ./libropium/ropchain/constraint.o ./libropium/ropchain/gadget.o ./libropium/ropchain/ropchain.o ./libropium/utils/utils.o ./libropium/database/database.o ./libropium/compiler/compiler.o ./libropium/compiler/il.o ./libropium/compiler/strategy_graph.o ./libropium/compiler/strategy_rules.o ./libropium/compiler/systems.o ./libropium/dependencies/murmur3/murmur3.o -lcapstone `python3-config --libs

$ make tests
g++ -O2 -Wno-narrowing `python3-config --cflags` -DPYTHON_BINDINGS -Ibindings/python -std=c++11 -fpermissive -fPIC -I ./libropium/include -I ./libropium/dependencies/murmur3 -Wno-write-strings -Wno-sign-compare -Wno-reorder  -o ./bin/tests ./tests/test_all.o ./tests/test_compiler.o ./tests/test_database.o ./tests/test_expression.o ./tests/test_gadgets.o ./tests/test_il.o ./tests/test_ir.o ./tests/test_simplification.o ./tests/test_strategy.o ./libropium/symbolic/expression.o ./libropium/symbolic/simplification.o ./libropium/symbolic/symbolic.o ./libropium/ir/ir.o ./libropium/arch/arch.o ./libropium/arch/archX86.o ./libropium/arch/disassembler.o ./libropium/ropchain/assertion.o ./libropium/ropchain/constraint.o ./libropium/ropchain/gadget.o ./libropium/ropchain/ropchain.o ./libropium/utils/utils.o ./libropium/database/database.o ./libropium/compiler/compiler.o ./libropium/compiler/il.o ./libropium/compiler/strategy_graph.o ./libropium/compiler/strategy_rules.o ./libropium/compiler/systems.o ./libropium/dependencies/murmur3/murmur3.o -lcapstone `python3-config --libs`

$ sudo make install
install -d /usr/lib/
install -D ./bin/libropium.so /usr/lib/
install -d /usr/include/
install -D ./libropium/include/ropium.hpp /usr/include/
install -d /root/.local/lib/python3.8/site-packages/
install -D ./bin/ropium.so /root/.local/lib/python3.8/site-packages/
install -d /usr/bin/
install -D cli-tool/ropium /usr/bin/
\nROPium was successfully installed.

$ ropium
Traceback (most recent call last):
  File "/usr/bin/ropium", line 2, in <module>
    from ropium import *
ModuleNotFoundError: No module named 'ropium'

pip version 20.0.2
python version 3.8.2
gcc version 9.3.0

What could be the problem?

hang on bad bytes

by doing

(ropium)> badbytes 115
(ropium)> find rax = 0x68732f6e69622f

ropium hangs. The target binary is the libc from ubuntu 18.04

Save the shellcode as soon as added.

Hi,

The shellcodes are saved only if the program is quit with an exit, if you crash or quit by CTRL-C, the shellcodes were not saved. It maybe good to save them as soon as added.

For information for readers, here the file and the format :

root@machine:~# cat .ROPGenerator/shellcodes_X86 
31c050682f2f7368682f62696e89e3505389e199b00bcd80
Linux x86 exec /bin/sh (ragg2)
root@machine:~# 

One line for the shellcode in hexadecimal and one for the description.

Regards,

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.