-
Notifications
You must be signed in to change notification settings - Fork 4
/
rpcclient.cs
215 lines (192 loc) · 8.44 KB
/
rpcclient.cs
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
using System;
using System.Collections.Generic;
using System.Linq;
namespace Reecon
{
class RPCClient
{
private static List<string> RunCommand(string ip, string command, bool signing)
{
List<string> processOutput = new List<string>();
if (signing)
{
processOutput = General.GetProcessOutput("rpcclient", $"-U \"\"%\"\" {ip} -c \"{command}\"");
}
else
{
// Xenial = -S
// processOutput = General.GetProcessOutput("rpcclient", $"-S off -U \"anonymous\"%\"\" {ip} -c \"{command}\"");
// Jammy = --option=clientsigning=off
// Both will probably run each time if the first is bad - Really need to set it
processOutput = General.GetProcessOutput("rpcclient", $"--option=clientsigning=off -U \"anonymous\"%\"\" {ip} -c \"{command}\"");
// Happens if smb2-security-mode: -> Message signing enabled and required
if (processOutput.Any(x => x.Contains("Bad SMB2 (sign_algo_id=2) signature for message")))
{
processOutput = General.GetProcessOutput("rpcclient", $"--option=clientsigning=off -U \"\"%\"\" {ip} -c \"{command}\"");
}
}
return processOutput;
}
public static List<string> GetEnumdomusersOutput(string ip, bool signing = true)
{
List<string> processOutput = RunCommand(ip, "enumdomusers", signing);
return processOutput;
}
public static List<string> GetLsaenumsidOutput(string ip, bool signing = true)
{
List<string> processOutput = RunCommand(ip, "lsaenumsid", signing);
return processOutput;
}
public static List<string> GetLsaqueryOutput(string ip)
{
List<string> processOutput = RunCommand(ip, "lsaquery", false);
return processOutput;
}
// Lookupnames
public class LookupName
{
public string Name;
public string SID;
public string Type;
}
public static List<LookupName> LookupNames(string ip, string namesList, bool signing)
{
List<LookupName> lookupList = new List<LookupName>();
List<string> proccessOutput = GetLookupnamesOutput(ip, namesList, signing);
foreach (string item in proccessOutput)
{
LookupName lookupName = new LookupName();
lookupName.Name = item.Split(' ')[0];
lookupName.SID = item.Split(' ')[1];
lookupName.Type = item.Split(' ')[2];
lookupList.Add(lookupName);
}
return lookupList;
}
public static List<string> GetLookupnamesOutput(string ip, string names, bool signing)
{
/*
administrator S-0-0 (UNKNOWN: 8)
guest S-0-0 (UNKNOWN: 8)
krbtgt S-0-0 (UNKNOWN: 8)
root S-1-22-1-0 (User: 1)
bin S-1-22-1-2 (User: 1)
none S-1-5-21-978893743-2663913856-222388731-513 (Domain Group: 2)
*/
List<string> proccessOutput = RunCommand(ip, $"lookupnames {names}", signing);
return proccessOutput;
}
// Lookupsids
public class LookupSid
{
public string SID;
public string Name;
public string Type;
}
public static List<LookupSid> LookupSids(string ip, List<string> sidList, bool signing)
{
List<LookupSid> lookupList = new List<LookupSid>();
List<string> proccessOutput = GetLookupsidsOutput(ip, sidList, signing);
foreach (string item in proccessOutput)
{
// S-1-22-1-1000 Unix User\fox (1)
LookupSid lookupSid = new LookupSid();
lookupSid.SID = item.Split(' ')[0];
string name = item.Split(' ')[2];
lookupSid.Name = name.Remove(0, name.LastIndexOf("\\") + 1);
lookupSid.Type = item.Split(' ')[3].Replace("(", "").Replace(")", "");
lookupList.Add(lookupSid);
}
return lookupList;
}
public static List<string> GetLookupsidsOutput(string ip, List<string> sidList, bool signing)
{
// Remove invalid sid info from previous commands
sidList.RemoveAll(x => x.StartsWith("found "));
// Remove blanks
sidList.RemoveAll(x => string.IsNullOrEmpty(x));
string sidListString = string.Join(' ', sidList);
List<string> proccessOutput = RunCommand(ip, $"lookupsids {sidListString}", signing);
return proccessOutput;
}
public static List<LookupSid> GetSneakySids(string ip, List<string> userSidList, bool signing)
{
// Get the unique bases from the users
List<LookupSid> returnList = new List<LookupSid>();
List<string> sneakySIDBaseList = new();
foreach (string sid in userSidList)
{
string sneakySIDBase = sid.Substring(0, sid.LastIndexOf("-") + 1);
if (!sneakySIDBaseList.Contains(sneakySIDBase))
{
sneakySIDBaseList.Add(sneakySIDBase);
}
}
// Generate a sneakySidList from the bases
List<string> sneakySIDList = new List<string>();
foreach (string sneakyBase in sneakySIDBaseList)
{
// Low ones are just system names - Can ignore them - Proper ones start from 1000
for (int j = 1000; j <= 1015; j++)
{
sneakySIDList.Add(sneakyBase + j);
}
// Some sneakier ones hiding from 1100 instead
for (int j = 1100; j <= 1115; j++)
{
sneakySIDList.Add(sneakyBase + j);
}
List<LookupSid> sneakySIDLookup = RPCClient.LookupSids(ip, sneakySIDList, signing);
if (sneakySIDLookup.Count != 0)
{
// Remove non-users
sneakySIDLookup.RemoveAll(x => x.Type != "1");
foreach (LookupSid sid in sneakySIDLookup)
{
// Some invalid ones simply have the number itself instead of the name
// A bit hacky, but it works
if (!int.TryParse(sid.Name, out int toIgnore))
{
returnList.Add(sid);
}
}
}
}
return returnList;
}
public static List<string> GetSrvinfoOutput(string ip, bool signing = true)
{
List<string> processOutput = RunCommand(ip, "srvinfo", signing);
return processOutput;
}
public static string GetQueryuserInfo(string ip, string username)
{
string returnInfo = "";
// Console.WriteLine("Debug Output: " + user);
// user:[Guest] rid:[0x1f5]
returnInfo += "-- " + username + Environment.NewLine;
List<string> infoList = RunCommand(ip, $"queryuser {username}", false);
foreach (string info in infoList)
{
// padding1[0..7]...
// logon_hrs[0..21]..
if (!info.Contains(":"))
{
return returnInfo;
}
string description = info.Substring(0, info.IndexOf(":"));
description = description.Trim();
string value = info.Remove(0, info.IndexOf(":") + 1);
value = value.Trim();
if (description == "Full Name" || description == "Home Drive" || description == "Comment" || description == "Description")
{
if (value != "")
{
returnInfo += "--- " + description + ": " + value + Environment.NewLine;
}
}
}
return returnInfo.Trim(Environment.NewLine.ToCharArray());
}
}
}