Reputation: 1
I'm implementing a C++ custom port scanner using raw sockets and I'm facing a problem in my class NetScanner::StartReceive. I traced down the problem to the async_receive method where it never actually receives a response from destination address being scanned. Here's the code:
#include <iostream>
#include <ostream>
#include <istream>
#include <chrono>
#include <functional>
#include <netinet/ip.h>
#include "NetScanner.hpp"
#include "NetUtils.hpp"
#include "../error_handler/ErrorHandler.hpp"
using std::placeholders::_1;
[...]
void NetScanner::HandleReceive(const boost::system::error_code &error, std::size_t len, ScanInfo scan_info, shared_buffer buffer, shared_timer timer) {
// Checks if the receive operation was aborted due to a timeout.
if (error == boost::asio::error::operation_aborted) {
if (timeout_port_.find(scan_info.port) == timeout_port_.end()) {
StartReceive(scan_info, timer);
} else {
PopulatePortInfo(scan_info.port, port_status::FILTERED);
}
return;
} else if (error) { // Checks if an error occurred during the receive operation.
(error_handler_.*&error_handler::ErrorHandler::HandleError)(error.message());
PopulatePortInfo(scan_info.port, port_status::ABORTED);
} else { // Processes the received data.
buffer->commit(len);
utils::TCPHeader header;
std::istream stream(&(*buffer));
stream >> header;
if (header.Syn() && header.Ack()) {
port_info_[header.Source()] = port_status::OPEN;
} else if (header.Rst() && header.Ack()) {
port_info_[header.Source()] = port_status::CLOSED;
} else {
StartReceive(scan_info, timer);
return;
}
}
timer->cancel();
}
void NetScanner::HandleScan(const boost::system::error_code &error, std::size_t len, ScanInfo scan_info, shared_buffer buffer) {
if (error) {
(error_handler_.*&error_handler::ErrorHandler::HandleError)(error.message());
} else {
shared_timer timer = std::make_shared<basic_timer>(io_context_);
std::cout << "Starting timer.." << std::endl;
StartTimer(timeout_miliseconds_, scan_info, timer);
StartReceive(scan_info, timer);
}
}
void NetScanner::StartReceive(ScanInfo scan_info, shared_timer timer) {
auto &&buffer = std::make_shared<stream_buffer>();
socket_.async_receive(
buffer->prepare(buffer_size),
std::bind(&NetScanner::HandleReceive, this, _1, _2, scan_info, buffer, timer)
);
}
void NetScanner::StartTimer(int milliseconds, ScanInfo scan_info, shared_timer timer) {
timer->expires_from_now(std::chrono::milliseconds(milliseconds));
timer->async_wait(std::bind(&NetScanner::Timeout, this, _1, scan_info, timer));
[...]
When I try to scan any port, it will return me as filtered (even though it is open) because it hits this line of code in the HandleReceive method.
if (error == boost::asio::error::operation_aborted) {
if (timeout_port_.find(scan_info.port) == timeout_port_.end()) {
Meaning the async_receive got no buffer from the port being scanned back in the timeframe of the timeout value.
You can check the full code at https://github.com/alexbsec/parasyte/blob/master/src/network/NetScanner.cpp
I tried to increase the timeout, but even with large times the above if statement is still being triggered.
I attempted debugging it by showing what was in the buffer after the alleged async_receive and it is empty.
I also checked that the async_receive tries to receive the answer back for as long as the timeout is set, meaning the if statement above is only triggered after that.
Upvotes: 0
Views: 47