├── LICENSE ├── README.md ├── package.json ├── r2pm_install.sh ├── r2retdec.js └── retdec_install.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 securisec 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | 3 | # r2retdec 4 | [![codebeat badge](https://codebeat.co/badges/c18f32ef-bf28-4948-8156-9a52e50e121c)](https://codebeat.co/projects/github-com-securisec-r2retdec-master) 5 | [![Twitter Follow](https://img.shields.io/twitter/follow/securisec.svg?style=social&label=Follow)]() 6 | [![Analytics](https://ga-beacon.appspot.com/UA-113966566-4/r2wiki/readme)](https://github.com/securisec/r2wiki) 7 | ![repo size](https://img.shields.io/github/repo-size/securisec/r2retdec.svg) 8 | 9 | 10 | r2retdec is a bridge in between radare2 and retdec and decompiles individual functions. It also provides summary of strings, xrefs and calls for a function. The various windows are mouse scrollable and draggable. 11 | 12 | [![asciicast](https://asciinema.org/a/170931.png)](https://asciinema.org/a/170931) 13 | 14 | ## Installation 15 | Install from r2pm. 16 | ``` 17 | r2pm init 18 | r2pm update 19 | r2pm -i r2retdec 20 | ``` 21 | - Create a file in $HOME call .r2retdec and put the full path to retdec-decompiler.sh in it. 22 | - A basic installation script is included in this repo. retdec_install.sh 23 | 24 | ## Uninstallation 25 | ``` 26 | r2pm -u r2retdec 27 | ``` 28 | 29 | ## Usage 30 | ``` 31 | usage: $dec [-h] [-p] [-t FILE] 32 | 33 | r2retdec help 34 | 35 | Optional arguments: 36 | -h, --help Show this help message and exit. 37 | -t TMP Set temp file for decompiled code 38 | -p Print dicompilation to stdout 39 | --python Print decompilation in python syntax. Default is C 40 | 41 | Invoke from inside r2 shell with $dec 42 | ``` 43 | 44 | - Press `h` in visual mode for visual mode help 45 | 46 | ## Dependencies 47 | Needs a locally compiled retdec available from https://github.com/avast-tl/retdec 48 | 49 | ## Tested with 50 | - Node version 8 and 9 51 | - Ubuntu 16.04 Vagrant 52 | - Mac OSX 10.12 53 | 54 | ## Supported architectures 55 | (32b only): Intel x86, ARM, MIPS, PIC32, and PowerPC. 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "r2decompile", 3 | "version": "1.0.0", 4 | "description": "Use a local retdec to decompile functions", 5 | "main": "r2decompile.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/securisec/r2decompile.git" 12 | }, 13 | "keywords": [], 14 | "author": "securisec", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/securisec/r2decompile/issues" 18 | }, 19 | "homepage": "https://github.com/securisec/r2decompile#readme", 20 | "dependencies": { 21 | "argparse": "^1.0.10", 22 | "blessed": "^0.1.81", 23 | "cli-highlight": "^1.2.3", 24 | "r2pipe": "^2.6.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /r2pm_install.sh: -------------------------------------------------------------------------------- 1 | R2PM_BEGIN 2 | 3 | R2PM_GIT "https://github.com/securisec/r2retdec" 4 | R2PM_DESC "[r2retdec] Use local opensource retdec to decompile functions" 5 | 6 | R2PM_DOC=" 7 | usage: $r2retdec [-h] [-p] [-t FILE] 8 | 9 | r2retdec help 10 | 11 | Optional arguments: 12 | -h, --help Show this help message and exit. 13 | -t TMP Set temp file for decompiled code 14 | -p Print decompilation to stdout 15 | 16 | Invoke from inside r2 shell with $dec 17 | " 18 | 19 | R2PM_INSTALL() { 20 | cd ${R2PM_GITDIR}/r2retdec 21 | npm install || exit 1 22 | cd - 23 | echo '$'dec="#"'!'"pipe node ${R2PM_GITDIR}/r2retdec/r2retdec.js" >> ~/.radare2rc || exit 1 24 | echo "\n[+] r2retdec has been installed" 25 | echo "\n[*] Make sure to put the path to retdec-decompiler.sh in \$HOME/.r2retdec" 26 | } 27 | 28 | R2PM_UNINSTALL() { 29 | rm -rf "${R2PM_GITDIR}"/r2retdec 30 | } 31 | 32 | R2PM_END -------------------------------------------------------------------------------- /r2retdec.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const r2pipe = require('r2pipe'); 4 | const r2 = r2pipe.lpipeSync(); 5 | const exec = require('child_process').execSync; 6 | const highlight = require('cli-highlight').highlight; 7 | const fs = require('fs'); 8 | const blessed = require('blessed'); 9 | const ArgumentParser = require('argparse').ArgumentParser; 10 | const parser = new ArgumentParser({ 11 | addHelp: true, 12 | description: 'r2retdec help' 13 | }); 14 | 15 | 16 | // r2pipe.options = ['-N']; 17 | 18 | function arg_help() { 19 | // argument parser 20 | parser.addArgument('-t', { 21 | help: 'Set temp file for decompiled code', 22 | defaultValue: '/tmp/r2.c', 23 | dest: 'tmp' 24 | }); 25 | parser.addArgument('-v', { 26 | help: 'Open visual mode to navigate with r2retdec', 27 | dest: 'visual', 28 | action: 'storeTrue' 29 | }); 30 | parser.addArgument('--python', { 31 | help: 'Print decompilation in python syntax. Default is C', 32 | dest: 'python', 33 | action: 'storeTrue' 34 | }); 35 | return parser.parseArgs(); 36 | } 37 | 38 | function checkConfig() { 39 | // Checks for and returns the path of the config file 40 | var configFile = process.env.HOME + '/.r2retdec'; 41 | if (!fs.existsSync(configFile)) { 42 | console.log('\nCould not find config file. Set the path to retdec in $HOME/.r2retdec'); 43 | process.exit(0); 44 | } else { 45 | return fs.readFileSync(configFile, 'utf8'); 46 | } 47 | } 48 | 49 | function boxFrame(align, height, width, content) { 50 | var frame = blessed.box({ 51 | scrollable: true, 52 | alwaysScroll: true, 53 | scrollbar: { 54 | bg: 'red' 55 | }, 56 | vi: true, 57 | keys: true, 58 | mouse: true, 59 | top: align, 60 | draggable: true, 61 | left: 'center', 62 | width: width, 63 | height: height, 64 | content: content, 65 | tags: true, 66 | border: { 67 | type: 'line' 68 | }, 69 | style: { 70 | fg: 'white', 71 | border: { 72 | fg: '#f0f0f0' 73 | }, 74 | focus: { 75 | border: { 76 | bg: 'red' 77 | } 78 | } 79 | } 80 | }); 81 | return frame; 82 | } 83 | 84 | function smallBoxes(command, key) { 85 | var info = screen.key([key], function () { 86 | var strings = boxFrame('left', '40%', '50%', command); 87 | strings.align = 'left'; 88 | screen.append(strings); 89 | screen.key(['q'], function () { 90 | strings.hide(); 91 | }); 92 | screen.render(); 93 | strings.focus(); 94 | }); 95 | } 96 | 97 | function rename_functions(code) { 98 | fn_data = r2.cmdj('aflj'); 99 | for (i = 0; i < fn_data.length; i++) { 100 | r2_name = fn_data[i].name; 101 | if(r2_name.slice(0,4) != "fcn.") { 102 | retdec_name = "function_" + fn_data[i].offset.toString(16); 103 | code = code.replace(new RegExp(retdec_name, 'g'), r2_name); 104 | } 105 | } 106 | return code 107 | } 108 | 109 | // runs retdec decompiler script 110 | var binaryPath = r2.cmdj('oj')[0]['uri']; 111 | // Check if we're using a ptrace uri (meaning we're in -d mode) 112 | if (RegExp('^ptrace:\/\/[0-9]+$').test(binaryPath.trim())) { 113 | console.log('Decompilation does not work while in debug mode. Use pdc.'); 114 | process.exit(0) 115 | } 116 | var pdf = r2.cmdj('pdfj'); 117 | if (pdf === null) { 118 | // Cannot find any function in current offset 119 | process.exit(0); 120 | } 121 | var functionStartAddress = '0x' + pdf.addr.toString(16); 122 | var functionEndAddress = '0x' + pdf.ops.pop().offset.toString(16); 123 | var retDecPath = checkConfig().replace('\n', ''); 124 | var a = arg_help(); 125 | var function_pdf = r2.cmd('pdf'); 126 | 127 | if (a.python === true) { 128 | var command = `${retDecPath} --cleanup -o ${a.tmp} -l py --select-ranges ${functionStartAddress}-${functionEndAddress} ${binaryPath}`; 129 | } else { 130 | var command = `${retDecPath} --cleanup -o ${a.tmp} --select-ranges ${functionStartAddress}-${functionEndAddress} ${binaryPath}`; 131 | } 132 | 133 | try { 134 | var p = exec(command).toString(); 135 | var code = fs.readFileSync(a.tmp, 'utf8'); 136 | code = rename_functions(code); 137 | var highlighted_code = highlight(code); 138 | } catch (e) { 139 | highlighted_code = 'Not valid for 64 bit arch. Using pdc instead\n\n'; 140 | highlighted_code += highlight(r2.cmd('pdc')); 141 | } 142 | 143 | if (a.visual !== true) { 144 | console.log(highlighted_code); 145 | process.exit(0); 146 | } 147 | 148 | var screen = blessed.screen({ 149 | smartCSR: true 150 | }); 151 | 152 | screen.title = 'r2retdec'; 153 | 154 | var help = blessed.text({ 155 | parent: screen, 156 | content: 'HELP: q (quit), h (help)', 157 | width: '90%', 158 | left: 'center', 159 | top: '98%' 160 | }); 161 | 162 | screen.key(['tab'], function (ch, key) { 163 | screen.focusNext(); 164 | }); 165 | 166 | screen.key(['h'], function (ch, key) { 167 | var help = blessed.box({ 168 | top: 'center', 169 | left: 'center', 170 | width: '25%', 171 | height: '40%', 172 | content: `HELP: 173 | c: close help 174 | d: show disassembly 175 | s: function strings 176 | c: function calls 177 | q: quit r2retdec 178 | TAB: choose box`, 179 | border: { 180 | type: 'line', 181 | fg: 'red' 182 | }, 183 | parent: screen 184 | }); 185 | screen.append(help); 186 | help.focus(); 187 | screen.key(['q'], function (key, ch) { 188 | help.destroy(); 189 | }); 190 | }); 191 | // show disassembly 192 | screen.key(['d'], function () { 193 | var box1 = boxFrame('left', '100%', '75%', function_pdf); 194 | box1.align = 'left'; 195 | screen.append(box1); 196 | box1.key(['q'], function () { 197 | box1.hide(); 198 | }); 199 | screen.render(); 200 | box1.focus(); 201 | }); 202 | // show strings 203 | smallBoxes(r2.cmd('pdsf~str'), 's'); 204 | 205 | // show calls 206 | var calls = smallBoxes; 207 | calls.height = '50%'; 208 | calls(r2.cmd('pdsf~call'), 'c'); 209 | 210 | // show xref 211 | smallBoxes(r2.cmd('axt'), 'x'); 212 | 213 | var box2 = boxFrame('center', '99%', '100%', highlighted_code); 214 | box2.focus(); 215 | screen.append(box2); 216 | box2.key(['q'], function () { 217 | screen.destroy(); 218 | r2.quit(); 219 | process.exit(0); 220 | }); 221 | 222 | screen.render(); 223 | -------------------------------------------------------------------------------- /retdec_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Only tested with a fresh vagrant running Ubuntu 16.04 64 bit [ENTER] to continue" 4 | read something 5 | sudo apt update -y 6 | sudo apt upgrade -y 7 | cpucores="nproc" 8 | 9 | sudo apt-get install libcurl4-gnutls-dev build-essential git perl python3 bash bison flex autoconf automake libtool pkg-config m4 coreutils zlib1g-dev libtinfo-dev wget bc upx doxygen graphviz python3-dev -y 10 | 11 | git clone https://github.com/avast-tl/retdec 12 | 13 | git clone -b v3.10.2 https://cmake.org/cmake.git cmake 14 | cd cmake 15 | ./bootstrap --system-curl 16 | make -j$cpucores 17 | sudo make install 18 | 19 | cd ~/retdec 20 | mkdir build && cd build 21 | cmake -DCMAKE_INSTALL_PREFIX=$HOME/retdec-install .. 22 | wget https://github.com/avast-tl/llvm/archive/753e703b185f07f6f85c8ca474a65f4a965371b1.zip -O external/src/llvm.zip 23 | make -j$cpucores 24 | make install 25 | --------------------------------------------------------------------------------