Right now only cyborg user can write to the file spirit.txt , but let’s see what will happen after running the shellcode.
Ahh! As you can see now cyborg-cyborg group-other have the permission of read-write. Which means now anyone other than cyborg user can read the content of the file too. Let’s open it in GDB and analyze it.
Let’s put the breakpoint on the call instruction. Because it is the one which will call our shellcode.
Now we can run the program using “r” or “run” command.
Alright! Now lets use “stepi” gdb command which is responsible for step into the next machine instruction. Now after it we must be inside but which holds our shellcode.
If you have read my previous articles or know ASM already then you might understand that int 0x80 is responsible for the interrupt call and passes the control to the kernel. Now we are just going to break the first “int 0x80” address and before making the call we will just check the register value from which we can simply analyze.
It is 15, now we can see in the syscall list what is the value of 15.
Alright so it is nothing but the _NR_chmod, now we must read the man 2 page of chmod.
Okay! So the chmod function takes two arguments, where the first argument is the file name/path and the second argument is for the mode.
It is 438, This is octal for 666. Now all of this make sense, isn’t?
I compiled it using gcc
gcc -fno-stack-protector -z execstack shellcode_read_file.c -o shellcode_read_file
Let’s open it in GDB and analyze it.
Let’s put the breakpoint on the call instruction. Because it is the one which will call our shellcode.
Now we can run the program using “r” or “run” command. After it just use “stepi” gdb command which is responsible for step into the next machine instruction. Then after it we must be inside buf which holds our shellcode.
So this tie we have total of four “int 0x80” instruction. Let’s put a breakpoint on each one of it.
Also if you are lazy, you can use gdb command “rununtil int” , then it will run until it see the int instruction. But I am good to go with the breakpoint.
[
Note:If you have read my previous articles or know ASM already then you might understand that int 0x80 is responsible for the interrupt call and passes the control to the kernel. Now we are just going to break the first “int 0x80” address and before making the call we will just check the register value from which we can simply analyze.]
Let’s continue the program and check the register value.
So currently:
- The value of EAX is 0x5 which is nothing but 5 in decimal.
- The value of EBX is the pointer to “spirit.txt” string.
Now we can see in the syscall list what is the value of 5.
Alright so it is nothing but the _NR_open, now we must read the man 2 page of open.
Okay! So the open function generally takes two arguments, where the first argument is the path name and the second argument is for the flags. Now all of this make sense, isn’t?
The spirit.txt inside EBX which is the first argument. Now time to analyze the next int 0x80 instruction. By typing “c” or “continue” which will continue the program.
So currently:
- The value of EAX is 0x3 which is nothing but 3 in decimal.
- The value of EBX is 0x3.
- The value of ECX point to address 0xbfffefcc which holds the buffer.
- The value of EDX is 0x1000.
Let’s see the value of 0x1000 in decimal.
Now we can see in the syscall list what is the value of 3.
Alright so it is nothing but the _NR_read, now we must read the man 2 page of read.
Okay! So the read function takes three arguments, where the first argument is the file descriptor, the second argument holds the value of buffer and the third argument holds the value of the size of the buffer. Now all of this makes sense, isn’t?
Now time to analyze the next int 0x80 instruction. By typing “c” or “continue” which will continue the program.
So currently:
- The value of EAX is 0x4 which is nothing but 4 in decimal.
- The value of EBX is 0x1.
- The value of ECX point to address 0xbfffefcc which holds the buffer.
- The value of EDX is 0x16
Let’s see the value of 0x16 in decimal
Now we can see in the syscall list what is the value of 4.
Alright so it is nothing but the _NR_write, now we must read the man 2 page of write.
Okay! So the read function takes three arguments, where the first argument is the file descriptor, the second argument holds the value of buffer and the third argument holds the value of the size of the buffer. Now all of this makes sense, isn’t?
As EBX value is 0x1 which is stdout, ECX value contains the buffer inside spirit.txt file and EDX is 0x22 which is 22 in decimal, which is the total length of the buffer.
That is actually how we really do it in any other programming language. If you have coded previously in python etc. then you might know we first open the file with a different mode. Lets say read mode then we read the file content and print it out which is nothing but the write func().
Also, the next int 0x80 for nothing but just the syscall for the exit. Because the shellcode should exit gracefully haha.
Lets run the shellcode
Analyzing Linux/x86/shell_reverse_tcp Shellcode
It has three basic options.
- CMD which tells what command to execute once the connection will establish.
- LHOST which is nothing but the listener IP address.
- LPORT which holds the value of port number on which the attacker is currently listening.
Let’s generate the shellcode
Here is my c code
I compiled it using gcc
gcc -fno-stack-protector -z execstack shellcode_reverse_tcp.c -o shellcode_reverse
Let’s open it in GDB and analyze it.
Let’s put the breakpoint on the call instruction. Because it is the one which will call our shellcode.
Now we can run the program using “r” or “run” command. After it just use “stepi” gdb command which is responsible for step into the next machine instruction. Then after it we must be inside buf which holds our shellcode.
So this tie we have total of four “int 0x80” instruction. Let’s put a breakpoint on each one of it.
Also if you are lazy, you can use gdb command “rununtil int” , then it will run until it see the int instruction. But I am good to go with the breakpoint.
[
Note:If you have read my previous articles or know ASM already then you might understand that int 0x80 is responsible for the interrupt call and passes the control to the kernel. Now we are just going to break the first “int 0x80” address and before making the call we will just check the register value from which we can simply analyze.]
Let’s continue the program and check the register value.
So currently:
- The value of EAX is 0x66.
- The value of EBX is 0x1 which is 1 in decimal.
- The value of ECX is 0xbfffefc0 which point to 0x2
Let us first check what is the value of 0x66 in decimal.
Alright! It is 102, Now we can see in the syscall list what is the value of 102.
Alright so it is nothing but the _NR_socketcall, now we must read the man 2 page of socketcall.
Okay! So the socketcall function generally takes two arguments, where the first argument is the call number. Also again I have already discussed all of this in my previous blog posts. But these call number are the /usr/include/linux/net.h call number for socketcall.
Right now the EBX is 0x1. So currently, the SYS_SOCKET is being called. Now after this instruction there will be a loop.
So in this the loop will keep running till the ECX value became -1. Once ECX will be -1 the SIGN flag will get set which will send the control to next instruction and get out of the loop.
So currently:
- The value of EAX is 0x3f.
- The value of EBX is 0x3 which is 3 in decimal.
- The value of ECX is 0x2 which is 2 in decimal.
Lets check what 0x3f is in decimal
It is 63, Now we can see in the syscall list what is the value of 63.
So this is syscall for dup2, lets check its man 2 page.
We can see the dup2 generally takes two arguments where the first one is old file descriptor and the second one is for the new file descriptor. To know more just read the description. This will run 3 times ,
- 0-->Standard Input-->STDIN_FILENO-->stdin
- 1-->Standard Output-->STDOUT_FILENO-->stdout
- 2-->Standard Error-->STDERR_FILENO-->stderr
Now once we get out of the loop.
It pushes the IP address and port on the stack and points it to ECX. So ECX will be the pointer that holds the value of IP address and port.
Now time to analyze the next int 0x80 instruction. By typing “c” or “continue” which will continue the program.
So currently:
- The value of EAX is 0x66 which is 102 in decimal.
- The value of EBX is 0x3 which is 3 in decimal.
- The value of ECX point to address 0xbfffefb0.
Well now we know 0x66 is 102 in decimal. Now we can see in the syscall list what is the value of 102.
Okay! So the socketcall function generally takes two arguments, where the first argument is the call number. Also again I have already discussed all of this in my previous blog posts. But these call number are the /usr/include/linux/net.h call number for socketcall.
Right now the EBX is 0x3 which is 3 in decimal,
so currently, the SYS_CONNECT is being called.
And from here forward everything is similar just like Assignment 2 reverse tcp shellcode. The shell execv function which is responsible to call /bin/sh.
Let's give it a try.
Pretty easy, huh? If you still have any doubt, then please feel free to ping me on twitter [
@Pwsecspirit]
Thanks,