22 Feb 2010 @ 8:19 PM 

UPDATE:

***** ACCESS VIOLATION *****
AppleMobileDeviceService.exe:0040fe9a mov eax,[eax] from thread 276 caused acces
s violation
when attempting to read from 0x6b736643

CONTEXT DUMP
EIP: 0040fe9a mov eax,[eax]
EAX: 6b736643 (1802724931) -> N/A
EBX: 003c3ee8 (   3948264) -> A><XAAAC (heap)
ECX: 00420498 (   4326552) -> H>< (AppleMobileDeviceService.exe.data)
EDX: 00000000 (         0) -> N/A
EDI: 0078fc04 (   7928836) -> H# (heap)
ESI: 003c3ee8 (   3948264) -> A><XAAAC (heap)
EBP: 008cfeec (   9240300) -> t(AB <}e= |~| < ;<><C<B<n@><be=x><><x09@=@x)|><x
x><[x|0| (stack)
ESP: 008cfee4 (   9240292) -> Cfsk (stack)
+00: 6b736643 (1802724931) -> N/A
+04: 00420498 (   4326552) -> H>< (AppleMobileDeviceService.exe.data)
+08: 008cff74 (   9240436) -> N/A
+0c: 00410c28 (   4262952) -> N/A
+10: 004204a0 (   4326560) -> Cfsk  (AppleMobileDeviceService.exe.data)
+14: 00000009 (         9) -> N/A

disasm around:
0x0040fe88 leave
0x0040fe89 ret
0x0040fe8a push ebp
0x0040fe8b mov ebp,esp
0x0040fe8d push ecx
0x0040fe8e push ecx
0x0040fe8f mov eax,[ebp+0x8]
0x0040fe92 mov eax,[eax]
0x0040fe94 mov [ebp-0x8],eax
0x0040fe97 mov eax,[ebp-0x8]
0x0040fe9a mov eax,[eax]
0x0040fe9c mov [ebp-0x4],eax
0x0040fe9f mov eax,[ebp+0x8]
0x0040fea2 mov ecx,[ebp-0x4]
0x0040fea5 mov [eax],ecx
0x0040fea7 mov eax,[ebp-0x4]
0x0040feaa mov ecx,[ebp+0x8]
0x0040fead mov [eax+0x4],ecx
0x0040feb0 mov eax,[ebp-0x8]
0x0040feb3 leave
0x0040feb4 ret

stack unwind:
AppleMobileDeviceService.exe:00410c28
AppleMobileDeviceService.exe:00401c6e
AppleMobileDeviceService.exe:00401d13

SEH unwind:
008cffdc -> AppleMobileDeviceService.exe:00403930 sub esp,0×14
ffffffff -> kernel32.dll:7c839ad8 push ebp

In previous posts we started fuzzing AppleMobileDeviceService.exe using a technique called In Memory Fuzzing.  This approach was outlined in chapter 19/20 of Fuzzing:  Brute Force Vulnerability Discovery.

This article will briefly touch on the topic of reverse engineering your binary to determine your enrty and restore hooks.  These hooks are very important as they tell the debugger where to take its first memory snapshot and when to revert back to this state.

As fuzzing becomes more complex it will be up to you to determine the changes made in memory during this time and take this into consideration when looking into crashes.

Since we are interested in hooking data received via winsock the best place to start is the imports section of the binary.  When we double click recv and jump to xRefs we see only one.

The decompiled look at this function goes a little something like this:

If recv returns FFFFFFFF (or -1) there is an error. And v7 points to it.  If not, v7 is set to 0.  If everything looks good, return the data.

Cool, so this is just a little wrapper to recv with some error handling I guess.  I wonder where this function is called from…

…We’re on the right track so lets set breakpoints after the return of the calls to this function.

(set a breakpoint on all of them!)

When we attach our iPhone IDA hits a breakpoint.  If you set breakpoints after all calls to our recv() wrapper you’ll get a breakpoint at the first packet receved, the address is 004133F3…

We take a look at ESP:

If you look at ESP+4 (009CFEE4) you may notice this is a dword pointer, by pressing D a couple of times it will convert this to an address that you can double click on or mouse over to de-reference…

So, there we have it… a pointer to our data (ESP+4) and a spot to hook, 004133F3.

If we take a look at the call graph:

We can see a pretty logical restore hook:

Zooming in we snag the address and hope for the best.

We will take a look at using code coverage tools to determine the best entry and restore hook points as soon as I get my paws on BaSO4

You can grab the script here or just copy-and paste from the end of this posting.

Here is a video of the basic fuzzer in action:

In Memory Fuzzing iPhone Device Service from jeremy Richards on Vimeo.

And here is the source to the fuzzer:

#!c:\python\python.exe

"""
In Memory Fuzzer 0.02a
"""

import time
import random
import utils
import struct

from pydbg import *
from pydbg.defines import *

snapshot_hook  = 0x00413495
restore_hook   = 0x00413604
snapshot_taken = False
hit_count      = 0
address        = 0

########################################################################################################################
### callback handlers.
########################################################################################################################

def handle_bp (dbg):
    global snapshot_hook, restore_hook, snapshot_taken, hit_count, address

    if dbg.exception_address == snapshot_hook:
        hit_count += 1
        print "snapshot / mutate hook point hit #%d" % hit_count

        # if a process snapshot has not yet been taken, take one now.
        if not snapshot_taken:
            start = time.time()
            print "taking process snapshot...",
            dbg.process_snapshot()
            end = time.time() - start
            print "done. completed in %.03f seconds" % end
            #context_list = dbg.dump_context_list(stack_depth=4, print_dots=True)
            print dbg.dump_context(stack_depth=4, print_dots=True)
            #print dbg.hex_dump(dbg.read_process_memory(dbg.context.Eax, 20))
            snapshot_taken = True

        if hit_count > 1:
            if address:
                print "freeing last chunk at %08x" % address
                dbg.virtual_free(address, 1000, MEM_DECOMMIT)

            print "allocating chunk of memory to hold mutation"
            address = dbg.virtual_alloc(None, 1000, MEM_COMMIT, PAGE_READWRITE)
            print "memory allocated at %08x" % address
            print "generating mutant...",
            mutant = struct.pack('hllll',random.randint(0, 255),0,2,2,0)
            print "done. generating mutant"
            print "writing mutant into target memory space"
            dbg.write(address, mutant)
            print "modifying function argument to point to mutant"
            dbg.write(dbg.context.Esp + 4, dbg.flip_endian(address))
            print dbg.hex_dump(dbg.read_process_memory(address,16))
            print "continuing execution...\n"
            dbg.bp_set(restore_hook)

    if dbg.exception_address == restore_hook:
        start = time.time()
        print "restoring process snapshot...",
        dbg.process_restore()
        end = time.time() - start
        print "done. completed in %.03f seconds" % end
        dbg.bp_set(restore_hook)

    return DBG_CONTINUE

def handle_av (dbg):
    print "***** ACCESS VIOLATION *****"

    crash_bin = utils.crash_binning.crash_binning()
    crash_bin.record_crash(dbg)

    print crash_bin.crash_synopsis()
    dbg.terminate_process()

########################################################################################################################

dbg = pydbg()

dbg.set_callback(EXCEPTION_BREAKPOINT,       handle_bp)
dbg.set_callback(EXCEPTION_ACCESS_VIOLATION, handle_av)

found_target = False
for (pid, proc_name) in dbg.enumerate_processes():
    if proc_name.lower() == "applemobiledeviceservice.exe":
        found_target = True
        break

if found_target:
    dbg.attach(pid)
    dbg.bp_set(snapshot_hook)
    dbg.bp_set(restore_hook)
    print "attached to %d. debugger active." % pid
    for addr in dbg.breakpoints.keys():
        print "bp at %08x" % addr
    dbg.run()
else:
    print "target not found."
Posted By: jRichards
Last Edit: 25 Feb 2010 @ 10:16 PM

EmailPermalinkComments (1)
Tags
Categories: Fuzzing, Reversing
 04 Feb 2010 @ 6:34 PM 

If you’ve spent any time playing with PaiMei’s PEEK! Module you’ve no doubt run into bugs.

PEEK! has the ability to track and print to screen the registers and stack when calls to recv() and recvfrom() are made. When these functions return EAX holds the buffer length of the recieved packet… unless there is a failure and it returns -1 (or FFFFFFFF). Unfortunately pydbg is instructed to do this without first checking the value of length.:

read_buf = create_string_buffer(length)


Which results in this:

File “C:\Python25\lib\ctypes\__init__.py”, line 70, in create_string_buffer
buftype = c_char * init
OverflowError: cannot fit ‘long’ into an index-sized integer

What’s the right ay to fix this? Should we edit pydbg to make sure it doesnt try to create a buffer 4294967295 in length? Maybe… but for now we’ll edit PAIMEIpeek.py because its easier, faster, and I don’t have commit to the svn

To resolve this, I modified each hook container call back like so:

    ####################################################################################################################
    def socket_logger_ws2_recvfrom (self, dbg, args, ret):
        '''
        Hook container call back.
        '''

        self.msg("ws2_32.recvfrom(buf=%08x, len=%d)" % (args[1], args[2]))
        self.msg("Actually received %d bytes:" % ret)
        if int(ret) == 4294967295:
            self.msg("ERROR received from ws2_32:%d" % ret)
        else:
            self.msg(dbg.hex_dump(dbg.read(args[1], ret)))

    ####################################################################################################################

Yes, its a hack but it accomplishes what I need to continue monitoring so it’s good enough for now.

Posted By: jRichards
Last Edit: 04 Feb 2010 @ 06:35 PM

EmailPermalinkComments (2)
Tags
Categories: Fuzzing, PaiMei, Reversing
 02 Feb 2010 @ 11:58 PM 

PaiMei and Sulley still rely on the power of IDA Pro to disassemble and identify basic blocks. This crucial piece of information is essential for setting breakpoints that identify entry and exit point of each basic block/function.

Thankfully the process of generating a PIDA file is rather simple these days. IDA Python has been included with the standard distribution of IDA Pro since 5.(2?). It is unfortunate that the whole process relies on having IDA Pro as it is a difficult product to license as an independant researcher. Thankfully I’ve got friends willing to generate my PIDA files for me. If anyone out there is interested, I’d love to develop a web front end/automated process for submitting a binary and generating a PIDA file.

In any case the process boils down to:

[1] Open the binary in IDA Pro and let it analyze the file. The console should alert you when AutoAnalysis is complete.
[2] Press ALT-9 and run C:\paimei\pida_dump.py
[3] Choose Full, Propagate nodes and edges for API calls (imports) Yes, Enumerate RPC Yes, Save.

Watch for this in the console log:

Analyzing IDB…
Analyzing functions…
Enumerating imports…
Enumerating RPC interfaces…
Enumerating intramodular cross references…
Done. Completed in 23.844000 seconds.

Saving to file… 25% 50% 75% Done. Completed in 1.562000 seconds.

Posted By: jRichards
Last Edit: 02 Feb 2010 @ 11:58 PM

EmailPermalinkComments (5)
Tags
Categories: Fuzzing, PaiMei, Reversing
 02 Feb 2010 @ 9:30 PM 

If you’re going to start fuzzing with Sulley I’m hoping you’ve spent a little time getting to know the concepts.

Overall usage of Sulley breaks down to the following:
Data Representation: First step in using any fuzzer. Run your target and tickle some interfaces while snagging the packets. Break down the protocol into individual requests and represent that as blocks in Sulley.
Session: Link your developed requests together to form a session, attach the various available Sulley monitoring agents (socket, debugger, etc…) and commence fuzzing.
Post Mortem: Review the generated data and monitored results. Replay individual test cases.

Today we’re going to be focusing on Data Representation. I’ve chosen a UDP broadcast protocol used by a demo SCADA app.

Here is a screenshot of the network traffic.

So it sends packets out from TCP 5513 to a UDP subnet broadcast IP of 10.7.0.255 at port 5512. After observing the application idle for 5 minutes I identified two slightly different packets:


4e65747363616e3b30643b353b
4e65747363616e3b30643b373b


As you can see in the wireshark screenshot, this is an ascii, plain text representation of those two packets:


Netscan;0d;5;
Netscan;0d;7;


To build our simple protocol defnintion lets look at the following example:

# fuzzes the string: 
s_delim("<")
s_string("BODY")
s_delim(" ")
s_string("bgcolor")
s_delim("=")
s_delim("\"")
s_string("black")
s_delim("\"")
s_delim(">")


Ours will look like:

s_string("Netscan")
s_delim(";")
s_binary(“0d”)
s_delim(";")
s_word(1, format="ascii")
s_delim(";")

Check out “C:/sulley/docs/index.html#installation” for full API details.

Lets create our Sulley fuzzing scripts. I use Crimson Editor for quick edits. Feel free to use your favorite IDE.

Create a new file called irc5.py in C:\sulley\requests

from sulley import *

########################################################################################################################
s_initialize("irc5")

if s_block_start("bcast"):
	s_string("Netscan")
	s_delim(";")
	s_binary("0d")
	s_delim(";")
	s_word(1, format="ascii")
	s_delim(";")
s_block_end()

Now in C:\sulley\ create irc5_bcast.py with the following:

#!c:\\python\\python.exe

from sulley   import *
from requests import irc5

########################################################################################################################
sess = sessions.session(session_filename="audits/irc5-bcast.session", sleep_time=.25, log_level=10)
sess                   = sessions.session(proto="udp")
sess.add_target(sessions.target("10.7.0.255", 5513))

sess.connect(s_get("irc5"))
sess.fuzz()

Now from the DOS box run the fuzzing script:


And if we look at Wireshark we can see the packets going across the wire… I wonder what code out packets are hitting… is there more we should know about the code that processes incoming packets (yes!)

Enter Process Stalking. This process will allow us to identify the basic blocks hit by our incoming packets. Check out the next post on Process Stalking.

Posted By: jRichards
Last Edit: 02 Feb 2010 @ 11:39 PM

EmailPermalinkComments (0)
Tags
Categories: Fuzzing, PaiMei, Reversing
 02 Feb 2010 @ 8:36 PM 

When analyzing software for vulnerabilities we need to map its attack surface. For obvious reasons, remote unauthenticated communication is of special interest because it can potentially yeild the holy grail in vulnerability research – remote, unauthenticated arbitrary code execution.

The process of picking a target is up to you. If you want to make some money from the folks at ZDI then I’d suggest looking at the vendors listed in the last few months of disclosures… that’s obviously what they are paying for these days.

If you want to start with something simple but still fun, I’d suggest grabbing a demo SCADA app. NOTE: Please be responsible.

For this blog post I’m going to use: “IRC5 OPC Server_5.12.01.exe” but Before we run the installer, lets fire up TCPView and check out our current open ports…




Ok, let’s get this installed…














We will look for new open ports in TCPView…




Based on what TCPView is telling us, it looks like this application listens on UDP ports 1308, 5512 and 5513.


Lets fire up wireshark to see if the application is chatty




So it sends packets out from TCP 5513 to a UDP subnet broadcast IP of 10.7.0.255 at port 5512. After observing the application idle for 5 minutes I identified two slightly different packets:


4e65747363616e3b30643b353b
4e65747363616e3b30643b373b


As you can see in the wireshark screenshot, this is an ascii, plain text representation of those two packets:


Netscan;0d;5;
Netscan;0d;7;


It starts with the string Netscan, followed by a separator, followed by what looks to be an ascii representation of a hex number, followed by a separator, followed by a decimal number and ending in a separator. This is going to be fun to fuzz later but what other attack surfaces can we find? Lets take a closer look at the application itself.







I tried changing poll rate, language, and users/password settings but the broadcast packet stayed the same. I’m going to go fuzz this with Sulley, would you like to come along? Don’t have Sully installed? We have an page for that too!

Posted By: jRichards
Last Edit: 02 Feb 2010 @ 10:00 PM

EmailPermalinkComments (0)
Tags

 Last 50 Posts
 Back
Change Theme...
  • Users » 52
  • Posts/Pages » 28
  • Comments » 13
Change Theme...
  • VoidVoid « Default
  • LifeLife
  • EarthEarth
  • WindWind
  • WaterWater
  • FireFire
  • LightLight

About



    No Child Pages.

Vulns



    No Child Pages.

Tools



    No Child Pages.

PaiMei



    No Child Pages.

PGP Key



    No Child Pages.