Add project files.
This commit is contained in:
39
Shodan.Net.sln
Normal file
39
Shodan.Net.sln
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{060AE71C-AE05-4F14-8970-84A1AE49A562}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{18A95621-2E1B-48F0-9D38-D7B3513F31D3}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
global.json = global.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Shodan.Net", "src\Shodan.Net\Shodan.Net.xproj", "{2AC1566F-7C77-499E-B9AE-1F029BD7F7E8}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Shodan.Net.UnitTests", "src\Shodan.Net.UnitTests\Shodan.Net.UnitTests.xproj", "{F83A8130-97B5-4AA2-810C-1D16A88799BD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2AC1566F-7C77-499E-B9AE-1F029BD7F7E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2AC1566F-7C77-499E-B9AE-1F029BD7F7E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2AC1566F-7C77-499E-B9AE-1F029BD7F7E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2AC1566F-7C77-499E-B9AE-1F029BD7F7E8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F83A8130-97B5-4AA2-810C-1D16A88799BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F83A8130-97B5-4AA2-810C-1D16A88799BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F83A8130-97B5-4AA2-810C-1D16A88799BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F83A8130-97B5-4AA2-810C-1D16A88799BD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{2AC1566F-7C77-499E-B9AE-1F029BD7F7E8} = {060AE71C-AE05-4F14-8970-84A1AE49A562}
|
||||
{F83A8130-97B5-4AA2-810C-1D16A88799BD} = {060AE71C-AE05-4F14-8970-84A1AE49A562}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
6
global.json
Normal file
6
global.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"projects": [ "src", "test" ],
|
||||
"sdk": {
|
||||
"version": "1.0.0-preview1-002702"
|
||||
}
|
||||
}
|
||||
21
src/Shodan.Net.UnitTests/Class1.cs
Normal file
21
src/Shodan.Net.UnitTests/Class1.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Shodan.Net.UnitTests
|
||||
{
|
||||
// This project can output the Class library as a NuGet Package.
|
||||
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
|
||||
public class Class1
|
||||
{
|
||||
[Fact]
|
||||
public async Task privateGetsPorts()
|
||||
|
||||
{
|
||||
var client = new ShodanClient("9F0mxmNSaHbe0mYmefwoCZrChT2h0KzC");
|
||||
var ports = await client.GetPortsAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/Shodan.Net.UnitTests/Properties/AssemblyInfo.cs
Normal file
19
src/Shodan.Net.UnitTests/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Shodan.Net.UnitTests")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f83a8130-97b5-4aa2-810c-1d16a88799bd")]
|
||||
22
src/Shodan.Net.UnitTests/Shodan.Net.UnitTests.xproj
Normal file
22
src/Shodan.Net.UnitTests/Shodan.Net.UnitTests.xproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>f83a8130-97b5-4aa2-810c-1d16a88799bd</ProjectGuid>
|
||||
<RootNamespace>Shodan.Net.UnitTests</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
25
src/Shodan.Net.UnitTests/project.json
Normal file
25
src/Shodan.Net.UnitTests/project.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"testRunner": "xunit",
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.5.0-rc2-24027",
|
||||
"xunit": "2.1.0",
|
||||
"dotnet-test-xunit": "1.0.0-rc2-build10015",
|
||||
"Shodan.Net": "1.0.0-*"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"type": "platform",
|
||||
"version": "1.0.0-rc2-3002702"
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/Shodan.Net/Class1.cs
Normal file
16
src/Shodan.Net/Class1.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net
|
||||
{
|
||||
// This project can output the Class library as a NuGet Package.
|
||||
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
|
||||
public class Class1
|
||||
{
|
||||
public Class1()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
124
src/Shodan.Net/IShodanAsyncClient.cs
Normal file
124
src/Shodan.Net/IShodanAsyncClient.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using Shodan.Net.Models;
|
||||
using Shodan.Net.Models.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net
|
||||
{
|
||||
internal interface IShodanAsyncClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all services that have been found on the given host IP.
|
||||
/// </summary>
|
||||
/// <param name="Ip">Host IP address</param>
|
||||
/// <param name="history">True if all historical banners should be returned (default: False) </param>
|
||||
/// <param name="minify">True to only return the list of ports and the general host information, no banners. (default: False) </param>
|
||||
/// <returns></returns>
|
||||
Task<Host> GetHostAsync(string Ip, bool history = false, bool minify = false);
|
||||
|
||||
/// <summary>
|
||||
/// This method returns a list of port numbers that the crawlers are looking for.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<int>> GetPortsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// This method returns an object containing all the protocols that can be used when launching an Internet scan.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetProtocolsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to request Shodan to crawl a network
|
||||
/// <strong>Requirements:</strong> This method uses API scan credits: 1 IP consumes 1 scan credit. You must have a paid API plan (either one-time payment or subscription) in order to use this method
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<ScanResult> RequstScanAsync(string ips);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="port"> The port that Shodan should crawl the Internet for. </param>
|
||||
/// <param name="protocol">The name of the protocol that should be used to interrogate the port. See /shodan/protocols for a list of supported protocols. </param>
|
||||
/// <returns></returns>
|
||||
Task<ScanPortResult> RequestInternetPortScanAsync(int port, string protocol);
|
||||
|
||||
/// <summary>
|
||||
/// Check the progress of a previously submitted scan request
|
||||
/// </summary>
|
||||
/// <param name="id">the unique scan ID that was returned by /shodan/scan</param>
|
||||
/// <returns></returns>
|
||||
Task<ScanStatus> GetScanStatusAsync(string id);
|
||||
|
||||
/// <summary>
|
||||
/// This method returns an object containing all the services that the Shodan crawlers look at. It can also be used as a quick and practical way to resolve a port number to the name of a service
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetServicesAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to obtain a list of search queries that users have saved in Shodan.
|
||||
/// </summary>
|
||||
/// <param name="page"> Page number to iterate over results; each page contains 10 items </param>
|
||||
/// <param name="options"> Sort the list based on a property. Possible values are: votes, timestamp </param>
|
||||
/// <param name="order">Whether to sort the list in ascending or descending order. Possible values are: asc, desc </param>
|
||||
/// <returns></returns>
|
||||
Task<SearchQueries> GetQueriesAsync(int? page = null, SortOptions? options = null, OrderOption? order = null);
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to search the directory of search queries that users have saved in Shodan.
|
||||
/// </summary>
|
||||
/// <param name="query"> What to search for in the directory of saved search queries. </param>
|
||||
/// <param name="page">Page number to iterate over results; each page contains 10 items </param>
|
||||
/// <returns></returns>
|
||||
Task<SearchQueries> SearchQueriesAsync(string query, int? page = null);
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to obtain a list of popular tags for the saved search queries in Shodan.
|
||||
/// </summary>
|
||||
/// <param name="size">The number of tags to return </param>
|
||||
/// <returns></returns>
|
||||
Task<TagResult> GetTagsAsync(int size = 10);
|
||||
|
||||
/// <summary>
|
||||
/// Returns information about the Shodan account linked to this API key.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<Profile> GetProfileAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Look up the IP address for the provided list of hostnames.
|
||||
/// </summary>
|
||||
/// <param name="hostnames">Comma-separated list of hostnames; example "google.com,bing.com" </param>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> DnsLookupAsync(string hostnames);
|
||||
|
||||
/// <summary>
|
||||
/// Look up the hostnames that have been defined for the given list of IP addresses
|
||||
/// </summary>
|
||||
/// <param name="ips">Comma-separated list of IP addresses; example "74.125.227.230,204.79.197.200"</param>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, List<string>>> ReverseLookupAsync(string ips);
|
||||
|
||||
/// <summary>
|
||||
/// Get your current IP address as seen from the Internet.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<string> GetMyIpAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Returns information about the API plan belonging to the given API key.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<ApiStatus> GetApiStatusAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a honeypot probability score rangin from 0 (not a honeypot) to 1.0 (is a honeypot).
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
Task<double> Experimental_GetHoneyPotScoreAsync(string ip);
|
||||
}
|
||||
}
|
||||
124
src/Shodan.Net/IShodanClient.cs
Normal file
124
src/Shodan.Net/IShodanClient.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using Shodan.Net.Models;
|
||||
using Shodan.Net.Models.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net
|
||||
{
|
||||
public interface IShodanClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all services that have been found on the given host IP.
|
||||
/// </summary>
|
||||
/// <param name="Ip">Host IP address</param>
|
||||
/// <param name="history">True if all historical banners should be returned (default: False) </param>
|
||||
/// <param name="minify">True to only return the list of ports and the general host information, no banners. (default: False) </param>
|
||||
/// <returns></returns>
|
||||
Host GetHost(string Ip, bool history = false, bool minify = false);
|
||||
|
||||
/// <summary>
|
||||
/// This method returns a list of port numbers that the crawlers are looking for.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
List<int> GetPorts();
|
||||
|
||||
/// <summary>
|
||||
/// This method returns an object containing all the protocols that can be used when launching an Internet scan.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Dictionary<string, string> GetProtocols();
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to request Shodan to crawl a network
|
||||
/// <strong>Requirements:</strong> This method uses API scan credits: 1 IP consumes 1 scan credit. You must have a paid API plan (either one-time payment or subscription) in order to use this method
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
ScanResult RequstScan(string ips);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="port"> The port that Shodan should crawl the Internet for. </param>
|
||||
/// <param name="protocol">The name of the protocol that should be used to interrogate the port. See /shodan/protocols for a list of supported protocols. </param>
|
||||
/// <returns></returns>
|
||||
ScanPortResult RequestPortScan(int port, string protocol);
|
||||
|
||||
/// <summary>
|
||||
/// Check the progress of a previously submitted scan request
|
||||
/// </summary>
|
||||
/// <param name="id">the unique scan ID that was returned by /shodan/scan</param>
|
||||
/// <returns></returns>
|
||||
ScanStatus GetScanStatus(string id);
|
||||
|
||||
/// <summary>
|
||||
/// This method returns an object containing all the services that the Shodan crawlers look at. It can also be used as a quick and practical way to resolve a port number to the name of a service
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Dictionary<string, string> GetServices();
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to obtain a list of search queries that users have saved in Shodan.
|
||||
/// </summary>
|
||||
/// <param name="page"> Page number to iterate over results; each page contains 10 items </param>
|
||||
/// <param name="options"> Sort the list based on a property. Possible values are: votes, timestamp </param>
|
||||
/// <param name="order">Whether to sort the list in ascending or descending order. Possible values are: asc, desc </param>
|
||||
/// <returns></returns>
|
||||
SearchQueries GetQueries(int? page = null, SortOptions? options = null, OrderOption? order = null);
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to search the directory of search queries that users have saved in Shodan.
|
||||
/// </summary>
|
||||
/// <param name="query"> What to search for in the directory of saved search queries. </param>
|
||||
/// <param name="page">Page number to iterate over results; each page contains 10 items </param>
|
||||
/// <returns></returns>
|
||||
SearchQueries GetQuerySearches(string query, int? page = null);
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to obtain a list of popular tags for the saved search queries in Shodan.
|
||||
/// </summary>
|
||||
/// <param name="size">The number of tags to return </param>
|
||||
/// <returns></returns>
|
||||
TagResult GetTags(int size = 10);
|
||||
|
||||
/// <summary>
|
||||
/// Returns information about the Shodan account linked to this API key.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Profile GetProfile();
|
||||
|
||||
/// <summary>
|
||||
/// Look up the IP address for the provided list of hostnames.
|
||||
/// </summary>
|
||||
/// <param name="hostnames">Comma-separated list of hostnames; example "google.com,bing.com" </param>
|
||||
/// <returns></returns>
|
||||
Dictionary<string, string> DnsLookup(string hostnames);
|
||||
|
||||
/// <summary>
|
||||
/// Look up the hostnames that have been defined for the given list of IP addresses
|
||||
/// </summary>
|
||||
/// <param name="ips">Comma-separated list of IP addresses; example "74.125.227.230,204.79.197.200"</param>
|
||||
/// <returns></returns>
|
||||
Dictionary<string, List<string>> ReverseLookup(string ips);
|
||||
|
||||
/// <summary>
|
||||
/// Get your current IP address as seen from the Internet.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
string GetMyIp();
|
||||
|
||||
/// <summary>
|
||||
/// Returns information about the API plan belonging to the given API key.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
ApiStatus GetApiStatus();
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a honeypot probability score rangin from 0 (not a honeypot) to 1.0 (is a honeypot).
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
double Experimental_GetHoneyPotScore(string ip);
|
||||
}
|
||||
}
|
||||
30
src/Shodan.Net/Models/ApiStatus.cs
Normal file
30
src/Shodan.Net/Models/ApiStatus.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class ApiStatus
|
||||
{
|
||||
[DataMember(Name = "query_credits")]
|
||||
public int QueryCredits { get; set; }
|
||||
|
||||
[DataMember(Name = "scan_credits")]
|
||||
public int ScanCredits { get; set; }
|
||||
|
||||
[DataMember(Name = "telnet")]
|
||||
public bool Telnet { get; set; }
|
||||
|
||||
[DataMember(Name = "plan")]
|
||||
public string Plan { get; set; }
|
||||
|
||||
[DataMember(Name = "https")]
|
||||
public bool Https { get; set; }
|
||||
|
||||
[DataMember(Name = "unlocked")]
|
||||
public bool Unlocked { get; set; }
|
||||
}
|
||||
}
|
||||
139
src/Shodan.Net/Models/Banner.cs
Normal file
139
src/Shodan.Net/Models/Banner.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class Banner
|
||||
{
|
||||
/// <summary>
|
||||
/// The timestamp for when the banner was fetched from the device in the UTC timezone.
|
||||
/// </summary>
|
||||
[DataMember(Name = "timestamp")]
|
||||
public DateTime Timestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Either "udp" or "tcp" to indicate which IP transport protocol was used to fetch the information
|
||||
/// </summary>
|
||||
[DataMember(Name = "transport")]
|
||||
public string Transport { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An array of strings containing all of the hostnames that have been assigned to the IP address for this device.
|
||||
/// </summary>
|
||||
[DataMember(Name = "hostnames")]
|
||||
public IList<string> Hostnames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the organization that is assigned the IP space for this device.
|
||||
/// </summary>
|
||||
[DataMember(Name = "org")]
|
||||
public string Org { get; set; }
|
||||
|
||||
[DataMember(Name = "guid")]
|
||||
public string Guid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains the banner information for the service.
|
||||
/// </summary>
|
||||
[DataMember(Name = "data")]
|
||||
public string Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The port number that the service is operating on
|
||||
/// </summary>
|
||||
[DataMember(Name = "port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ISP that is providing the organization with the IP space for this device. Consider this the "parent" of the organization in terms of IP ownership.
|
||||
/// </summary>
|
||||
[DataMember(Name = "isp")]
|
||||
public string Isp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The autonomous system number (ex. "AS4837"
|
||||
/// </summary>
|
||||
[DataMember(Name = "asn")]
|
||||
public string Asn { get; set; }
|
||||
|
||||
[DataMember(Name = "location")]
|
||||
public Location Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IP address of the host as an integer
|
||||
/// </summary>
|
||||
[DataMember(Name = "ip")]
|
||||
public int? Ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IPv6 address of the host as a string. If this is present then the "ip" and "ip_str" fields wont be.
|
||||
/// </summary>
|
||||
[DataMember(Name = "ip")]
|
||||
public string Ipv6 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ] An array of strings containing the top-level domains for the hostnames of the device. This is a utility property in case you want to filter by TLD instead of subdomain. It is smart enough to handle global TLDs with several dots in the domain (ex. "co.uk")
|
||||
/// </summary>
|
||||
[DataMember(Name = "domains")]
|
||||
public IList<string> Domains { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IP address of the host as a string
|
||||
/// </summary>
|
||||
[DataMember(Name = "ip_str")]
|
||||
public string IpStr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The operating system that powers the device.
|
||||
/// </summary>
|
||||
[DataMember(Name = "os")]
|
||||
public object Os { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains experimental and supplemental data for the service. This can include the SSL certificate, robots.txt and other raw information that hasn't yet been formalized into the Banner Specification.
|
||||
/// </summary>
|
||||
[DataMember(Name = "opts", IsRequired = false)]
|
||||
public dynamic Opts { get; set; }
|
||||
|
||||
#region Optional Properties
|
||||
|
||||
/// <summary>
|
||||
/// The number of minutes that the device has been online.
|
||||
/// </summary>
|
||||
[DataMember(Name = "uptime", IsRequired = false)]
|
||||
public int? Uptime { get; set; }
|
||||
|
||||
[DataMember(Name = "link", IsRequired = false)]
|
||||
public string Link { get; set; }
|
||||
|
||||
[DataMember(Name = "title", IsRequired = false)]
|
||||
public string Title { get; set; }
|
||||
|
||||
[DataMember(Name = "html", IsRequired = false)]
|
||||
public string Html { get; set; }
|
||||
|
||||
[DataMember(Name = "product", IsRequired = false)]
|
||||
public string Product { get; set; }
|
||||
|
||||
[DataMember(Name = "version", IsRequired = false)]
|
||||
public string Version { get; set; }
|
||||
|
||||
[DataMember(Name = "devicetype", IsRequired = false)]
|
||||
public string DeviceType { get; set; }
|
||||
|
||||
[DataMember(Name = "info", IsRequired = false)]
|
||||
public string Info { get; set; }
|
||||
|
||||
[DataMember(Name = "cpe", IsRequired = false)]
|
||||
public string Cpe { get; set; }
|
||||
|
||||
[DataMember(Name = "ssl", IsRequired = false)]
|
||||
public SslProperties Ssl { get; set; }
|
||||
|
||||
#endregion Optional Properties
|
||||
}
|
||||
}
|
||||
39
src/Shodan.Net/Models/Host.cs
Normal file
39
src/Shodan.Net/Models/Host.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class Host
|
||||
{
|
||||
[DataMember(Name = "region_code")]
|
||||
public string RegionCode { get; set; }
|
||||
|
||||
[DataMember(Name = "ip")]
|
||||
public string Ip { get; set; }
|
||||
|
||||
[DataMember(Name = "area_code")]
|
||||
public string AreaCode { get; set; }
|
||||
|
||||
[DataMember(Name = "country_names")]
|
||||
public string CountryName { get; set; }
|
||||
|
||||
[DataMember(Name = "hostnames")]
|
||||
public List<string> Hostnames { get; set; }
|
||||
|
||||
[DataMember(Name = "postal_code")]
|
||||
public string PostalCode { get; set; }
|
||||
|
||||
[DataMember(Name = "dma_code")]
|
||||
public string DmaCode { get; set; }
|
||||
|
||||
[DataMember(Name = "country_code")]
|
||||
public string CountryCode { get; set; }
|
||||
|
||||
[DataMember(Name = "data")]
|
||||
public List<Banner> Data { get; set; }
|
||||
}
|
||||
}
|
||||
78
src/Shodan.Net/Models/Location.cs
Normal file
78
src/Shodan.Net/Models/Location.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class Location
|
||||
{
|
||||
/// <summary>
|
||||
/// An object containing all of the location information for the device.
|
||||
/// </summary>
|
||||
public Location()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The 3-letter country code for the device location.
|
||||
/// </summary>
|
||||
|
||||
[DataMember(Name = "country_code3")]
|
||||
public string CountryCode3 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the city where the device is located.
|
||||
/// </summary>
|
||||
[DataMember(Name = "city")]
|
||||
public string City { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The postal code for the device's location.
|
||||
/// </summary>
|
||||
[DataMember(Name = "postal_code")]
|
||||
public string PostalCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The longitude for the geolocation of the device.
|
||||
/// </summary>
|
||||
[DataMember(Name = "longitude")]
|
||||
public double Longitude { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The 2-letter country code for the device location.
|
||||
/// </summary>
|
||||
|
||||
[DataMember(Name = "country_code")]
|
||||
public string CountryCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The latitude for the geolocation of the device
|
||||
/// </summary>
|
||||
|
||||
[DataMember(Name = "latitude")]
|
||||
public double Latitude { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the country where the device is located.
|
||||
/// </summary>
|
||||
[DataMember(Name = "country_name")]
|
||||
public string CountryName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The area code for the device's location. Only available for the US.
|
||||
/// </summary>
|
||||
[DataMember(Name = "area_code")]
|
||||
public int AreaCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The designated market area code for the area where the device is located. Only available for the US.
|
||||
/// </summary>
|
||||
[DataMember(Name = "dma_code")]
|
||||
public int? DmaCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the region where the device is located.
|
||||
/// </summary>
|
||||
[DataMember(Name = "region_code")]
|
||||
public string RegionCode { get; set; }
|
||||
}
|
||||
}
|
||||
13
src/Shodan.Net/Models/Options/OrderOption.cs
Normal file
13
src/Shodan.Net/Models/Options/OrderOption.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models.Options
|
||||
{
|
||||
public enum OrderOption
|
||||
{
|
||||
asc,
|
||||
desc
|
||||
}
|
||||
}
|
||||
15
src/Shodan.Net/Models/Options/RequestType.cs
Normal file
15
src/Shodan.Net/Models/Options/RequestType.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models.Options
|
||||
{
|
||||
public enum RequestType
|
||||
{
|
||||
GET = 0,
|
||||
PUT = 1,
|
||||
POST = 2,
|
||||
DELETE = 4
|
||||
}
|
||||
}
|
||||
13
src/Shodan.Net/Models/Options/SortOptions.cs
Normal file
13
src/Shodan.Net/Models/Options/SortOptions.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models.Options
|
||||
{
|
||||
public enum SortOptions
|
||||
{
|
||||
votes,
|
||||
timestamp
|
||||
}
|
||||
}
|
||||
24
src/Shodan.Net/Models/Profile.cs
Normal file
24
src/Shodan.Net/Models/Profile.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class Profile
|
||||
{
|
||||
[DataMember(Name = "member")]
|
||||
public bool Member { get; set; }
|
||||
|
||||
[DataMember(Name = "credits")]
|
||||
public int Credits { get; set; }
|
||||
|
||||
[DataMember(Name = "display_name")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
[DataMember(Name = "created")]
|
||||
public DateTime Created { get; set; }
|
||||
}
|
||||
}
|
||||
15
src/Shodan.Net/Models/ScanPortResult.cs
Normal file
15
src/Shodan.Net/Models/ScanPortResult.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class ScanPortResult
|
||||
{
|
||||
[DataMember(Name = "id")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
}
|
||||
21
src/Shodan.Net/Models/ScanResult.cs
Normal file
21
src/Shodan.Net/Models/ScanResult.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class ScanResult
|
||||
{
|
||||
[DataMember(Name = "id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[DataMember(Name = "count")]
|
||||
public int Count { get; set; }
|
||||
|
||||
[DataMember(Name = "credits_left")]
|
||||
public int CreditsLeft { get; set; }
|
||||
}
|
||||
}
|
||||
21
src/Shodan.Net/Models/ScanStatus.cs
Normal file
21
src/Shodan.Net/Models/ScanStatus.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class ScanStatus
|
||||
{
|
||||
[DataMember(Name = "id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[DataMember(Name = "count")]
|
||||
public int Count { get; set; }
|
||||
|
||||
[DataMember(Name = "status")]
|
||||
public StatusEnum? Status { get; set; }
|
||||
}
|
||||
}
|
||||
40
src/Shodan.Net/Models/SearchQueries.cs
Normal file
40
src/Shodan.Net/Models/SearchQueries.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class Match
|
||||
{
|
||||
[DataMember(Name = "votes")]
|
||||
public int Votes { get; set; }
|
||||
|
||||
[DataMember(Name = "description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[DataMember(Name = "title")]
|
||||
public string Title { get; set; }
|
||||
|
||||
[DataMember(Name = "timestamp")]
|
||||
public DateTime Timestamp { get; set; }
|
||||
|
||||
[DataMember(Name = "tags")]
|
||||
public IList<string> Tags { get; set; }
|
||||
|
||||
[DataMember(Name = "query")]
|
||||
public string Query { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class SearchQueries
|
||||
{
|
||||
[DataMember(Name = "total")]
|
||||
public int Total { get; set; }
|
||||
|
||||
[DataMember(Name = "matches")]
|
||||
public IList<Match> Matches { get; set; }
|
||||
}
|
||||
}
|
||||
42
src/Shodan.Net/Models/SslProperties.cs
Normal file
42
src/Shodan.Net/Models/SslProperties.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class SslProperties
|
||||
{
|
||||
/// <summary>
|
||||
/// The parsed certificate properties that includes information such as when it was issued, the SSL extensions, the issuer, subject etc.
|
||||
/// </summary>
|
||||
[DataMember(Name = "cert")]
|
||||
public dynamic Cert { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Preferred cipher for the SSL connection
|
||||
/// </summary>
|
||||
[DataMember(Name = "ciper")]
|
||||
public dynamic Ciper { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An array of certificates, where each string is a PEM-encoded SSL certificate. This includes the user SSL certificate up to its root certificate.
|
||||
/// </summary>
|
||||
[DataMember(Name = "chain")]
|
||||
public IList<dynamic> Chain { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Diffie-Hellman parameters if available: "prime", "public_key", "bits", "generator" and an optional "fingerprint" if we know which program generated these parameters.
|
||||
/// </summary>
|
||||
[DataMember(Name = "dhparams")]
|
||||
public dynamic DhParams { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of SSL versions that are supported by the server. If a version isnt supported the value is prefixed with a "-". Example: ["TLSv1", "-SSLv2"] means that the server supports TLSv1 but doesnt support SSLv2.
|
||||
/// </summary>
|
||||
[DataMember(Name = "versions")]
|
||||
public IList<string> Versions { get; set; }
|
||||
}
|
||||
}
|
||||
15
src/Shodan.Net/Models/StatusEnum.cs
Normal file
15
src/Shodan.Net/Models/StatusEnum.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
public enum StatusEnum
|
||||
{
|
||||
SUBMITTING,
|
||||
QUEUE,
|
||||
PROCESSING,
|
||||
DONE
|
||||
}
|
||||
}
|
||||
28
src/Shodan.Net/Models/TagResult.cs
Normal file
28
src/Shodan.Net/Models/TagResult.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net.Models
|
||||
{
|
||||
[DataContract]
|
||||
public class TagResult
|
||||
{
|
||||
[DataMember(Name = "total")]
|
||||
public int Total { get; set; }
|
||||
|
||||
[DataMember(Name = "matches")]
|
||||
public IList<Match> Matches { get; set; }
|
||||
|
||||
[DataContract]
|
||||
public class Match
|
||||
{
|
||||
[DataMember(Name = "value")]
|
||||
public string Value { get; set; }
|
||||
|
||||
[DataMember(Name = "count")]
|
||||
public int Count { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/Shodan.Net/Properties/AssemblyInfo.cs
Normal file
19
src/Shodan.Net/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Shodan.Net")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("2ac1566f-7c77-499e-b9ae-1f029bd7f7e8")]
|
||||
205
src/Shodan.Net/QueryGenerator.cs
Normal file
205
src/Shodan.Net/QueryGenerator.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net
|
||||
{
|
||||
public class QueryGenerator
|
||||
{
|
||||
internal Dictionary<string, string> queryData { get; set; }
|
||||
private HashSet<string> CalledMethods = new HashSet<string>();
|
||||
|
||||
public QueryGenerator Before(DateTime time)
|
||||
{
|
||||
queryData.Add("before", time.ToString("dd/MM/yyyy"));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only show results that were collected after the given date
|
||||
/// </summary>
|
||||
/// <param name="time"></param>
|
||||
/// <returns></returns>
|
||||
public QueryGenerator After(DateTime time)
|
||||
{
|
||||
queryData.Add("after", time.ToString("dd/MM/yyyy"));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Autonomous System Number that identifies the network the device is on.
|
||||
/// </summary>
|
||||
/// <param name="asn"></param>
|
||||
/// <returns></returns>
|
||||
public QueryGenerator WithAsn(string asn)
|
||||
{
|
||||
queryData.Add("asn", asn);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator InCity(string city)
|
||||
{
|
||||
queryData.Add("city", city);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator InCountry(string country)
|
||||
{
|
||||
queryData.Add("country", country);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If "true" only show results that have a screenshot available.
|
||||
/// </summary>
|
||||
/// <param name="hasScreenshot"></param>
|
||||
/// <returns></returns>
|
||||
public QueryGenerator HasScreenshot(bool hasScreenshot = true)
|
||||
{
|
||||
queryData.Add("has_screenshot", hasScreenshot.ToString());
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithHostname(string hostname)
|
||||
{
|
||||
queryData.Add("hostname", hostname);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithHtml(string html)
|
||||
{
|
||||
queryData.Add("html", html);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithIsp(string isp)
|
||||
{
|
||||
queryData.Add("isp", isp);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithNet(string net)
|
||||
{
|
||||
queryData.Add("net", net);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithOrg(string org)
|
||||
{
|
||||
queryData.Add("org", org);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithOs(string os)
|
||||
{
|
||||
queryData.Add("os", os);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator Withport(string port)
|
||||
{
|
||||
queryData.Add("port", port);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator With_postal(string postal)
|
||||
{
|
||||
queryData.Add("postal", postal);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator With_product(string product)
|
||||
{
|
||||
queryData.Add("product", product);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator With_state(string state)
|
||||
{
|
||||
queryData.Add("state", state);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator With_title(string title)
|
||||
{
|
||||
queryData.Add("title", title);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator With_version(string version)
|
||||
{
|
||||
queryData.Add("version", version);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator With_Bitcoinip(string bitcoinip)
|
||||
{
|
||||
queryData.Add("bitcoin.ip", bitcoinip);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator With_Bitcoinip_count(string bitcoinip_count)
|
||||
{
|
||||
queryData.Add("bitcoin.ip_count", bitcoinip_count);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithBitcoinport(string bitcoinport)
|
||||
{
|
||||
queryData.Add("bitcoin.port", bitcoinport);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithBitcoinversion(string bitcoinversion)
|
||||
{
|
||||
queryData.Add("bitcoin.version", bitcoinversion);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithNtpip(string ntpip)
|
||||
{
|
||||
queryData.Add("ntp.ip", ntpip);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithNtpip_count(string ntpip_count)
|
||||
{
|
||||
queryData.Add("ntp.ip_count", ntpip_count);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithNtpmore(string ntpmore)
|
||||
{
|
||||
queryData.Add("ntp.more", ntpmore);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryGenerator WithNtpport(string ntpport)
|
||||
{
|
||||
queryData.Add("ntp.port", ntpport);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SearchQuery Generate(string searchText)
|
||||
{
|
||||
var sb = new StringBuilder(searchText);
|
||||
sb.Append(" ");
|
||||
foreach(var item in queryData)
|
||||
{
|
||||
sb.Append($"{item.Key}:{item.Value}");
|
||||
}
|
||||
return new SearchQuery(sb.ToString());
|
||||
}
|
||||
|
||||
private void EnsureMethodNotCalled(string methodName)
|
||||
{
|
||||
if(CalledMethods.Contains(methodName))
|
||||
{
|
||||
throw new ShodanException($"{methodName} cannot be called twice");
|
||||
}
|
||||
CalledMethods.Add(methodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/Shodan.Net/SearchQuery.cs
Normal file
17
src/Shodan.Net/SearchQuery.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net
|
||||
{
|
||||
public class SearchQuery
|
||||
{
|
||||
internal SearchQuery(string builtQuery)
|
||||
{
|
||||
this.Query = builtQuery;
|
||||
}
|
||||
|
||||
internal string Query { get; set; }
|
||||
}
|
||||
}
|
||||
12
src/Shodan.Net/SearchQueryGenerator.cs
Normal file
12
src/Shodan.Net/SearchQueryGenerator.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net
|
||||
{
|
||||
public class SearchQueryGenerator
|
||||
{
|
||||
public QueryGenerator WithQuery() => new QueryGenerator();
|
||||
}
|
||||
}
|
||||
21
src/Shodan.Net/Shodan.Net.xproj
Normal file
21
src/Shodan.Net/Shodan.Net.xproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>2ac1566f-7c77-499e-b9ae-1f029bd7f7e8</ProjectGuid>
|
||||
<RootNamespace>Shodan.Net</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
326
src/Shodan.Net/ShodanClient.cs
Normal file
326
src/Shodan.Net/ShodanClient.cs
Normal file
@@ -0,0 +1,326 @@
|
||||
using Newtonsoft.Json;
|
||||
using Shodan.Net.Models;
|
||||
using Shodan.Net.Models.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net
|
||||
{
|
||||
public class ShodanClient : IShodanAsyncClient
|
||||
{
|
||||
private readonly string apikey;
|
||||
private const string BasePath = "https://api.shodan.io";
|
||||
|
||||
//todo error handle!!!
|
||||
//todo:
|
||||
/*
|
||||
/shodan/host/count
|
||||
/shodan/host/search
|
||||
/shodan/host/search/tokens
|
||||
*/
|
||||
|
||||
public ShodanClient(string apikey)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(apikey))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(apikey));
|
||||
}
|
||||
this.apikey = apikey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Look up the IP address for the provided list of hostnames.
|
||||
/// </summary>
|
||||
/// <param name="hostnames">Comma-separated list of hostnames; example "google.com,bing.com" </param>
|
||||
/// <returns></returns>
|
||||
public Task<Dictionary<string, string>> DnsLookupAsync(string hostnames)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(hostnames))
|
||||
{
|
||||
throw new ArgumentNullException(hostnames);
|
||||
}
|
||||
var url = new Uri($"{BasePath}/dns/resolve?hostnames={hostnames}&key={this.apikey}");
|
||||
return MakeRequestAsync<Dictionary<string, string>>(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a honeypot probability score ranging from 0 (not a honeypot) to 1.0 (is a honeypot).
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<double> Experimental_GetHoneyPotScoreAsync(string ip)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(ip))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ip));
|
||||
}
|
||||
var url = new Uri($"{BasePath}/labs/honeyscore/{ip}?key={apikey}");
|
||||
var result = await MakeRequestAsync<string>(url);
|
||||
double resultParsed;
|
||||
if(!double.TryParse(result, out resultParsed))
|
||||
{
|
||||
throw new ShodanException($"honeypot score returned with {result} failed to parse to double");
|
||||
}
|
||||
return resultParsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns information about the API plan belonging to the given API key.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<ApiStatus> GetApiStatusAsync()
|
||||
{
|
||||
var url = new Uri($"{BasePath}/api-info?key={apikey}");
|
||||
return MakeRequestAsync<ApiStatus>(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all services that have been found on the given host IP.
|
||||
/// </summary>
|
||||
/// <param name="Ip">Host IP address</param>
|
||||
/// <param name="history">True if all historical banners should be returned (default: False) </param>
|
||||
/// <param name="minify">True to only return the list of ports and the general host information, no banners. (default: False) </param>
|
||||
/// <returns></returns>
|
||||
public Task<Host> GetHostAsync(string Ip, bool history = false, bool minify = false)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(Ip))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Ip));
|
||||
}
|
||||
var builder = new UriBuilder($"{BasePath}/shodan/host/{Ip}")
|
||||
{
|
||||
Query = $"key={this.apikey}&history={history.ToString()}&minify={minify.ToString()}"
|
||||
};
|
||||
|
||||
return MakeRequestAsync<Host>(builder.Uri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get your current IP address as seen from the Internet.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<string> GetMyIpAsync()
|
||||
{
|
||||
var url = new Uri($"{BasePath}/tools/myip?key={this.apikey}");
|
||||
return MakeRequestAsync<string>(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method returns a list of port numbers that the crawlers are looking for.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<List<int>> GetPortsAsync()
|
||||
{
|
||||
var builder = new Uri($"{BasePath}/shodan/ports?key={this.apikey}");
|
||||
return MakeRequestAsync<List<int>>(builder);
|
||||
}
|
||||
|
||||
private async static Task<T> MakeRequestAsync<T>(Uri url, HttpContent content = null, RequestType requstType = RequestType.GET)
|
||||
where T : class
|
||||
{
|
||||
if(requstType != RequestType.GET && content == null)
|
||||
{
|
||||
throw new ShodanException($"Request type {requstType} requires content");
|
||||
}
|
||||
if(requstType == RequestType.DELETE || requstType == RequestType.PUT)
|
||||
{
|
||||
throw new NotImplementedException("Put and Delete requests have not been implemented properly");
|
||||
}
|
||||
using(var client = new HttpClient())
|
||||
{
|
||||
HttpResponseMessage connection = null;
|
||||
if(requstType == RequestType.GET)
|
||||
{
|
||||
connection = await client.GetAsync(url);
|
||||
}
|
||||
else if(requstType == RequestType.POST)
|
||||
{
|
||||
connection = await client.PostAsync(url, content);
|
||||
}
|
||||
|
||||
var statusCode = (int)connection.StatusCode;
|
||||
if(statusCode != 200 && statusCode != 201 && statusCode == 202)
|
||||
{
|
||||
//todo error handle
|
||||
return null;
|
||||
}
|
||||
var readResult = await connection.Content.ReadAsStringAsync();
|
||||
if(typeof(T) == typeof(string))
|
||||
{
|
||||
return readResult as T;
|
||||
}
|
||||
return JsonConvert.DeserializeObject<T>(readResult);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns information about the Shodan account linked to this API key.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<Profile> GetProfileAsync()
|
||||
{
|
||||
var url = new Uri($"{BasePath}/account/profile?key={apikey}");
|
||||
return MakeRequestAsync<Profile>(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method returns an object containing all the protocols that can be used when launching an Internet scan.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<Dictionary<string, string>> GetProtocolsAsync()
|
||||
{
|
||||
var url = new Uri($"{BasePath}/shodan/protocols?key={this.apikey}");
|
||||
return MakeRequestAsync<Dictionary<string, string>>(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to obtain a list of search queries that users have saved in Shodan.
|
||||
/// </summary>
|
||||
/// <param name="page"> Page number to iterate over results; each page contains 10 items </param>
|
||||
/// <param name="sort"> Sort the list based on a property. Possible values are: votes, timestamp </param>
|
||||
/// <param name="order">Whether to sort the list in ascending or descending order. Possible values are: asc, desc </param>
|
||||
/// <returns></returns>
|
||||
public Task<SearchQueries> GetQueriesAsync(int? page = null, SortOptions? sort = null, OrderOption? order = null)
|
||||
{
|
||||
var url = new UriBuilder($"{BasePath}/shodan/query")
|
||||
{
|
||||
Query = $"key={apikey}"
|
||||
};
|
||||
if(sort.HasValue)
|
||||
{
|
||||
var sortName = Enum.GetName(typeof(SortOptions), sort.Value);
|
||||
url.Query = $"{url.Query}&sort={sortName}";
|
||||
}
|
||||
if(order.HasValue)
|
||||
{
|
||||
var orderName = Enum.GetName(typeof(OrderOption), order.Value);
|
||||
url.Query = $"{url.Query}&order={orderName}";
|
||||
}
|
||||
return MakeRequestAsync<SearchQueries>(url.Uri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to search the directory of search queries that users have saved in Shodan.
|
||||
/// </summary>
|
||||
/// <param name="query"> What to search for in the directory of saved search queries. </param>
|
||||
/// <param name="page">Page number to iterate over results; each page contains 10 items </param>
|
||||
/// <returns></returns>
|
||||
public Task<SearchQueries> SearchQueriesAsync(string query, int? page = null)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
throw new ArgumentNullException(query);
|
||||
}
|
||||
var url = new UriBuilder($"{BasePath}/shodan/query/search")
|
||||
{
|
||||
Query = $"key={apikey}&query={query}"
|
||||
};
|
||||
if(page != null)
|
||||
{
|
||||
url.Query = $"{url.Query}&page={page}";
|
||||
}
|
||||
return MakeRequestAsync<SearchQueries>(url.Uri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check the progress of a previously submitted scan request
|
||||
/// </summary>
|
||||
/// <param name="id">the unique scan ID that was returned by <see cref="RequstScanAsync(string)"/></param>
|
||||
/// <returns></returns>
|
||||
public Task<ScanStatus> GetScanStatusAsync(string id)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(id));
|
||||
}
|
||||
var url = new Uri($"{BasePath}/shodan/scan/{id}");
|
||||
return MakeRequestAsync<ScanStatus>(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method returns an object containing all the services that the Shodan crawlers look at. It can also be used as a quick and practical way to resolve a port number to the name of a service
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<Dictionary<string, string>> GetServicesAsync()
|
||||
{
|
||||
var url = new Uri($"{BasePath}/shodan/services?key={this.apikey}");
|
||||
return MakeRequestAsync<Dictionary<string, string>>(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to obtain a list of popular tags for the saved search queries in Shodan.
|
||||
/// </summary>
|
||||
/// <param name="size">The number of tags to return </param>
|
||||
/// <returns></returns>
|
||||
public Task<TagResult> GetTagsAsync(int size = 10)
|
||||
{
|
||||
var url = new UriBuilder($"{BasePath}/shodan/query/tags")
|
||||
{
|
||||
Query = $"key={apikey}&size={size}"
|
||||
};
|
||||
return MakeRequestAsync<TagResult>(url.Uri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to request Shodan to crawl the Internet for a specific port.
|
||||
/// This method is restricted to security researchers and companies with a Shodan Data license. To apply for access to this method as a researcher, please email jmath@shodan.io with information about your project. Access is restricted to prevent abuse.
|
||||
/// </summary>
|
||||
/// <param name="port">The port that Shodan should crawl the Internet for. </param>
|
||||
/// <param name="protocol">The name of the protocol that should be used to interrogate the port. See <see cref="GetProtocolsAsync"/> for a list of supported protocols. </param>
|
||||
/// <returns></returns>
|
||||
public Task<ScanPortResult> RequestInternetPortScanAsync(int port, string protocol)
|
||||
{
|
||||
var url = new Uri($"{BasePath}/shodan/scan/internet?key={this.apikey}");
|
||||
using(var data = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>() {
|
||||
new KeyValuePair<string, string>("port", port.ToString()),
|
||||
new KeyValuePair<string, string>("protocol", protocol)
|
||||
}))
|
||||
{
|
||||
return MakeRequestAsync<ScanPortResult>(url, data, RequestType.POST);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to request Shodan to crawl a network
|
||||
/// <strong>Requirements:</strong> This method uses API scan credits: 1 IP consumes 1 scan credit. You must have a paid API plan (either one-time payment or subscription) in order to use this method
|
||||
/// </summary>
|
||||
/// <param name="ips"></param>
|
||||
/// <returns></returns>
|
||||
public Task<ScanResult> RequstScanAsync(string ips)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(ips))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ips));
|
||||
}
|
||||
if(!ips.Split(',').Any())
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"{ips} must have one valid record");
|
||||
}
|
||||
var url = new Uri($"{BasePath}/shodan/scan?key={this.apikey}");
|
||||
using(var data = new FormUrlEncodedContent(new KeyValuePair<string, string>[] { new KeyValuePair<string, string>("ips", ips) }))
|
||||
{
|
||||
return MakeRequestAsync<ScanResult>(url, data, RequestType.POST);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Look up the hostnames that have been defined for the given list of IP addresses
|
||||
/// </summary>
|
||||
/// <param name="ips">Comma-separated list of IP addresses; example "74.125.227.230,204.79.197.200"</param>
|
||||
/// <returns></returns>
|
||||
public Task<Dictionary<string, List<string>>> ReverseLookupAsync(string ips)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(ips))
|
||||
{
|
||||
throw new ArgumentNullException(ips);
|
||||
}
|
||||
var url = new Uri($"{BasePath}/dns/reverse?ips={ips}&key={this.apikey}");
|
||||
return MakeRequestAsync<Dictionary<string, List<string>>>(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/Shodan.Net/ShodanException.cs
Normal file
22
src/Shodan.Net/ShodanException.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Shodan.Net
|
||||
{
|
||||
public class ShodanException : Exception
|
||||
{
|
||||
public ShodanException()
|
||||
{
|
||||
}
|
||||
|
||||
public ShodanException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public ShodanException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/Shodan.Net/project.json
Normal file
17
src/Shodan.Net/project.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.5.0-rc2-24027",
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-24027",
|
||||
"System.Dynamic.Runtime": "4.0.11-rc2-24027",
|
||||
"Newtonsoft.Json": "8.0.3",
|
||||
"System.Diagnostics.TraceSource": "4.0.0-rc2-24027"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netstandard1.5": {
|
||||
"imports": "dnxcore50"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user