Protostar net3 write-up

net3

#include "../common/common.c"

#define NAME "net3"
#define UID 996
#define GID 996
#define PORT 2996

/*
 * Extract a null terminated string from the buffer
 */

int get_string(char **result, unsigned char *buffer, u_int16_t len)  
{
  unsigned char byte;

  byte = *buffer;

  if(byte > len) errx(1, "badly formed packet");
  *result = malloc(byte);
  strcpy(*result, buffer + 1);

  return byte + 1;
}

/*
 * Check to see if we can log into the host
 */

int login(unsigned char *buffer, u_int16_t len)  
{
  char *resource, *username, *password;
  int deduct;
  int success;

  if(len < 3) errx(1, "invalid login packet length");

  resource = username = password = NULL;

  deduct = get_string(&amp;resource, buffer, len);
  deduct += get_string(&amp;username, buffer+deduct, len-deduct);
  deduct += get_string(&amp;password, buffer+deduct, len-deduct);

  success = 0;
  success |= strcmp(resource, "net3");
  success |= strcmp(username, "awesomesauce");
  success |= strcmp(password, "password");

  free(resource);
  free(username);
  free(password);

  return ! success;
}

void send_string(int fd, unsigned char byte, char *string)  
{
  struct iovec v[3];
  u_int16_t len;
  int expected;

  len = ntohs(1 + strlen(string));

  v[0].iov_base = &len;
  v[0].iov_len = sizeof(len);

  v[1].iov_base = &byte;
  v[1].iov_len = 1;

  v[2].iov_base = string;
  v[2].iov_len = strlen(string);

  expected = sizeof(len) + 1 + strlen(string);

  if(writev(fd, v, 3) != expected) errx(1, "failed to write correct amount of bytes");

}

void run(int fd)  
{
  u_int16_t len;
  unsigned char *buffer;
  int loggedin;

  while(1) {
    nread(fd, &amp;len, sizeof(len));
    len = ntohs(len);
    buffer = malloc(len);

    if(! buffer) errx(1, "malloc failure for %d bytes", len);

    nread(fd, buffer, len);

    switch(buffer[0]) {
      case 23:
        loggedin = login(buffer + 1, len - 1);
        send_string(fd, 33, loggedin ? "successful" : "failed");
        break;

      default:
        send_string(fd, 58, "what you talkin about willis?");
        break;
    }
  }
}

int main(int argc, char **argv, char **envp)  
{
  int fd;
  char *username;

  /* Run the process as a daemon */
  background_process(NAME, UID, GID);

  /* Wait for socket activity and return */
  fd = serve_forever(PORT);

  /* Set the client socket to STDIN, STDOUT, and STDERR */
  set_io(fd);

  /* Don't do this :> */
  srandom(time(NULL));

  run(fd);
}

对源码进行分析,在run()函数中,首先接收一个len长度,表示接下来的缓冲区buffer大小,然后接收buffer内容,其中要求buffer[0] = 23 = 0x17,然后调用login()函数,根据deduct 表示的长度值来将buffer内容切片,分解为三个字符串

net3 / awesomesauce / password

而deduct值相当于字符串前缀表示的就是该段字符串的长度,后边再加上一个\x00结束符

据此构造处buffer内容为

buf = “\x17” + “\x05net3\x00” + “\x0dawesomesauce\x00” + “\x08password”

根据分析编写python脚本net3.py

from socket import *
from struct import *

s = socket(AF_INET, SOCK_STREAM)
s.connect(("localhost", 2996))

# Send the buf string
buf = "\x17" + "\x05net3\x00" + "\x0dawesomesauce\x00" + "\x08password"

# Send the buf length as unsigned short (H) and network byte order (!)
s.send(pack("!H", len(buf)))
s.send(buf)

print(s.recv(1024))
s.close()

执行成功

您可能还喜欢...