=================================== Lec08: Socket Programming in Python =================================== In this tutorial, we are going to learn about the basic socket programming in Python and techniques required for remote exploitation. 1. 'nc' command =============== The netcat command (shortly nc) is similar to the cat command, but for networking. The old-good-day nc (called ncat in today's distribution) is much versatile (check it out if you want). Here is simple demonstration of how to use nc: (console 1) $ nc -l 1234 (listen on the 1234 port) (console 2) $ nc localhost 1234 Try to type "hello" in the console 2: (console 2) $ nc localhost 1234 hello (console 1) $ nc -l 1234 hello ----- Did you "hello" in the console 1? What about typing "world" in the console 2? You just created a nice chat program! 2. Rock, Paper, Scissor ======================= Today's goal is to win rock-paper-scissors against the computer! $ make $ ./target 1234 In another console, try to connect to the target server: $ nc -l localhost 1234 Let's play rock, paper, scissor! Your name> Do you want to explore the program a bit? $ nc localhost 1234 Let's play rock, paper, scissor! Your name> cs6265 Your turn> rock You lose! Game over You have to win 5 times in straight to win the game, which means it's not TOO bad for brute forcing. 2.1. Socket Programming in Python --------------------------------- This code snippet opens a socket (on the 1234 port) and read/write to it: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("localhost", 1234)) s.send(s.recv(10)) s.close() We provide a template code to help you in writing a socket client code in python. (console 1) $ ./target (console 2) $ ./exploit.py Your first task is to understand the template and write a code that brute forces the target server! ~~~~~~~~~~~~ e.g., any chance to win by having "rock" x 5 (or more) times? You have a pretty high chance of winning (1/3^5 = 1/243!). 2.2. Timing Attack against the Remote Server! --------------------------------------------- Brute forcing is dumb, so be smart in exploitation. This is the most interesting code in target.c: ---------------------------------------------------------------------- void start(int fd) { write(fd, "Let's play rock, paper, scissors!\nYour name> ", 44); char name[0x200]; if (read_line(fd, name, sizeof(name) - 1) <= 0) { return; } srand(*(unsigned int*)name + time(NULL)); int iter; for (iter = 0; iter < 5; iter ++) { write(fd, "Your turn> ", 11); char input[10]; if (read_line(fd, input, sizeof(input) - 1) <= 0) { return; } int yours = convert_to_int(input); if (yours == -1) { write(fd, "Not recognized! You lost!\n", 26); return; } int r = rand(); int result = yours - r % 3; if (result == 0) { write(fd, "Tie, try again!\n", 16); iter --; continue; } if (result == 1 || result == -2) { write(fd, "You win! try again!\n", 20); } else { write(fd, "You lose! Game over\n", 20); return; } } write(fd, "YOU WIN!\n", 9); dump_flag(fd); } ---------------------------------------------------------------------- Did you notice the use of srand + name as a seed for the game? srand(*(unsigned int*)name + time(NULL)); Since the name variable is what you've provided and the time is predictable, you can abuse this information to win the match all the time! (dreaming of winning jackpots all the time ..) There are two things you need to know in Python. 1) Invoking a C function ref. https://docs.python.org/2/library/ctypes.html ---------------------------------------------------------------------- from ctypes import * # how to invoke a c function in Python libc = cdll.LoadLibrary("libc.so.6") libc.printf("hello world!\n") ---------------------------------------------------------------------- This is how you invoke a 'printf' function in Python. How to invoke srand()/rand()? 2) Packing To cast a c string to an unsigned int, you need to know how to 'unpack' in Python (i.e., unpacking a string to get an unsigned int). ref. https://docs.python.org/2/library/struct.html ---------------------------------------------------------------------- struct.unpack("