execve with arguments
so far, i’ve only been doing simple program loading using sys_execve in shellcodes. simple in the sense that no arguments are being passed to loaded programs. unfortunately, running a program without any argument produces rather boring outputs. today, i added a bit of twist to things. i tried to implement a shellcode that chroots into a particular directory.
first, an introduction.
chroot or “change root” for that matter makes it possible for a user to run a command or interactive shell within a special ‘user defined’ directory.
of course, a little bit of preparation is required before running chroot. one needs to imitate his/her root directory. here’s how mine went.
first, i made a directory that will act as my fake root.
steph@heaven ~ $ mkdir myroot ; cd myroot
once i’m in my fake root, i’ll be using /bin/bash, /bin/ls and /bin/pwd so i also need to create a bin directory inside my fake root where bash, ls and pwd will reside.
steph@heaven ~/myroot $ mkdir bin
then i copied the bash, ls and pwd binaries into it from my ‘real’ root.
steph@heaven ~/myroot $ cp /bin/bash bin/ steph@heaven ~/myroot $ cp /bin/ls bin/ steph@heaven ~/myroot $ cp /bin/pwd bin/
things are not done yet! i still had to resolve their shared library dependencies for them to work! i first resolved /bin/bash’s dependencies.
steph@heaven ~/myroot $ ldd /bin/bash
linux-gate.so.1 => (0xffffe000)
libdl.so.2 => /lib/libdl.so.2 (0xb7f19000)
libc.so.6 => /lib/libc.so.6 (0xb7e01000)
/lib/ld-linux.so.2 (0xb7f28000)
it uses some files inside /lib! so inside my fake root, i also create a lib directory and copied the shared objects there.
steph@heaven ~/myroot $ mkdir lib steph@heaven ~/myroot $ cp /lib/libdl.so.2 lib/ steph@heaven ~/myroot $ cp /lib/libc.so.6 lib/ steph@heaven ~/myroot $ cp /lib/ld-linux.so.2 lib/
i did the same for ls and pwd. printing their shared dependencies using ldd, then copying them to their respective directories inside my fake root. after copying, i verified if everything was in place.
steph@heaven ~/myroot $ ls -l * bin: total 761 -rwxr-xr-x 1 steph users 680316 Feb 19 15:33 bash -rwxr-xr-x 1 steph users 75268 Feb 19 15:33 ls -rwxr-xr-x 1 steph users 15716 Feb 19 15:26 pwd lib: total 1301 -rwxr-xr-x 1 steph users 83620 Feb 19 15:36 ld-linux.so.2 -rwxr-xr-x 1 steph users 1228960 Feb 19 15:36 libc.so.6 -rwxr-xr-x 1 steph users 10892 Feb 19 15:36 libdl.so.2groovy! my fake root looks like a real simple root now! time to test it.
steph@heaven ~ $ chroot /home/steph/myroot /bin/bash chroot: cannot change root directory to /home/steph/myroot: Operation not permittedoopsie! i guess i better run chroot as “root”.
heaven steph # chroot /home/steph/myroot /bin/bash bash-3.00#
it worked! let’s try running some commands inside the fake root shall we?
heaven steph # chroot /home/steph/myroot /bin/bash bash-3.00# ls bin lib bash-3.00# pwd / bash-3.00# cat bash: cat: command not foundi tried running three commands inside my fake root. first was ls. and it showed the contents of my chrooted directory. next was pwd and it showed my present working directory, that happens to be “/” of my fake root. and lastly, cat. but it didn’t work. that is because i don’t have cat inside my fake root. i only copied three files and their corresponding dependencies. a good chroot directory must have all the important files or binaries for it to be productive. also, it must not contain useless files that won’t be used. in my case, it was the cat command.
lastly, i exited my chroot environment and copied the fake root folder (myroot) to where the real fun will happen. inside my git repository!
steph@heaven ~ $ cp -r myroot ~/git/null/asm/shellcoding/
it was too bad that i had to run chroot as “root”. quite creepy.
next page: the shellcode
based on the activity above, i’m supposed to run chroot as follows /usr/bin/chroot ./myroot /bin/bash. that implies that my shellcode expects to find a directory “myroot” from where i’d be running it. that’s two arguments passed to chroot! well, three if you count the path to the program also. as usual, i first tried everything on a normal assembly listing. based on which, i came up with the shellcode below.
global _start
section .text
_start:
jmp short .setup
.shellcode:
pop ebx ; ebx holds string addr
xor eax, eax ; eax = null
mov [ebx+15], al ; segregation
mov [ebx+24], al ; ditto
lea esp, [esp-16] ; room on stack
and esp, -16
mov [esp], ebx ; '/usr/bin/chroot' addr in first dword
lea ecx, [ebx+16]
mov [esp+4], ecx ; './myroot' addr in second dword
lea ecx, [ebx+25]
mov [esp+8], ecx ; '/bin/bash' addr in third dword
xor ecx, ecx ; see also xor eax, eax above
mov [esp+12], ecx ; null pad in fourth dword
mov al, 11 ; sys_execve
lea ecx, [esp] ; char *const argv[]
xor edx, edx
int 0x80 ; pray it works!
.setup:
call .shellcode
cmd db '/usr/bin/chroot ./myroot /bin/bash'
assembled, this would generate the following opcodes.
Disassembly of section .text: 080480a0 <.text>: 80480a0: eb 33 jmp 0x80480d5 80480a2: 5b pop %ebx 80480a3: 31 c0 xor %eax,%eax 80480a5: 88 43 0f mov %al,0xf(%ebx) 80480a8: 88 43 18 mov %al,0x18(%ebx) 80480ab: 8d 64 24 f0 lea 0xfffffff0(%esp),%esp 80480af: 81 e4 f0 ff ff ff and $0xfffffff0,%esp 80480b5: 89 1c 24 mov %ebx,(%esp) 80480b8: 8d 4b 10 lea 0x10(%ebx),%ecx 80480bb: 89 4c 24 04 mov %ecx,0x4(%esp) 80480bf: 8d 4b 19 lea 0x19(%ebx),%ecx 80480c2: 89 4c 24 08 mov %ecx,0x8(%esp) 80480c6: 31 c9 xor %ecx,%ecx 80480c8: 89 4c 24 0c mov %ecx,0xc(%esp) 80480cc: b0 0b mov $0xb,%al 80480ce: 8d 0c 24 lea (%esp),%ecx 80480d1: 31 d2 xor %edx,%edx 80480d3: cd 80 int $0x80 80480d5: e8 c8 ff ff ff call 0x80480a2 80480da: 2f das 80480db: 75 73 jne 0x8048150 80480dd: 72 2f jb 0x804810e 80480df: 62 69 6e bound %ebp,0x6e(%ecx) 80480e2: 2f das 80480e3: 63 68 72 arpl %bp,0x72(%eax) 80480e6: 6f outsl %ds:(%esi),(%dx) 80480e7: 6f outsl %ds:(%esi),(%dx) 80480e8: 74 20 je 0x804810a 80480ea: 2e cs 80480eb: 2f das 80480ec: 6d insl (%dx),%es:(%edi) 80480ed: 79 72 jns 0x8048161 80480ef: 6f outsl %ds:(%esi),(%dx) 80480f0: 6f outsl %ds:(%esi),(%dx) 80480f1: 74 20 je 0x8048113 80480f3: 2f das 80480f4: 62 69 6e bound %ebp,0x6e(%ecx) 80480f7: 2f das 80480f8: 62 61 73 bound %esp,0x73(%ecx) 80480fb: 68 .byte 0x68of course i still had to put those inside a string and call it from c.
char root[] = "\xeb\x33\x5b\x31\xc0\x88\x43\x0f\x88\x43\x18\x8d\x64\x24\xf0\x81\"\
\"\xe4\xf0\xff\xff\xff\x89\x1c\x24\x8d\x4b\x10\x89\x4c\x24\x04\x8d\"\
\"\x4b\x19\x89\x4c\x24\x08\x31\xc9\x89\x4c\x24\x0c\xb0\x0b\x8d\x0c\"\
\"\x24\x31\xd2\xcd\x80\xe8\xc8\xff\xff\xff\x2f\x75\x73\x72\x2f\x62\"\
\"\x69\x6e\x2f\x63\x68\x72\x6f\x6f\x74\x20\x2e\x2f\x6d\x79\x72\x6f\"\
\"\x6f\x74\x20\x2f\x62\x69\x6e\x2f\x62\x61\x73\x68";
typedef int (*fp)();
void exec(int (*fp)())
{
fp();
}
int main(int argc, char **argv)
{
exec((fp)root);
return 0;
}
and then i compiled and executed the c program that contains my chroot shellcode.
steph@heaven ~/git/null/asm/shellcoding $ su Password: heaven shellcoding # ./print_str bash-3.00# ls bin lib
well it worked. i succesfully chrooted to my fake root directory. i had lots of fun doing this and i hope i’ve entertained whoever is reading this at this moment (no one i guess). i’ll go girl hunting at friendster now. bye bye.
