-
Notifications
You must be signed in to change notification settings - Fork 5
/
main.c
163 lines (126 loc) · 3.08 KB
/
main.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "common.h"
#include "reverse-listener.h"
#include "reverse-shell.h"
#include "plugin.h"
#include "plain_tcp.h"
#include "plain_udp.h"
#define PROGNAME "rshell"
#define VERSION "1.2.0-dev"
#define SHELL "sh"
#define PATH "/bin"
#define PATHSHELL PATH "/" SHELL
static void version(void)
{
fprintf(stderr, "%s %s\n", PROGNAME, VERSION);
exit(0);
}
static void usage(int ret)
{
fprintf(stderr, "usage: %s [options] <host> <port> [peer]\n", PROGNAME);
fprintf(stderr, "arguments:\n");
fprintf(stderr, "\thost : mandatory specific host to bind or connect (could be \"any\" in listen mode)\n");
fprintf(stderr, "\tport : mandatory specific port to bind or connect\n");
fprintf(stderr, "\tpeer : optional peer address to accept connection from in listen mode\n");
fprintf(stderr, "options:\n");
fprintf(stderr, "\t-4 : use IPv4 socket\n");
fprintf(stderr, "\t-6 : use IPv6 socket\n");
fprintf(stderr, "\t-f : foreground mode (eg: no fork)\n");
fprintf(stderr, "\t-h : display this and exit\n");
fprintf(stderr, "\t-l : listen mode\n");
fprintf(stderr, "\t-s <shell> : give the path shell (default: %s)\n", PATHSHELL);
fprintf(stderr, "\t-u : use an UDP socket\n");
fprintf(stderr, "\t-v : display version and exit\n");
exit(ret);
}
static void rshell_init(struct rshell *rshell)
{
rshell->family = AF_UNSPEC;
rshell->shell = PATHSHELL;
rshell->flags = 0;
rshell->peer = NULL;
rshell->plugin = &plain_tcp_plugin;
}
static int rshell_set_port(struct rshell *rshell, char *port)
{
long int res;
res = strtol(port, NULL, 10);
if ( res <= 0 || res > 0xffff )
return -1;
rshell->service = port;
rshell->port = (uint16_t) res;
return 0;
}
static int parse_option(int argc, char *argv[], struct rshell *rshell)
{
int c;
rshell_init(rshell);
while ( (c = getopt(argc, argv, "46fhls:uv")) != -1 )
{
switch ( c )
{
case '4':
rshell->family = AF_INET;
break;
case '6':
rshell->family = AF_INET6;
break;
case 'f':
rshell->flags |= RSHELL_F_NOFORK;
break;
case 'h':
usage(0);
/* NOTREACHED */
return 0;
case 'l':
rshell->flags |= RSHELL_F_LISTEN;
break;
case 's':
rshell->shell = optarg;
break;
case 'u':
rshell->plugin = &plain_udp_plugin;
break;
case 'v':
version();
return 0;
}
}
argv += optind;
argc -= optind;
if ( rshell->flags & RSHELL_F_LISTEN )
{
if ( argc < 2 || argc > 3 )
usage(-1);
if ( argc == 3 )
rshell->peer = argv[2];
}
else
{
if ( argc != 2 )
usage(-1);
}
rshell->host = argv[0];
if ( rshell_set_port(rshell, argv[1]) )
{
fprintf(stderr, "Invalid port %s\n", argv[1]);
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
int ret;
struct rshell rshell;
if ( (ret = parse_option(argc, argv, &rshell)) )
return ret;
if ( rshell.flags & RSHELL_F_LISTEN )
return rshell_serve(&rshell);
return rshell_connect(&rshell);
}