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: SLAE64-1434
Target Operating System: 64 bit Linux (x86_64 GNU/Linux)
GitHub Link:https://github.com/rtaylor777/nasm/blob/master/BindShellPass1434.nasm
Number of bytes = 96
Number of nulls = 0
BindShellPass1434.nasm
Assemble:
nasm -felf64 BindShellPass1434.nasm -o BindShellPass1434.o
Link:
ld BindShellPass1434.o -o BindShellPass1434
Run:
./BindShellPass1434
If you run netstat (in another terminal) you can see your new service listening on port 4444:
Connecting a client, from a different terminal, entering the password and interacting with the shell:
Once you exit the /bin/sh shell on the client, BindShellPass1434 also exits on the server.
Note:
There is a default delay of one minute before Linux will allow you to bind to the same port again. So if you try to run BindShellPass1434 again before a minute has passed you will get a Segmentation Fault.
Normally what would happen is the BindShellPass1434 would have bound to another port because 4444 was not yet permitted to be used by Linux. When this happens an error code is returned in the RAX register, which if I coded my BindShellPass1434 differently, would not have caused a Segmentation Fault. But I figured since the point is we don't want our BindShellPass1434 to bind to some alternate random port anyway it might as well assume that it was successful getting port 4444.
To see more about this topic search Google for the text TIME_WAIT.
Also if you are new to Socket programming with assembly language you should start by reading my blog post:
http://a41l4.blogspot.ca/2017/02/assignment-1b.html
Visit the above link to see my previous blog post as it explains most of the code that you see in this shellcode.
I decided that it didn't make sense to repeat the explanation for the code which is identical to that which I discussed for the BindShell1434. The only difference between this code and that is this code includes the addition of a password.
I decided that a 4 character password would be adequate to protect our shellcode from someone who is unauthorized connecting and getting a /bin/sh shell. They would only get one chance before our shellcode would exit. Considering the 96 displayable characters that can be entered from the keyboard there would be 96 exponent 4 possibilities which is equal to 84,934,656.
If you would rather have an 8 character password that can be arranged easily by first moving the 8 character password into another register, such as RBX, and then subtracting that from RSI. You have to do it like that because you can't do anything with an 8 byte immediate value other than move it into a register.
Line 78 and 79 are setting up RSI to point at a buffer for our Read syscall. We are simply using the stack for the buffer as usual.
The Read syscall has a value of 0, which as it happens is already what RAX is set to from the previous Dup2 loop.
Line 82 we are making the Read syscall.
Line 83 we are popping the value read (our buffer) into RSI. We are setting RSI up to be zeroed with the next instruction.
Line 84, we subtract the immediate value "1434" which is our password from the 32 bit register ESI.
If you have been reading my previous blogs, by now you should be getting the idea that if we write to a 32 bit register, it automatically will zero the upper 32 bits of our 64 bit register. The flags are set by the result of the 32 bit subtraction, not the zeroing of the upper 32 bits of the register.
Line 85, if the result of the subtraction is anything but zero (meaning the password was correct) we jump back to the start of our shellcode. You might think that this would put us into a repeat loop that would permit another password attempt. But even if you wait for a minute after connecting before you enter a password (permitting the TIME_WAIT to be up for the 4444 socket) the shellcode will exit with a segmentation fault if you enter the wrong password. I decided that this behavior was more predictable than jumping to whatever code may exist in memory after our shellcode.
If you wish to learn more about assembly language, I highly recommend the "SecurityTube Linux Assembly Expert course and certification."
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE64-1434
Target Operating System: 64 bit Linux (x86_64 GNU/Linux)
Assignment 1a:
Create a Shell_Bind_Tcp shellcode that binds to a port but when a client connects to it, the client would need to send a passcode which is like an authentication. Only if the passcode is correct would the execshell run, if not it would just disconnect the client.GitHub Link:https://github.com/rtaylor777/nasm/blob/master/BindShellPass1434.nasm
Number of bytes = 96
Number of nulls = 0
BindShellPass1434.nasm
Intro
This shellcode, when executed, listens on port 4444 for a connection. Once a client connects to port 4444, the client is required to send a 4 character "password". If the client sends the correct password a /bin/sh shell is launched and the client can interact with it.Testing
Once you have downloaded the BindShellPass1434.nasm source code from the GitHub link above, you will need to assemble it. Assuming you have the NASM assembler ( http://www.nasm.us/ ):Assemble:
nasm -felf64 BindShellPass1434.nasm -o BindShellPass1434.o
Link:
ld BindShellPass1434.o -o BindShellPass1434
Run:
./BindShellPass1434
If you run netstat (in another terminal) you can see your new service listening on port 4444:
Once you exit the /bin/sh shell on the client, BindShellPass1434 also exits on the server.
Note:
There is a default delay of one minute before Linux will allow you to bind to the same port again. So if you try to run BindShellPass1434 again before a minute has passed you will get a Segmentation Fault.
Normally what would happen is the BindShellPass1434 would have bound to another port because 4444 was not yet permitted to be used by Linux. When this happens an error code is returned in the RAX register, which if I coded my BindShellPass1434 differently, would not have caused a Segmentation Fault. But I figured since the point is we don't want our BindShellPass1434 to bind to some alternate random port anyway it might as well assume that it was successful getting port 4444.
To see more about this topic search Google for the text TIME_WAIT.
Please See:
If you are new to shellcode or shellcoding you should start by reading my blog post: http://a41l4.blogspot.ca/2017/01/execvestack1434.htmlAlso if you are new to Socket programming with assembly language you should start by reading my blog post:
http://a41l4.blogspot.ca/2017/02/assignment-1b.html
Visit the above link to see my previous blog post as it explains most of the code that you see in this shellcode.
I decided that it didn't make sense to repeat the explanation for the code which is identical to that which I discussed for the BindShell1434. The only difference between this code and that is this code includes the addition of a password.
After Dup2
After the Dup2 section and starting at line 75 marked ;Read we begin to see our new code.I decided that a 4 character password would be adequate to protect our shellcode from someone who is unauthorized connecting and getting a /bin/sh shell. They would only get one chance before our shellcode would exit. Considering the 96 displayable characters that can be entered from the keyboard there would be 96 exponent 4 possibilities which is equal to 84,934,656.
If you would rather have an 8 character password that can be arranged easily by first moving the 8 character password into another register, such as RBX, and then subtracting that from RSI. You have to do it like that because you can't do anything with an 8 byte immediate value other than move it into a register.
Details
On line 77 we are popping 16 from the stack into rdx. 16 was still on the stack from when we did our Accept call. We only needed to set up the read call to read 4 bytes. But there is no harm in reading more, other than we want to put a stop to it while we are still working with a value for the number of bytes that fits in AL (a byte).Line 78 and 79 are setting up RSI to point at a buffer for our Read syscall. We are simply using the stack for the buffer as usual.
The Read syscall has a value of 0, which as it happens is already what RAX is set to from the previous Dup2 loop.
Line 82 we are making the Read syscall.
Line 83 we are popping the value read (our buffer) into RSI. We are setting RSI up to be zeroed with the next instruction.
Line 84, we subtract the immediate value "1434" which is our password from the 32 bit register ESI.
If you have been reading my previous blogs, by now you should be getting the idea that if we write to a 32 bit register, it automatically will zero the upper 32 bits of our 64 bit register. The flags are set by the result of the 32 bit subtraction, not the zeroing of the upper 32 bits of the register.
Line 85, if the result of the subtraction is anything but zero (meaning the password was correct) we jump back to the start of our shellcode. You might think that this would put us into a repeat loop that would permit another password attempt. But even if you wait for a minute after connecting before you enter a password (permitting the TIME_WAIT to be up for the 4444 socket) the shellcode will exit with a segmentation fault if you enter the wrong password. I decided that this behavior was more predictable than jumping to whatever code may exist in memory after our shellcode.
Execve
There are some slight changes to the Execve section. RAX is no longer zero at the start of the ExecveStack code so we zero RDX and push that for our zero terminator. We know RAX should be a value between 4 and 16 because that was the return value for our Read loop. Read returns the number of bytes read and we set up our Read call to read a maximum of 16 bytes. So the rest of the code can remain unchanged.Shellcode.c
Summary
We have successfully set up our TCP Bind Shell to require a password before launching the /bin/sh command shell. We have also managed to avoid NULLS in our code and we have kept our code size fairly small.If you wish to learn more about assembly language, I highly recommend the "SecurityTube Linux Assembly Expert course and certification."
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Comments
Post a Comment