Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ void usage(FILE *stream);
* @param no_host_disc Flag to skip host discovery.
* @param force_ping Flag to force ICMP.
* @param force_arp Flag to force ARP.
* @param force_syn Flag to force SYN scan.
* @param write_file Pointer to store the write_file path.
* @return int 0 on success, CLI_PARSE on error.
*/
Expand All @@ -30,6 +31,7 @@ int parse_cli(int argc,
int *no_host_disc,
int *force_ping,
int *force_arp,
int *force_syn,
char **write_file);

#endif
2 changes: 2 additions & 0 deletions include/syn_scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
* @param port_arr The array of ports to scan.
* @param count The number of ports in the array.
* @param is_open_port Whether any open ports were found.
* @param is_up Whether the host is up.
* @param result_arr Pointer to an array to store the results of the scan.
* @return `int` Returns SUCCESS on success, or an error code from `error.h` on failure.
*/
int port_scan(char *address,
unsigned short *port_arr,
int count,
short *is_open_port,
short *is_up,
unsigned short **result_arr);

/**
Expand Down
32 changes: 22 additions & 10 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ static void banner(FILE *stream)
"disco - network utility for host discovery and port enumeration\n"
"author: pilsnerfrajz\n\n");
fprintf(stream,
"usage: disco target [-h] [-p port(s)] [-o] [-n] [-P] [-a] [-w file]\n"
"usage: disco target [-h] [-p ports] [-o] [-n] [-P] [-a] [-S] [-w file]\n"
"options:\n"
" target : host to scan (IP address or domain)\n"
" -p, --ports : ports to scan, e.g., -p 1-1024 or -p 21,22,80\n"
" -o, --open : show open ports only (default: open or unknown)\n"
" -o, --open : show open ports only (default: open or filtered)\n"
" -n, --no-check : skip host status check\n"
" -P, --ping-only : force ICMP host discovery (skip ARP attempt)\n"
" -a, --arp-only : force ARP host discovery (skip ICMP fallback)\n"
" -a, --arp-only : force ARP host discovery (skip ICMP fallback)\n"
" -S, --syn-only : force SYN host discovery (skip ARP and ICMP)\n"
" -w, --write : write results to a file\n"
" -h, --help : display this message\n");
}
Expand All @@ -45,21 +46,23 @@ void usage(FILE *stream)
else
{
fprintf(stream,
"[!] usage: disco target [-h] [-p port(s)] [-o] [-n] [-P] [-a] [-w file]\n"
"[!] usage: disco target [-h] [-p ports] [-o] [-n] [-P] [-a] [-S] [-w file]\n"
" options:\n"
" target : host to scan (IP address or domain)\n"
" -p, --ports : ports to scan, e.g., -p 1-1024 or -p 21,22,80\n"
" -o, --open : show open ports only (default: open or unknown)\n"
" -o, --open : show open ports only (default: open or filtered)\n"
" -n, --no-check : skip host status check\n"
" -P, --ping-only : force ICMP host discovery (skip ARP attempt)\n"
" -a, --arp-only : force ARP host discovery (skip ICMP fallback)\n"
" -a, --arp-only : force ARP host discovery (skip ICMP fallback)\n"
" -S, --syn-only : force SYN host discovery (skip ARP and ICMP)\n"
" -w, --write : write results to a file\n"
" -h, --help : display this message\n");
}
}

int parse_cli(int argc, char *argv[], char **target, char **ports, int *show_open,
int *no_host_disc, int *force_ping, int *force_arp, char **write_file)
int *no_host_disc, int *force_ping, int *force_arp, int *force_syn,
char **write_file)
{
/* Reset optind for multiple tests to work properly*/
optind = 1;
Expand Down Expand Up @@ -97,6 +100,12 @@ int parse_cli(int argc, char *argv[], char **target, char **ports, int *show_ope
NULL,
'a',
},
{
"syn-only",
no_argument,
NULL,
'S',
},
{
"open",
no_argument,
Expand All @@ -112,7 +121,7 @@ int parse_cli(int argc, char *argv[], char **target, char **ports, int *show_ope
{0, 0, 0, 0}};

int option;
while ((option = getopt_long(argc, argv, "p:nhPaow:", options, NULL)) != -1)
while ((option = getopt_long(argc, argv, "p:nhPaSow:", options, NULL)) != -1)
{
switch (option)
{
Expand Down Expand Up @@ -167,6 +176,9 @@ int parse_cli(int argc, char *argv[], char **target, char **ports, int *show_ope
case 'a':
*force_arp = 1;
break;
case 'S':
*force_syn = 1;
break;
case 'h':
usage(stdout);
return CLI_PARSE;
Expand Down Expand Up @@ -220,9 +232,9 @@ int parse_cli(int argc, char *argv[], char **target, char **ports, int *show_ope
}
}

if (*force_arp + *force_ping + *no_host_disc > 1)
if (*force_arp + *force_ping + *force_syn + *no_host_disc > 1)
{
fprintf(stderr, "[-] Conflicting options. Only one of -P, -a and -n can be used at once\n");
fprintf(stderr, "[-] Conflicting options. Only one of -P, -a, -S and -n can be used at once\n");
usage(stderr);
return CLI_PARSE;
}
Expand Down
47 changes: 40 additions & 7 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

#define RETRIES 3
#define MSG_BUF_SIZE 2048
#define DISCOVERY_PORT_COUNT 3

static unsigned short discovery_ports[DISCOVERY_PORT_COUNT] = {22, 80, 443};

/**
* @brief Print a message to a stream and to a file if provided.
Expand Down Expand Up @@ -55,10 +58,21 @@ static int default_scan(FILE *fp, char *target)
char *msg = "[!] ARP failed, falling back to ICMP\n";
print_wrapper(stdout, fp, msg);
rv = ping(target, RETRIES);
if (rv != SUCCESS)
if (rv == SUCCESS)
{
return 0;
}

msg = "[!] Ping failed, falling back to TCP SYN\n";
print_wrapper(stdout, fp, msg);

short is_up = 0;
short is_open_port = 0;
rv = port_scan(target, discovery_ports, DISCOVERY_PORT_COUNT, &is_open_port, &is_up, NULL);
if (rv != SUCCESS || !is_up)
{
print_err(stderr, "[-] ping", rv);
print_err(fp, "[-] ping", rv);
msg = "[-] Host discovery failed. Host is down, aborting\n";
print_wrapper(stderr, fp, msg);
return NO_RESPONSE;
}

Expand Down Expand Up @@ -166,11 +180,12 @@ int main(int argc, char *argv[])
int no_host_disc = 0;
int force_ping = 0;
int force_arp = 0;
int force_syn = 0;
int show_open = 0;
int up = 0;
int rv = 0;

if (parse_cli(argc, argv, &target, &ports, &show_open, &no_host_disc, &force_ping, &force_arp, &write_file) != 0)
if (parse_cli(argc, argv, &target, &ports, &show_open, &no_host_disc, &force_ping, &force_arp, &force_syn, &write_file) != 0)
{
return CLI_PARSE;
}
Expand Down Expand Up @@ -230,7 +245,24 @@ int main(int argc, char *argv[])
up = 1;
}

if (ports == NULL && no_host_disc && !force_arp && !force_ping)
if (force_syn)
{
msg = "[!] Forcing TCP SYN host discovery (skipping ARP and ICMP)\n";
print_wrapper(stdout, fp, msg);
short is_up = 0;
short is_open_port = 0;
rv = port_scan(target, discovery_ports, DISCOVERY_PORT_COUNT, &is_open_port, &is_up, NULL);
if (rv != SUCCESS || !is_up)
{
msg = "[-] TCP SYN host discovery failed. Host is down, aborting\n";
print_wrapper(stderr, fp, msg);
rv = NO_RESPONSE;
goto cleanup;
}
up = 1;
}

if (ports == NULL && no_host_disc && !force_arp && !force_ping && !force_syn)
{
msg = "[!] Doing nothing. Use '-p' with the '-n' option!\n\n";
print_wrapper(stderr, fp, msg);
Expand All @@ -245,7 +277,7 @@ int main(int argc, char *argv[])
print_wrapper(stdout, fp, msg);
}

if (!no_host_disc && !force_arp && !force_ping)
if (!no_host_disc && !force_arp && !force_ping && !force_syn)
{
rv = default_scan(fp, target);
if (rv != 0)
Expand Down Expand Up @@ -278,8 +310,9 @@ int main(int argc, char *argv[])
print_wrapper(stdout, fp, msg_buf);
memset(msg_buf, 0, MSG_BUF_SIZE);
short is_open_port = 0;
short is_up = 0;

rv = port_scan(target, port_arr, port_count, &is_open_port, &res_arr);
rv = port_scan(target, port_arr, port_count, &is_open_port, &is_up, &res_arr);
if (rv != SUCCESS)
{
print_err(stderr, "[-] port_scan", rv);
Expand Down
8 changes: 8 additions & 0 deletions src/syn_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct callback_data
{
short loopback_flag;
short any_open; /* Flag if any open port is found */
short is_up; /* Flag if host is up */
volatile short port_status[65536];
};

Expand Down Expand Up @@ -145,6 +146,11 @@ static void tcp_process_pkt(u_char *user, const struct pcap_pkthdr *pkt_hdr,
}
}

if (tcp_hdr->flags)
{
c_data->is_up = 1;
}

if ((tcp_hdr->flags & SYN_ACK) == SYN_ACK)
{
c_data->port_status[ntohs(tcp_hdr->sport)] = OPEN;
Expand Down Expand Up @@ -857,6 +863,7 @@ int port_scan(char *address,
unsigned short *port_arr,
int port_count,
short *is_open_port,
short *is_up,
unsigned short **result_arr)
{
if (test_print)
Expand Down Expand Up @@ -1102,6 +1109,7 @@ int port_scan(char *address,
}

*is_open_port = c_data.any_open;
*is_up = c_data.is_up;

/* Save results to supplied result_arr for use in caller */
if (result_arr != NULL)
Expand Down
5 changes: 3 additions & 2 deletions tests/cli_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ void cli_test(void)
int no_host_disc = 0;
int force_ping = 0;
int force_arp = 0;
int force_syn = 0;
int show_open = 0;

char *help[] = {"program", "-h"};
Expand All @@ -78,11 +79,11 @@ void cli_test(void)
"127.0.0.1",
"::1"};

parse_cli(2, help, &target, &ports, &show_open, &no_host_disc, &force_ping, &force_arp, NULL);
parse_cli(2, help, &target, &ports, &show_open, &no_host_disc, &force_ping, &force_arp, &force_syn, NULL);

test(0, ports, 0, target, no_host_disc, force_ping, force_arp);

parse_cli(11, parse, &target, &ports, &show_open, &no_host_disc, &force_ping, &force_arp, NULL);
parse_cli(11, parse, &target, &ports, &show_open, &no_host_disc, &force_ping, &force_arp, &force_syn, NULL);

test(6, ports, 1, target, no_host_disc, force_ping, force_arp);

Expand Down
11 changes: 6 additions & 5 deletions tests/syn_scan_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,16 @@ void syn_scan_test(void)
}

short is_open = 0;
short is_up = 0;

if ((ret = port_scan("127.0.0.1", test_arr, TEST_ARR_LEN, &is_open, NULL)) == SUCCESS)
if ((ret = port_scan("127.0.0.1", test_arr, TEST_ARR_LEN, &is_open, &is_up, NULL)) == SUCCESS)
printf("└ ✅ Localhost IPv4 Port scan test: Passed\n");
else
{
print_err(stderr, "└ ❌ Localhost IPv4 Port scan test failed", ret);
}

if ((ret = port_scan("::1", test_arr, TEST_ARR_LEN, &is_open, NULL)) == SUCCESS)
if ((ret = port_scan("::1", test_arr, TEST_ARR_LEN, &is_open, &is_up, NULL)) == SUCCESS)
printf("└ ✅ Localhost IPv6 Port scan test: Passed\n");
else
{
Expand All @@ -101,7 +102,7 @@ void syn_scan_test(void)

if (ping(lan_dev, 3) == SUCCESS)
{
if ((ret = port_scan(lan_dev, test_arr, TEST_ARR_LEN, &is_open, NULL)) == SUCCESS)
if ((ret = port_scan(lan_dev, test_arr, TEST_ARR_LEN, &is_open, &is_up, NULL)) == SUCCESS)
printf("└ ✅ IPv4 LAN device port scan test: Passed\n");
else
{
Expand All @@ -128,14 +129,14 @@ void syn_scan_test(void)
print_err(stderr, "❌ IPv6 Lan Port scan test failed", ret);
}*/

if ((ret = port_scan("scanme.nmap.org", scanme_ports, 4, &is_open, NULL)) == SUCCESS)
if ((ret = port_scan("scanme.nmap.org", scanme_ports, 4, &is_open, &is_up, NULL)) == SUCCESS)
printf("└ ✅ External IPv4 Port scan test: Passed\n");
else
{
print_err(stderr, "└ ❌ External IPv4 Port scan test failed", ret);
}

if ((ret = port_scan("2600:3c01::f03c:91ff:fe18:bb2f", scanme_ports, 4, &is_open, NULL)) == SUCCESS)
if ((ret = port_scan("2600:3c01::f03c:91ff:fe18:bb2f", scanme_ports, 4, &is_open, &is_up, NULL)) == SUCCESS)
printf("└ ✅ External IPv6 Port scan test: Passed\n");
else
{
Expand Down