static uint8_t *decode_html(uint8_t *data, uint64_t data_length, uint64_t *out_length) { buffer_t *b = buffer_create(BO_HOST); uint64_t i = 0; while(i < data_length) { /* If the character is a '%' and we aren't at the end of the string, decode * the hex character and add it to the string. * * The typecasts to 'int' here are to fix warnings from cygwin. */ if(data[i] == '%' && (i + 2) < data_length && isxdigit((int)data[i + 1]) && isxdigit((int)data[i + 2])) { /* Add the new character to the string as a uint8_t. */ buffer_add_int8(b, hex_to_int(&data[i] + 1)); /* We consumed three digits here. */ i += 3; } else if(data[i] == '+') { /* In html encoding, a '+' is a space. */ buffer_add_int8(b, ' '); i++; } else { /* If it's not %NN or +, it's just a raw number.k */ buffer_add_int8(b, data[i]); i++; } } return buffer_create_string_and_destroy(b, out_length); }
static uint8_t *encode_html(uint8_t *data, uint64_t data_length, uint64_t *out_length) { int i; buffer_t *b = buffer_create(BO_HOST); char tmp[16]; for(i = 0; i < data_length; i++) { if(isalnum(data[i])) { /* If the character is alphanumeric, add it as-is. */ buffer_add_int8(b, data[i]); } else if(data[i] == ' ') { /* If the character is a space, add a '+'. */ buffer_add_int8(b, '+'); } else { /* Otherwise, encode it as a % followed by a hex code. */ sprintf(tmp, "%%%02x", data[i]); buffer_add_string(b, tmp); } } return buffer_create_string_and_destroy(b, out_length); }
void parse_SMB_COM_NEGOTIATE(int s, SMB_t *smb) { uint16_t choice; char dialects[256]; SMB_t *response = smb_create_response(SMB_COM_NEGOTIATE, 1, smb); choice = 0; while(buffer_can_read_ntstring(smb->data[0].buffer)) { buffer_read_next_ntstring(smb->data[0].buffer, dialects, 256); printf("Offered dialect: %s\n", dialects); choice++; } /* Parameters. */ buffer_add_int16(response->parameters[0].buffer, choice); /* Dialect index. */ buffer_add_int8(response->parameters[0].buffer, 0x03); /* Security mode. */ buffer_add_int16(response->parameters[0].buffer, 0x01); /* Max Mpx. */ buffer_add_int16(response->parameters[0].buffer, 0x01); /* Max VCs. */ buffer_add_int32(response->parameters[0].buffer, 4356); /* Buffer size. */ buffer_add_int32(response->parameters[0].buffer, 65535); /* Max raw. */ buffer_add_int32(response->parameters[0].buffer, 0); /* Session key. */ buffer_add_int32(response->parameters[0].buffer, 0x8000e3fd); /* TODO: testing. CAP_STATUS32 | CAP_NT_SMBS); Capabilities. */ buffer_add_int32(response->parameters[0].buffer, 0x8789e1f4); /* System time. */ buffer_add_int32(response->parameters[0].buffer, 0x01c8fedb); /* System time. */ buffer_add_int16(response->parameters[0].buffer, 360); /* Timezone offset. */ buffer_add_int8(response->parameters[0].buffer, 8); /* Key length. */ /* Data. */ buffer_add_bytes(response->data[0].buffer, "AAAAAAAA", 8); /* Encryption key. */ buffer_add_unicode(response->data[0].buffer, "name"); /* Server name. */ buffer_add_unicode(response->data[0].buffer, "domain"); /* Server domain. */ smb_send(response, s, -1, NULL); /* TODO: Fix. */ }
/* Note: This function isn't tested, so be careful about messing around! */ static uint8_t *encode_fancy(uint8_t *data, uint64_t data_length, uint64_t *out_length) { uint64_t i, j; buffer_t *b = buffer_create(BO_HOST); char tmp[64]; for(i = 0; i < data_length; i++) { if((i % 16) == 0) /* if i is a multiple of 16... */ { if(i > 0) { sprintf(tmp, " "); buffer_add_string(b, tmp); for(j = 16; j > 0; j--) buffer_add_int8(b, get_character_from_byte(data[i - j])); } sprintf(tmp, "\n%04X: ", (uint16_t)i); buffer_add_string(b, tmp); } sprintf(tmp, "%02X ", data[i]); buffer_add_string(b, tmp); } if((i % 16) == 0) { sprintf(tmp, " "); buffer_add_string(b, tmp); for(j = 16; j > 0; j--) buffer_add_int8(b, get_character_from_byte(data[i - j])); } else { /* Add padding spaces. */ for(i = data_length % 16; i < 17; i++) buffer_add_string(b, " "); for(i = data_length - (data_length % 16); i < data_length; i++) buffer_add_int8(b, get_character_from_byte(data[i])); } sprintf(tmp, "\nLength: 0x%"PRIX64" (%"PRId64")\n", data_length, data_length); buffer_add_string(b, tmp); /* Null terminate the buffer. */ buffer_add_int8(b, 0); return buffer_create_string_and_destroy(b, out_length); }
static uint8_t *decode_hex(uint8_t *data, uint64_t data_length, uint64_t *out_length) { buffer_t *b = buffer_create(BO_HOST); uint64_t i = 0; /* If we wind up with an odd number of characters, the final character is * ignored. */ while(i + 1 < data_length) { /* Skip over and ignore non-hex digits. */ if(!isxdigit(data[i]) || !isxdigit(data[i+1])) { i++; continue; } /* Add the new character to the string as a uint8_t. */ buffer_add_int8(b, hex_to_int(&data[i])); /* We consumed three digits here. */ i += 2; } return buffer_create_string_and_destroy(b, out_length); }
uint8_t *packet_to_bytes(packet_t *packet, size_t *length, options_t options) { buffer_t *buffer = buffer_create(BO_BIG_ENDIAN); buffer_add_int16(buffer, packet->packet_id); buffer_add_int8(buffer, packet->packet_type); buffer_add_int16(buffer, packet->session_id); switch(packet->packet_type) { case PACKET_TYPE_SYN: buffer_add_int16(buffer, packet->body.syn.seq); buffer_add_int16(buffer, packet->body.syn.options); if(packet->body.syn.options & OPT_NAME) { buffer_add_ntstring(buffer, packet->body.syn.name); } if(packet->body.syn.options & OPT_DOWNLOAD) { buffer_add_ntstring(buffer, packet->body.syn.filename); } break; case PACKET_TYPE_MSG: if(options & OPT_CHUNKED_DOWNLOAD) { buffer_add_int32(buffer, packet->body.msg.options.chunked.chunk); } else { buffer_add_int16(buffer, packet->body.msg.options.normal.seq); buffer_add_int16(buffer, packet->body.msg.options.normal.ack); } buffer_add_bytes(buffer, packet->body.msg.data, packet->body.msg.data_length); break; case PACKET_TYPE_FIN: buffer_add_ntstring(buffer, packet->body.fin.reason); break; case PACKET_TYPE_PING: buffer_add_ntstring(buffer, packet->body.ping.data); break; default: LOG_FATAL("Error: Unknown message type: %u\n", packet->packet_type); exit(1); } return buffer_create_string_and_destroy(buffer, length); }
static uint8_t *buffer_decode_hex(uint8_t *str, size_t *length) { size_t i = 0; buffer_t *out = buffer_create(BO_BIG_ENDIAN); /*printf("Decoding: %s (%zu bytes)...\n", str, *length);*/ while(i < *length) { uint8_t c1 = 0; uint8_t c2 = 0; /* Read the first character, ignoring periods */ do { c1 = toupper(str[i++]); } while(c1 == '.' && i < *length); /* Make sure we aren't at the end of the buffer. */ if(i >= *length) { LOG_ERROR("Couldn't hex-decode the name (name was an odd length): %s", str); return NULL; } /* Make sure we got a hex digit */ if(!isxdigit(c1)) { LOG_ERROR("Couldn't hex-decode the name (contains non-hex characters): %s", str); return NULL; } /* Read the second character. */ do { c2 = toupper(str[i++]); } while(c2 == '.' && i < *length); /* Make sure we got a hex digit */ if(!isxdigit(c2)) { LOG_ERROR("Couldn't hex-decode the name (contains non-hex characters): %s", str); return NULL; } c1 = ((c1 < 'A') ? (c1 - '0') : (c1 - 'A' + 10)); c2 = ((c2 < 'A') ? (c2 - '0') : (c2 - 'A' + 10)); buffer_add_int8(out, (c1 << 4) | c2); } return buffer_create_string_and_destroy(out, length); }
/* Read data from the session that will be sent out across the network. This * will return up to read_length bytes (and will return the number of bytes * read in read_length as well). The memory returned has to be freed. * * If the session isn't found, NULL is returned. If no data is waiting, the * empty string is returned and read_length is set to 0. */ uint8_t *session_read(sessions_t *sessions, char *session_name, uint32_t *read_length) { uint32_t i = 0; buffer_t *incoming; buffer_t *response; session_t *session; session = session_get(sessions, session_name); if(!session) return NULL; if(session_is_closed(sessions, session_name)) return NULL; if(buffer_can_read_int8(sessions->buffer_data)) { incoming = sessions->buffer_data; } else { if(!session) return NULL; incoming = session->buffer; } response = buffer_create(BO_NETWORK); while(buffer_can_read_int8(incoming) && i < *read_length) { if(sessions->log) fputc(buffer_peek_next_int8(incoming), sessions->log); buffer_add_int8(response, buffer_read_next_int8(incoming)); i++; } /* Clear whichever buffer we're using if we're at the end. */ if(!buffer_can_read_int8(incoming)) buffer_clear(incoming); return buffer_create_string_and_destroy(response, read_length); }
static uint8_t *encode_cstr(uint8_t *data, uint64_t data_length, uint64_t *out_length) { int i; buffer_t *b = buffer_create(BO_HOST); char tmp[16]; for(i = 0; i < data_length; i++) { if(isalnum(data[i])) { /* Add letters/numbers as-is. */ buffer_add_int8(b, data[i]); } else { /* Encode all other characters as "\xNN". */ sprintf(tmp, "\\x%02x", data[i]); buffer_add_string(b, tmp); } } return buffer_create_string_and_destroy(b, out_length); }
/* This function expects to receive the proper length of data. */ static void handle_packet_out(driver_dns_t *driver, uint8_t *data, size_t length) { size_t i; dns_t *dns; buffer_t *buffer; uint8_t *encoded_bytes; size_t encoded_length; uint8_t *dns_bytes; size_t dns_length; size_t section_length; assert(driver->s != -1); /* Make sure we have a valid socket. */ assert(data); /* Make sure they aren't trying to send NULL. */ assert(length > 0); /* Make sure they aren't trying to send 0 bytes. */ assert(length <= MAX_DNSCAT_LENGTH(driver->domain)); buffer = buffer_create(BO_BIG_ENDIAN); /* If no domain is set, add the wildcard prefix at the start. */ if(!driver->domain) { buffer_add_bytes(buffer, (uint8_t*)WILDCARD_PREFIX, strlen(WILDCARD_PREFIX)); buffer_add_int8(buffer, '.'); } section_length = 0; /* TODO: I don't much care for this loop... */ for(i = 0; i < length; i++) { char hex_buf[3]; #ifdef WIN32 sprintf_s(hex_buf, 3, "%02x", data[i]); #else sprintf(hex_buf, "%02x", data[i]); #endif buffer_add_bytes(buffer, hex_buf, 2); /* Add periods when we need them. */ section_length += 2; if(i + 1 != length && section_length + 2 >= MAX_FIELD_LENGTH) { section_length = 0; buffer_add_int8(buffer, '.'); } } /* If a domain is set, instead of the wildcard prefix, add the domain to the end. */ if(driver->domain) { buffer_add_int8(buffer, '.'); buffer_add_bytes(buffer, driver->domain, strlen(driver->domain)); } buffer_add_int8(buffer, '\0'); /* Get the result out. */ encoded_bytes = buffer_create_string_and_destroy(buffer, &encoded_length); /* Double-check we didn't mess up the length. */ assert(encoded_length <= MAX_DNS_LENGTH); dns = dns_create(_DNS_OPCODE_QUERY, _DNS_FLAG_RD, _DNS_RCODE_SUCCESS); dns_add_question(dns, (char*)encoded_bytes, driver->type, _DNS_CLASS_IN); dns_bytes = dns_to_packet(dns, &dns_length); LOG_INFO("Sending DNS query for: %s to %s:%d", encoded_bytes, driver->dns_host, driver->dns_port); udp_send(driver->s, driver->dns_host, driver->dns_port, dns_bytes, dns_length); safe_free(dns_bytes); safe_free(encoded_bytes); dns_destroy(dns); }
static uint8_t *decode_cstr(uint8_t *data, uint64_t data_length, uint64_t *out_length) { buffer_t *b = buffer_create(BO_HOST); uint64_t i = 0; uint64_t in_length = data_length; while(i < in_length) { if(data[i] == '\\') { /* Consume the slash. */ i++; /* Check for the various format specifiers - \a, \b, \t, \n, \r, etc) */ if(i < in_length && data[i] == '\\') { buffer_add_int8(b, '\\'); i++; } else if(i < in_length && data[i] == 'a') { buffer_add_int8(b, 0x07); i++; } else if(i < in_length && data[i] == 'b') { buffer_add_int8(b, 0x08); i++; } else if(i < in_length && data[i] == 't') { buffer_add_int8(b, 0x09); i++; } else if(i < in_length && data[i] == 'n') { buffer_add_int8(b, 0x0a); i++; } else if(i < in_length && data[i] == 'v') { buffer_add_int8(b, 0x0b); i++; } else if(i < in_length && data[i] == 'f') { buffer_add_int8(b, 0x0c); i++; } else if(i < in_length && data[i] == 'r') { buffer_add_int8(b, 0x0d); i++; } else if(i < in_length && data[i] == 'e') { buffer_add_int8(b, 0x1b); i++; } /* Ensure the data is sane. */ else if(i + 2 < in_length && data[i] == 'x' && isxdigit((int)data[i + 1]) && isxdigit((int)data[i + 2])) { /* Add the new character to the string as a uint8_t. */ buffer_add_int8(b, hex_to_int(&data[i] + 1)); /* We consumed three digits here. */ i += 3; } else { buffer_add_int8(b, '\\'); } } else { buffer_add_int8(b, data[i]); i++; } } return buffer_create_string_and_destroy(b, out_length); }