Work in progress ROP post
Anirudh icyph0x@pm.me
Thu, 06 Jun 2019 14:22:32 +0530
9 files changed,
310 insertions(+),
0 deletions(-)
jump to
A
build/blog/rop-on-arm/index.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html> +<html lang=en> +<link rel="stylesheet" href="/static/style.css" type="text/css"> +<link rel="stylesheet" href="/static/syntax.css" type="text/css"> +<link rel="shortcut icon" type="images/x-icon" href="/static/favicon.ico"> +<meta name="description" content="Making stack-based exploitation great again!"> +<meta name="viewport" content="initial-scale=1"> +<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> +<meta content="#021012" name="theme-color"> +<meta name="HandheldFriendly" content="true"> +<meta name="twitter:card" content="summary_large_image"> +<meta name="twitter:site" content="@icyphox"> +<meta name="twitter:title" content="Return Oriented Programming on ARM (32-bit)"> +<meta name="twitter:description" content="Making stack-based exploitation great again!"> +<meta name="twitter:image" content="/static/icyphox.png"> +<meta property="og:title" content="Return Oriented Programming on ARM (32-bit)"> +<meta property="og:type" content="website"> +<meta property="og:description" content="Making stack-based exploitation great again!"> +<meta property="og:url" content="https://icyphox.sh"> +<meta property="og:image" content="/static/icyphox.png"> +<html> + <title> + Return Oriented Programming on ARM (32-bit) + </title> +<script src="//instant.page/1.1.0" type="module" integrity="sha384-EwBObn5QAxP8f09iemwAJljc+sU+eUXeL9vSBw1eNmVarwhKk2F9vBEpaN9rsrtp"></script> +<div class="container-text"> + <header class="header"> + <a href="../">‹ back</a> + </header> +<body> + <div class="content"> + <div align="left"> + <p> 05 June, 2019 </p> + <h1>Return Oriented Programming on ARM (32-bit)</h1> + +<h2>Making stack-based exploitation great again!</h2> + +<p>Before we start <em>anything</em>, you’re expected to know the basics of ARM +assembly to follow along. I highly recommend +<a href="https://twitter.com/fox0x01">Azeria’s</a> series on <a href="https://azeria-labs.com/writing-arm-assembly-part-1/">ARM Assembly +Basics</a>. Once you’re +comfortable with it, proceed with the next bit — environment setup.</p> + +<h3>Setup</h3> + +<p>Since we’re working with the ARM architecture, there are two options to go +forth with: </p> + +<ol> +<li>Emulate — head over to <a href="https://www.qemu.org/download/">qemu.org/download</a> and install QEMU. +And then download and extract the ARMv6 Debian Stretch image from one of the links <a href="https://blahcat.github.io/qemu/">here</a>. +The scripts found inside should be self-explanatory.</li> +<li>Use actual ARM hardware, like an RPi.</li> +</ol> + +<p>For debugging and disassembling, we’ll be using plain old <code>gdb</code>, but you +may use <code>radare2</code>, IDA or anything else, really. All of which can be +trivially installed.</p> + +<p>Finally, the binary we’ll be using in this exercise is <a href="https://twitter.com/bellis1000">Billy Ellis’</a> +<a href="/static/files/roplevel2.c">roplevel2</a>. </p> + +<p>Compile it:</p> + +<div class="codehilite"><pre><span></span><code>$ gcc roplevel2.c -o rop2 +</code></pre></div> + +<p>With that out of the way, here’s a quick run down of what ROP actually is.</p> + +<h3>A primer on ROP</h3> + +<p>ROP or Return Oriented Programming is a modern exploitation technique that’s +used to bypass protections like the <strong>NX bit</strong> (no-execute bit) and <strong>code sigining</strong>. +In essence, no code in the binary is actually modified and the entire exploit +is crafted out of pre-existing artifacts within the binary, known as <strong>gadgets</strong>.</p> + +<p>A gadget is essentially a small sequence of code (instructions), ending with +a <code>ret</code>, or a return instruction. In our case, since we’re dealing with ARM +code, there is no <code>ret</code> instruction but rather a <code>pop {pc}</code> or a <code>bx lr</code>. +These gadgets are <em>chained</em> together by jumping (returning) from one onto the other +to form what’s called as a <strong>ropchain</strong>. At the end of a ropchain, +there’s generally a call to <code>system()</code>, to acheive code execution.</p> + +<p>In practice, the process of executing a ropchain is something like this:</p> + +<ul> +<li>confirm the existence of a stack-based buffer overflow</li> +<li>identify the offset at which the instruction pointer gets overwritten</li> +<li>locate the addresses of the gadgets you wish to use</li> +<li>craft your input keeping in mind the stack’s layout, and chain the addresses +of your gadgets</li> +</ul> + +<p><a href="https://twitter.com/LiveOverflow">LiveOverflow</a> has a <a href="https://www.youtube.com/watch?v=zaQVNM3or7k&list=PLhixgUqwRTjxglIswKp9mpkfPNfHkzyeN&index=46&t=0s">beautiful video</a> where he explains ROP using “weird machines”. +Check it out, it might be just what you needed for that “aha!” moment :)</p> + +<p>Still don’t get it? Don’t fret, we’ll look at <em>actual</em> exploit code in a bit and hopefully +that should put things into perspective.</p> + +<h3>Exploring our binary</h3> + +<p>Start by running it, and entering any arbitrary string. On entering a fairly +large string, say, “AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”, we +see a segmentation fault occur.</p> + +<p><img src="/static/img/string_segfault.png" alt="string and segfault" /></p> + +<p>Now, open it up in <code>gdb</code> and look at the functions inside it.</p> + +<p><img src="/static/img/gdb_functions.png" alt="gdb functions" /></p> + +<p>There are three functions that are of importance here, <code>main</code>, <code>winner</code> and +<code>gadget</code>. Disassembling the <code>main</code> function:</p> + +<p><img src="/static/img/gdb_main_disas.png" alt="gdb main disassembly" /></p> + +<p>We see a buffer of 16 bytes being created (<code>sub sp, sp, #16</code>), and some calls +to <code>puts()</code>/<code>printf()</code> and <code>scanf()</code>. Looks like <code>winner</code> and <code>gadget</code> are +never actually called.</p> + +<p>Disassembling the <code>gadget</code> function:</p> + +<p><img src="/static/img/gdb_gadget_disas.png" alt="gdb gadget disassembly" /></p> + +<p>This is fairly simple, the stack is being initialized by <code>push</code>ing <code>{r11}</code>, +which is also the frame pointer (<code>fp</code>). What’s interesting is the <code>pop {r0, pc}</code> +instruction in the middle. This is a <strong>gadget</strong>.</p> + +<p>We can use this to control what goes into <code>r0</code> and <code>pc</code>. Unlike in x86 where +arguments to functions are passed on the stack, in ARM the registers <code>r0</code> to <code>r3</code> +are used for this. So this gadget effectively allows us to pass arguments to +functions using <code>r0</code>, and subsequently jumping to them by passing its address +in <code>pc</code>. Neat.</p> + +<p>Moving on to the disassembly of the <code>winner</code> function:</p> + +<p><img src="/static/img/gdb_disas_winner.png" alt="gdb winner disassembly" /></p> + + </div> + </body> + </div> +</html>
A
build/static/files/roplevel2.c
@@ -0,0 +1,29 @@
+#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +char str1[] = "uname -a"; +char str2[] = "touch pwned.txt"; +char str3[] = "ls -sail"; + +void winner(){ + printf("Nothing interesting here...\n"); + system("# this does nothing..."); + exit(0); +} + +void gadget(){ + __asm__("pop {r0,pc}\n"); +} + +int main(){ + char buff[16]; + printf("Welcome to ROPLevel2 created by Billy Ellis (@bellis1000)\n"); + printf("The objective of this level is to execute a shell command of your choice by using a ROP gadget followed by jumping to system()\n"); + printf("Good luck: "); + scanf("%s",buff); + printf("Nice try ;)\n"); + return 0; +} +
A
pages/blog/rop-on-arm.md
@@ -0,0 +1,110 @@
+--- +template: text.html +title: Return Oriented Programming on ARM (32-bit) +subtitle: Making stack-based exploitation great again! +date: 05 June, 2019 +--- + +# Return Oriented Programming on ARM (32-bit) +## Making stack-based exploitation great again! + +Before we start _anything_, you’re expected to know the basics of ARM +assembly to follow along. I highly recommend +[Azeria’s](https://twitter.com/fox0x01) series on [ARM Assembly +Basics](https://azeria-labs.com/writing-arm-assembly-part-1/). Once you’re +comfortable with it, proceed with the next bit — environment setup. + +### Setup + +Since we’re working with the ARM architecture, there are two options to go +forth with: + +1. Emulate — head over to [qemu.org/download](https://www.qemu.org/download/) and install QEMU. +And then download and extract the ARMv6 Debian Stretch image from one of the links [here](https://blahcat.github.io/qemu/). +The scripts found inside should be self-explanatory. +2. Use actual ARM hardware, like an RPi. + +For debugging and disassembling, we’ll be using plain old `gdb`, but you +may use `radare2`, IDA or anything else, really. All of which can be +trivially installed. + +Finally, the binary we’ll be using in this exercise is [Billy Ellis’](https://twitter.com/bellis1000) +[roplevel2](/static/files/roplevel2.c). + +Compile it: +```sh +$ gcc roplevel2.c -o rop2 +``` + +With that out of the way, here’s a quick run down of what ROP actually is. + +### A primer on ROP + +ROP or Return Oriented Programming is a modern exploitation technique that’s +used to bypass protections like the **NX bit** (no-execute bit) and **code sigining**. +In essence, no code in the binary is actually modified and the entire exploit +is crafted out of pre-existing artifacts within the binary, known as **gadgets**. + +A gadget is essentially a small sequence of code (instructions), ending with +a `ret`, or a return instruction. In our case, since we’re dealing with ARM +code, there is no `ret` instruction but rather a `pop {pc}` or a `bx lr`. +These gadgets are _chained_ together by jumping (returning) from one onto the other +to form what’s called as a **ropchain**. At the end of a ropchain, +there’s generally a call to `system()`, to acheive code execution. + +In practice, the process of executing a ropchain is something like this: + +- confirm the existence of a stack-based buffer overflow +- identify the offset at which the instruction pointer gets overwritten +- locate the addresses of the gadgets you wish to use +- craft your input keeping in mind the stack’s layout, and chain the addresses +of your gadgets + +[LiveOverflow](https://twitter.com/LiveOverflow) has a [beautiful video](https://www.youtube.com/watch?v=zaQVNM3or7k&list=PLhixgUqwRTjxglIswKp9mpkfPNfHkzyeN&index=46&t=0s) where he explains ROP using “weird machines”. +Check it out, it might be just what you needed for that “aha!” moment :) + +Still don’t get it? Don’t fret, we’ll look at _actual_ exploit code in a bit and hopefully +that should put things into perspective. + +### Exploring our binary + +Start by running it, and entering any arbitrary string. On entering a fairly +large string, say, “AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”, we +see a segmentation fault occur. + +![string and segfault](/static/img/string_segfault.png) + +Now, open it up in `gdb` and look at the functions inside it. + +![gdb functions](/static/img/gdb_functions.png) + +There are three functions that are of importance here, `main`, `winner` and +`gadget`. Disassembling the `main` function: + +![gdb main disassembly](/static/img/gdb_main_disas.png) + +We see a buffer of 16 bytes being created (`sub sp, sp, #16`), and some calls +to `puts()`/`printf()` and `scanf()`. Looks like `winner` and `gadget` are +never actually called. + +Disassembling the `gadget` function: + +![gdb gadget disassembly](/static/img/gdb_gadget_disas.png) + +This is fairly simple, the stack is being initialized by `push`ing `{r11}`, +which is also the frame pointer (`fp`). What’s interesting is the `pop {r0, pc}` +instruction in the middle. This is a **gadget**. + +We can use this to control what goes into `r0` and `pc`. Unlike in x86 where +arguments to functions are passed on the stack, in ARM the registers `r0` to `r3` +are used for this. So this gadget effectively allows us to pass arguments to +functions using `r0`, and subsequently jumping to them by passing its address +in `pc`. Neat. + +Moving on to the disassembly of the `winner` function: + +![gdb winner disassembly](/static/img/gdb_disas_winner.png) + + + +
A
static/files/roplevel2.c
@@ -0,0 +1,29 @@
+#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +char str1[] = "uname -a"; +char str2[] = "touch pwned.txt"; +char str3[] = "ls -sail"; + +void winner(){ + printf("Nothing interesting here...\n"); + system("# this does nothing..."); + exit(0); +} + +void gadget(){ + __asm__("pop {r0,pc}\n"); +} + +int main(){ + char buff[16]; + printf("Welcome to ROPLevel2 created by Billy Ellis (@bellis1000)\n"); + printf("The objective of this level is to execute a shell command of your choice by using a ROP gadget followed by jumping to system()\n"); + printf("Good luck: "); + scanf("%s",buff); + printf("Nice try ;)\n"); + return 0; +} +