-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathWebAPI.cs
253 lines (215 loc) · 9.19 KB
/
WebAPI.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
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
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using System.Globalization;
namespace Shodan
{
public class WebAPI
{
private readonly string API_KEY;
private const string BASE_URL = "http://beta.shodanhq.com/api/";
private JavaScriptSerializer json_parser = new JavaScriptSerializer();
private WebClient web_client = new WebClient();
/// <summary>
/// Initialize the Shodan WebAPI object.
/// </summary>
/// <param name="api_key">The Shodan API key for your account.</param>
public WebAPI(string apiKey)
{
API_KEY = apiKey;
}
/// <summary>
/// Get all the information Shodan has on the IP.
/// </summary>
/// <param name="ip">IP of the computer to look up</param>
/// <returns>A Host object with the banners and location information.</returns>
public Host GetHost(IPAddress ip)
{
string str_ip = ip.ToString();
// Send the request
Dictionary<string, string> args = new Dictionary<string, string>();
args["ip"] = str_ip;
Dictionary<string, object> res_dict = SendRequest("host", args);
Host host = new Host(res_dict);
return host;
}
/// <summary>
/// Get all the information Shodan has on the IP (given as a string).
/// </summary>
/// <param name="ip">IP of the computer to look up</param>
/// <returns>A Host object with the banners and location information.</returns>
public Host GetHost(string ip)
{
return GetHost(IPAddress.Parse(ip));
}
/// <summary>
/// Search the Shodan search engine for computers matching the given search criteria.
/// </summary>
/// <param name="query">The search query for Shodan; identical syntax to the website.</param>
/// <param name="offset">The starting position for the search cursor. Only for enterprise customers.</param>
/// <param name="limit">The number of hosts to return (max. 100) per search query. Only for enterprise customers.</param>
/// <returns>A SearchResult object that contains a List of Hosts matching the query and the total number of results found.</returns>
public SearchResult Search(string query, int offset=0, int limit=50)
{
Dictionary<string, string> args = new Dictionary<string, string>();
args["q"] = query;
args["o"] = offset.ToString();
args["l"] = limit.ToString();
Dictionary<string, object> res_dict = SendRequest("search", args);
SearchResult result = new SearchResult(res_dict);
return result;
}
/// <summary>
/// Internal wrapper function to send API requests.
/// </summary>
/// <param name="api_func">The API function to call.</param>
/// <param name="args">The arguments to pass to the given API function.</param>
/// <returns>A Dictionary<string, object> with the deserialized JSON information.</returns>
private Dictionary<string, object> SendRequest(string api_func, Dictionary<string, string> args)
{
// Convert the arguments to a query string
string str_args = ToQuerystring(args);
// Send the request
Stream response = web_client.OpenRead(BASE_URL + api_func + str_args + "&key=" + API_KEY);
// Read the response into a string
StreamReader reader = new StreamReader(response);
string data = reader.ReadToEnd();
reader.Close();
// Turn the JSON string into a native dictionary object
Dictionary<string, object> result = json_parser.Deserialize<Dictionary<string, object>>(data);
// Raise an exception if an error was returned
if (result.ContainsKey("error"))
{
throw new System.ArgumentException((string)result["error"]);
}
return result;
}
private string ToQuerystring(Dictionary<string, string> dict)
{
return "?" + string.Join("&", dict.Select(x => string.Format("{0}={1}", HttpUtility.UrlEncode(x.Key), HttpUtility.UrlEncode(x.Value))));
}
}
public class SearchResult
{
private int numResults; // total # of results
private List<Host> hosts;
public int NumResults { get { return numResults; } }
public List<Host> Hosts { get { return hosts; } }
public SearchResult(Dictionary<string, object> results)
{
// Get the total number of results
numResults = (int)results["total"];
// Loop through the matches and create host entries
hosts = new List<Host>();
foreach (Dictionary<string, object> item in (ArrayList)results["matches"])
{
hosts.Add(new Host(item, true));
}
}
}
public class ServiceBanner
{
private int port;
private string banner;
private DateTime timestamp;
public int Port { get { return port; } }
public string Banner { get { return banner; } }
public DateTime Timestamp { get { return timestamp; } }
public ServiceBanner(int arg_port, string arg_banner, DateTime arg_timestamp)
{
port = arg_port;
banner = arg_banner;
timestamp = arg_timestamp;
}
}
public class HostLocation
{
private string country_code;
private string country_name;
private string city;
private double latitude;
private double longitude;
public string CountryCode { get { return country_code; } }
public string CountryName { get { return country_name; } }
public string City { get { return city; } }
public double Latitude { get { return latitude; } }
public double Longitude { get { return longitude; } }
public HostLocation(Dictionary<string, object> host)
{
// Extract the info out of the host dictionary and put it in the local properties
if (host.ContainsKey("country_name"))
country_name = (string)host["country_name"];
if (host.ContainsKey("country_code"))
country_code = (string)host["country_code"];
if (host.ContainsKey("city"))
city = (string)host["city"];
if (host.ContainsKey("latitude"))
{
latitude = (double)((decimal)host["latitude"]);
longitude = (double)((decimal)host["longitude"]);
}
}
/// <summary>
/// Check whether there are valid coordinates available for this location.
/// </summary>
/// <returns>true if there are latitude/ longitude coordinates, false otherwise.</returns>
public Boolean HasCoordinates()
{
if (Latitude != 0 && Longitude != 0)
{
return true;
}
return false;
}
}
public class Host
{
/*
* Setup the properties
*/
private List<ServiceBanner> banners;
private IPAddress ip = IPAddress.None;
private List<string> hostnames;
private HostLocation location = null;
private Boolean simple = false;
public List<ServiceBanner> Banners { get { return banners; } }
public IPAddress IP { get { return ip; } }
public List<string> Hostnames { get { return hostnames; } }
public HostLocation Location { get { return location; } }
// Used to differentiate between hosts from Search() results and direct GetHost() queries
public Boolean IsSimple { get { return simple; } }
public Host(Dictionary<string, object> host, Boolean simple=false)
{
CultureInfo provider = CultureInfo.InvariantCulture;
// Extract the info out of the host dictionary and put it in the local properties
ip = IPAddress.Parse(host["ip"].ToString());
// Hostnames
ArrayList tmp = (ArrayList)host["hostnames"];
hostnames = tmp.Cast<string>().ToList();
// Banners
banners = new List<ServiceBanner>();
if (host["data"] is ArrayList)
{
tmp = (ArrayList)host["data"];
foreach (Dictionary<string, object> data in tmp)
{
DateTime timestamp = DateTime.ParseExact((string)data["timestamp"], "dd.MM.yyyy", provider);
banners.Add(new ServiceBanner((int)data["port"], (string)data["banner"], (DateTime)timestamp));
}
}
else if (host["data"] is string)
{
DateTime timestamp = DateTime.ParseExact((string)host["updated"], "dd.MM.yyyy", provider);
banners.Add(new ServiceBanner((int)host["port"], (string)host["data"], (DateTime)timestamp));
}
// Location
location = new HostLocation(host);
}
}
}