forked from syn53/packetagent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
packetagent-client.go
268 lines (185 loc) · 5.9 KB
/
packetagent-client.go
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/*
| | _ _
____ _____ ____| | _ _____ _| |_ _____ _____ ____ _____ ____ _| |_
| _ \(____ |/ ___) |_/ ) ___ (_ _|_____|____ |/ _ | ___ | _ (_ _)
| |_| / ___ ( (___| _ (| ____| | |_ / ___ ( (_| | ____| | | || |_
| __/\_____|\____)_| \_)_____) \__) \_____|\___ |_____)_| |_| \__)
|_| (_____|
packet-agent 🕵 : client.go
license: LGPLv3
author: Ben Duncan @ben_colo
more: https://packet-agent.com/
FILE_ID.DIZ
*/
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"strconv"
"strings"
"time"
"github.com/syn53/packetagent"
pb "gopkg.in/cheggaaa/pb.v1"
// Should be optional really ...
)
/*
TODO:
- Add per IP message support
- SSL support
- base64AES-256-KEY(encrypted by RSA public key)+}base64payload}}(EOF)
- if crypto fails, try plaintext
- Port ranges
x - Fit 2 bytes in, vs 1
- Function to find free ports
- TCP or UDP
- How to detect these, filter via tcpdump and the like.
- Send dummy data to cloak
x - Progress bar support
- Look at godep support
Support other transport methods:
- IP headers
- Spoofed packets ( destination IP )
- ICMP payloads
- Dest port ( e.g between $range + (1 to 66) to represent Base64
- Two ports, e.g 80 and 443 as binary for dst connect, no data
- ipv6 support, lots more padding
- Combination of TCP + UDP packets
- UDP DEST PORT! SRC IS IRRELEVANT VIA A NAT! :)
*/
func main() {
// CLI Flags
message := flag.String("message", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", "Message to transmit")
verbose := flag.Bool("verbose", false, "Flag for verbose output")
dstport := flag.Int("port", 8053, "Connect on specified port (UDP)")
server := flag.String("server", "127.0.0.1", "Connect to specified server (localhost)")
file := flag.String("file", "", "Send a file (<32kb recommended)")
sleep := flag.Int("sleep", 1, "Pause for X milliseconds between packets (1ms)")
broadcast := flag.Bool("broadcast", false, "Broadcast to subnet (UDP only)")
source := flag.String("source", "", "Source IP address")
publickey := flag.String("pubkey", "", "Public RSA key to encrypt data (optional)")
flag.Parse()
var str string
// Read the file to send
if *file != "" {
data, err := ioutil.ReadFile(*file)
if err != nil {
log.Fatalf("Cannot read specified file: %s", err)
}
dataLen := len(data)
str = string(data)
fmt.Println("Sending file =>", *file, "(", len(data), ") bytes on disk. (", len(str), ") bytes base64 encoded")
if dataLen > 1024*32 {
fmt.Println("WARNING: File specified is larger then 32kb, this is not recommended.")
}
} else {
str = *message
fmt.Println("Transmitting message => ", *message)
}
// Create a map between characters
ctl := pkagent.CtlStrings{}
ctl = pkagent.CtlStringsToMap(ctl)
if *broadcast == true {
*server = "255.255.255.255"
}
RemoteAddr := net.UDPAddr{IP: net.ParseIP(*server), Port: *dstport}
fmt.Println("\nDialing ☎️ =>", RemoteAddr.IP, ":", RemoteAddr.Port, "\n")
// Public key specified? Encrypt a AES shared-key using the rcpt public RSA key
// After this, encrypt the payload using the AES cipher
// Format:
// }base64-AES-256-KEY(signed by RSA public key)}(AES encrypted payload, base64}}(EOF)
var ports []int
if *publickey != "" {
pub_parsed, err := pkagent.LoadRSApublicKey(*publickey)
if err != nil {
log.Fatal(err)
}
label := []byte("")
hash := sha256.New()
if *verbose == true {
fmt.Println("Encrypting message")
}
// Encrypt the AES shared key
aesKey := pkagent.GenKey()
aesSharedKey, err := rsa.EncryptOAEP(hash, rand.Reader, pub_parsed, aesKey, label)
if err != nil {
fmt.Println("Failed to encrypt AES shared key", err)
}
if *verbose == true {
fmt.Println("Encrypting complete")
}
// Next, encrypt the payload using the AES key
aesPayLoad, err := pkagent.Encrypt(aesKey, str)
if err != nil {
fmt.Println(err)
}
if *verbose == true {
fmt.Println("SharedKey length =", len(aesSharedKey))
fmt.Println(string(aesSharedKey))
fmt.Println("Payload")
fmt.Println(aesPayLoad)
}
// base64-AES-256-KEY(signed by RSA public key)+{(AES encrypted payload, base64}}(EOF)
// Encode the AES shared key using the RSA public key
ports = pkagent.SrcportToASCII(string(aesSharedKey), ctl.Data, true)
// Next, the payload AES encrypted
ports = append(ports, pkagent.SrcportToASCII(aesPayLoad, ctl.Data, false)...)
} else {
ports = pkagent.SrcportToASCII(str, ctl.Data, false)
}
count := len(ports)
bar := pb.StartNew(count)
for _, value := range ports {
bar.Increment()
var s []string
if *source != "" {
s = []string{string(*source) + ":", strconv.Itoa(value)}
} else {
s = []string{":", strconv.Itoa(value)}
}
LocalAddr, err := net.ResolveUDPAddr("udp", strings.Join(s, ""))
if err != nil {
log.Fatal("Could not create network socket:", err)
}
if *verbose == true {
fmt.Println("Opening connection on port", s)
}
// Attempt to dial 5 times max ( src part may already be in use )
var attempt int
for {
conn, err := net.DialUDP("udp", LocalAddr, &RemoteAddr)
if err != nil {
fmt.Println("Could not dial network socket:", err)
attempt++
if attempt == 5 {
log.Fatal("Could not dial network socket after 5 attempts:", err)
time.Sleep(time.Second * 1)
}
continue
}
// TODO: Random data, or null for data payload
//var i int
msg := string("")
buf := []byte(msg)
_, err = conn.Write(buf)
if err != nil {
fmt.Println(msg, err)
}
// Sleep for the specified time between packets
sleep2 := time.Duration(*sleep)
snooze := time.Millisecond * sleep2
time.Sleep(snooze)
// Close the connection
// TODO: Add TCP support
conn.Close()
break
}
}
bar.Finish()
bar.FinishPrint("\nComplete - 🕵 PacketAgent at your service")
}