Wednesday, November 7, 2012

How To Check For ASLR And NX Features Of Embedded Linux System

How To Check For ASLR And NX Features Of Embedded Linux System

by cawan (cawan[at]ieee.org or chuiyewleong[at]hotmail.com)

on 7/11/2012

In exploiting embedded linux system, it is crucial to ensure ASLR and NX features are
enabled or not. If both of the features are enabled, then we need to apply ROP with
offset comparison technique in creating shellcode to work with the exploit. If any of
them is disabled, then it is much simpler to be compromised. Let's start from how to
check an embedded linux system has ASLR and NX features enabled or not first. For ASLR,
it is really simple by checking the user and kernel modules layout in memory before
and after the system reboot. Let's show with an example.

Before Reboot,

tango3[bin]# cat /proc/modules
em8xxx 935488 0 - Live 0xc01b8000 (PF)
llad 144800 1 em8xxx, Live 0xc00b0000 (P)
sigmablock 70976 3 - Live 0xc002c000 (P)
tango3[bin]# cat /proc/self/maps
00400000-004b0000 r-xp 00000000 00:01 387        /bin/busybox
004bc000-004c0000 rw-p 000ac000 00:01 387        /bin/busybox
004c0000-004c4000 rwxp 004c0000 00:00 0          [heap]
2aaa8000-2aac8000 r-xp 00000000 00:01 624        /lib/ld-2.8.so
2aac8000-2aacc000 rw-p 2aac8000 00:00 0
2aad4000-2aad8000 rw-p 0001c000 00:01 624        /lib/ld-2.8.so
2aad8000-2ab54000 r-xp 00000000 00:01 514        /lib/libm-2.8.so
2ab54000-2ab60000 ---p 0007c000 00:01 514        /lib/libm-2.8.so
2ab60000-2ab64000 rw-p 00078000 00:01 514        /lib/libm-2.8.so
2ab64000-2acac000 r-xp 00000000 00:01 630        /lib/libc-2.8.so
2acac000-2acb8000 ---p 00148000 00:01 630        /lib/libc-2.8.so
2acb8000-2acc0000 r--p 00144000 00:01 630        /lib/libc-2.8.so
2acc0000-2acc4000 rw-p 0014c000 00:01 630        /lib/libc-2.8.so
2acc4000-2acc8000 rw-p 2acc4000 00:00 0
7fb84000-7fbd8000 rwxp 7fb84000 00:00 0          [stack]

After Reboot,

tango3[bin]# cat /proc/modules
em8xxx 935488 0 - Live 0xc01b8000 (PF)
llad 144800 1 em8xxx, Live 0xc00b0000 (P)
sigmablock 70976 3 - Live 0xc002c000 (P)
tango3[bin]# cat /proc/self/maps
00400000-004b0000 r-xp 00000000 00:01 387        /bin/busybox
004bc000-004c0000 rw-p 000ac000 00:01 387        /bin/busybox
004c0000-004c4000 rwxp 004c0000 00:00 0          [heap]
2aaa8000-2aac8000 r-xp 00000000 00:01 624        /lib/ld-2.8.so
2aac8000-2aacc000 rw-p 2aac8000 00:00 0
2aad4000-2aad8000 rw-p 0001c000 00:01 624        /lib/ld-2.8.so
2aad8000-2ab54000 r-xp 00000000 00:01 514        /lib/libm-2.8.so
2ab54000-2ab60000 ---p 0007c000 00:01 514        /lib/libm-2.8.so
2ab60000-2ab64000 rw-p 00078000 00:01 514        /lib/libm-2.8.so
2ab64000-2acac000 r-xp 00000000 00:01 630        /lib/libc-2.8.so
2acac000-2acb8000 ---p 00148000 00:01 630        /lib/libc-2.8.so
2acb8000-2acc0000 r--p 00144000 00:01 630        /lib/libc-2.8.so
2acc0000-2acc4000 rw-p 0014c000 00:01 630        /lib/libc-2.8.so
2acc4000-2acc8000 rw-p 2acc4000 00:00 0
7f7c8000-7f81c000 rwxp 7f7c8000 00:00 0          [stack]

Most of them are consistent before and after the system reboot, except the stack, but
that is not a problem from the perspective of attacking embedded linux system. So, the
system being tested has ASLR disabled. How about NX ? Regarding to this issue, we first
assume the stack should always be NX protected. So, we will put some instructions in
the stack and then redirect the program counter into it. After that, we step over those
instructions and observe the outcomes. If the outcome is positive, it means the NX is
disabled. Otherwise, if exception incurred, then it means the NX is enabled and run
properly. We will run our test on a MIPS platform with GDB. Let's say we want to create
some instructions to change register $t0 to 0xffffffff now. Well, it is

lui $t0,0xffff
ori $t0,$t0,0xffff

Please refer my previous paper "How To Convert Assembly Instruction Into Machine Code
In Any Type Of Processors Platform" to obtain the respective machine code of that 2
instructions.

Host:# echo 'lui $t0,0xffff' > temp.s && ./mips-linux-gnu-gcc -EL -c temp.s &&
./mips-linux-gnu-objdump -d temp.o | grep 0: | sed s/.*0://
    3c08ffff     lui    t0,0xffff
Host:# echo 'ori $t0,$t0,0xffff' > temp.s && ./mips-linux-gnu-gcc -EL -c temp.s &&
./mips-linux-gnu-objdump -d temp.o | grep 0: | sed s/.*0://
    3508ffff     ori    t0,t0,0xffff

Well, let us put the machine codes into the stack. We need to run a dummy program, set
a breakpoint at _main, then continue the execution, and stop at the breakpoint.

tango3[gdb]# ./gdb ./hello
GNU gdb (GDB) 7.0
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mips-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /root/cawan/mips-4.3/bin/gdb-7.0/gdb/hello...
(no debugging symbols found)...done.
Setting up the environment for debugging gdb.
Function "internal_error" not defined.
Make breakpoint pending on future shared library load? (y or [n])
[answered N; input not from terminal]
Function "info_command" not defined.
Make breakpoint pending on future shared library load? (y or [n])
[answered N; input not from terminal]
/root/cawan/mips-4.3/bin/gdb-7.0/gdb/.gdbinit:8: Error in sourced command file:
No breakpoint number 0.
(gdb) break main
Breakpoint 1 at 0x400620
(gdb) run
Starting program: /root/cawan/mips-4.3/bin/gdb-7.0/gdb/hello

Breakpoint 1, 0x00400620 in main ()
(gdb)

Good, we are at the point. Let's check the register info.

(gdb) info reg
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 fffffff8 7ff5ba68 2aac8a70 00000001 7ff5bb24 7ff5bb2c 00000000
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   2ac372f4 0ffffffe 00000002 7ff5ba20 ffffffff 7ff5b978 2aab1b84 f0000000
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  00400658 004004f0 004cece8 004ced40 00412580 004cece8 004ceda0 004cedb0
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000000 00400610 00000000 00000000 2ac3d950 7ff5ba30 7ff5ba30 2aaee948
        status       lo       hi badvaddr    cause       pc
      00001c13 00005e17 000001a5 2ab065d0 50808024 00400620
          fcsr      fir  restart
      00000000 01739300 00000000
(gdb)

Nice, $t0=2ac372f4, $sp=7ff5ba30, $pc=00400620

Let's check the content of stack.

(gdb) x/16x $sp
0x7ff5ba30:     0x7ff5bb24      0x00400658      0x004004f0      0x004cece8
0x7ff5ba40:     0x2ac3d950      0x00412580      0x00000000      0x2aaee948
0x7ff5ba50:     0x00000000      0x00000001      0x7ff5bb24      0x2aaee7fc
0x7ff5ba60:     0x2ac3d950      0x00000000      0x2aaee908      0x7ff5ba50
(gdb)

Let's change it with our instructions.

(00000000) nop
(00000000) nop
(3c08ffff) lui $t0,0xffff
(3508ffff) ori $t0,$t0,0xffff
(00000000) nop
(00000000) nop

(gdb) set *0x7ff5ba30 = 0x00000000
(gdb) set *(0x7ff5ba30+4) = 0x00000000
(gdb) set *(0x7ff5ba30+8) = 0x3c08ffff 
(gdb) set *(0x7ff5ba30+12) = 0x3508ffff
(gdb) set *(0x7ff5ba30+16) = 0x00000000
(gdb) set *(0x7ff5ba30+20) = 0x00000000
(gdb) x/16x $sp                       
0x7ff5ba30:     0x00000000      0x00000000      0x3c08ffff      0x3508ffff
0x7ff5ba40:     0x00000000      0x00000000      0x00000000      0x2aaee948
0x7ff5ba50:     0x00000000      0x00000001      0x7ff5bb24      0x2aaee7fc
0x7ff5ba60:     0x2ac3d950      0x00000000      0x2aaee908      0x7ff5ba50
(gdb) x/16i $pc
0x7ff5ba30:     nop
0x7ff5ba34:     nop
0x7ff5ba38:     lui     t0,0xffff
0x7ff5ba3c:     ori     t0,t0,0xffff
0x7ff5ba40:     nop
0x7ff5ba44:     nop
0x7ff5ba48:     nop
0x7ff5ba4c:     slti    t6,s5,-5816
0x7ff5ba50:     nop
0x7ff5ba54:     movf    zero,zero,$fcc0
0x7ff5ba58:     0x7ff5bb24
0x7ff5ba5c:     slti    t6,s5,-6148
0x7ff5ba60:     slti    v1,s6,-9904
0x7ff5ba64:     nop
0x7ff5ba68:     slti    t6,s5,-5880
0x7ff5ba6c:     subu.ph s7,ra,s5
(gdb) 


Fine, the content of stack has been changed to our instructions. Now, let us
redirect our program counter to the stack.

(gdb) set $pc = $sp
warning: GDB can't find the start of the function at 0x7ff5ba30.
(gdb) info reg
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 fffffff8 7ff5ba68 2aac8a70 00000001 7ff5bb24 7ff5bb2c 00000000
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   2ac372f4 0ffffffe 00000002 7ff5ba20 ffffffff 7ff5b978 2aab1b84 f0000000
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  00400658 004004f0 004cece8 004ced40 00412580 004cece8 004ceda0 004cedb0
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000000 00400610 00000000 00000000 2ac3d950 7ff5ba30 7ff5ba30 2aaee948
        status       lo       hi badvaddr    cause       pc
      00001c13 00005e17 000001a5 2ab065d0 50808024 7ff5ba30
          fcsr      fir  restart
      00000000 01739300 00000000
(gdb)

Well, the program counter is already at the stack, and the $t0 register is 2ac372f4 now.
Let us step over those instructions, and we suppose once the program counter arrived at
the 5th instruction, register $t0 should be changed into 0xffffffff. Let's see.

(gdb) ni
warning: GDB can't find the start of the function at 0x7ff5ba34.
0x7ff5ba34 in ?? ()
(gdb) ni
warning: GDB can't find the start of the function at 0x7ff5ba38.
0x7ff5ba38 in ?? ()
(gdb) ni
warning: GDB can't find the start of the function at 0x7ff5ba3c.
0x7ff5ba3c in ?? ()
(gdb) ni
warning: GDB can't find the start of the function at 0x7ff5ba40.
0x7ff5ba40 in ?? ()
(gdb) ni
warning: GDB can't find the start of the function at 0x7ff5ba44.
0x7ff5ba44 in ?? ()
(gdb) info reg
          zero       at       v0       v1       a0       a1       a2       a3
 R0   00000000 fffffff8 7ff5ba68 2aac8a70 00000001 7ff5bb24 7ff5bb2c 00000000
            t0       t1       t2       t3       t4       t5       t6       t7
 R8   ffffffff 0ffffffe 00000002 7ff5ba20 ffffffff 7ff5b978 2aab1b84 f0000000
            s0       s1       s2       s3       s4       s5       s6       s7
 R16  00400658 004004f0 004cece8 004ced40 00412580 004cece8 004ceda0 004cedb0
            t8       t9       k0       k1       gp       sp       s8       ra
 R24  00000000 00400610 00000000 00000000 2ac3d950 7ff5ba30 7ff5ba30 2aaee948
        status       lo       hi badvaddr    cause       pc
      00001c13 00005e17 000001a5 2ab065d0 50808024 7ff5ba44
          fcsr      fir  restart
      00000000 01739300 00000000
(gdb)

Awesome, the register $t0 has eventually changed to 0xffffffff. So, the MIPS platform
under test has NX disabled. In other words, it is easy to design shellcode to work with
appropriate exploit in attacking this platform.


pdf version:

http://www.scribd.com/doc/112540003/How-to-Check-for-ASLR-and-NX-Features-of-Embedded-Linux-System-1

No comments:

Post a Comment