Properly Attach to existing chrome driver with C# Selenium Webdriver - c#

I have used this method designed by Tarun Lalwani to attach a Selenium Chrome driver by reusing the url and the sessionID in C#. This attach is partly working but some driver methods such as FindElement(By.ID) display error "invalid argument: invalid locator (Session info: chrome=91.0.4472.114)" on this line:
var respBase = base.Execute(driverCommandToExecute, parameters);
My guess is that it is due to options or desired capabilities are empty when the driver is attached.But I havent find a way to properly set it on ReuseRemoteWebDriver.
I include an image of the look of the attached driver
here.
How can I solve this issue so I can attach the previous chrome driver and keep all expected selenium functionalities?
static void Main(string[] args)
{
InputSimulator teclado = new InputSimulator();
ChromeOptions options = new ChromeOptions();
options.UseSpecCompliantProtocol = true;
ChromeDriverService service = ChromeDriverService.CreateDefaultService(#"Thepathofchromedriver");
IWebDriver driver;
DesiredCapabilities capabilities = new DesiredCapabilities();
Uri myUri = new Uri("http://127.0.0.1:65431", UriKind.Absolute);
service.Port = 65431;
string ID = "1f42d5f0ad105910e8d2fc7be23480a9";
if (ID != "")
{
IWebDriver drivertest1 = new ChromeDriver(service, options);
IWebDriver drivertest = new ReuseRemoteWebDriver(myUri, ID,capabilities,options);
driver = drivertest;
}
else
{
IWebDriver drivertest = new ChromeDriver(service,options);
driver = drivertest;
}
IWebElement inputUser = driver.FindElement(By.Id("ID"));}
public class ReuseRemoteWebDriver : OpenQA.Selenium.Remote.RemoteWebDriver
{
private String _sessionId;
public ReuseRemoteWebDriver(Uri remoteAddress, String sessionId, OpenQA.Selenium.Remote.DesiredCapabilities capability, ChromeOptions options)
: base(remoteAddress,options)
{
this._sessionId = sessionId;
var sessionIdBase = this.GetType()
.BaseType
.GetField("sessionId",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic);
sessionIdBase.SetValue(this, new OpenQA.Selenium.Remote.SessionId(sessionId));
}
protected override OpenQA.Selenium.Remote.Response
Execute(string driverCommandToExecute, System.Collections.Generic.Dictionary<string, object> parameters)
{
if (driverCommandToExecute == OpenQA.Selenium.Remote.DriverCommand.NewSession)
{
var resp = new OpenQA.Selenium.Remote.Response();
resp.Status = OpenQA.Selenium.WebDriverResult.Success;
resp.SessionId = this._sessionId;
resp.Value = new System.Collections.Generic.Dictionary<String, Object>();
return resp;
}
var respBase = base.Execute(driverCommandToExecute, parameters);
return respBase;
}
}
UPDATE: I could fix most issues, as I indicated in the reply.
the most important functionality I couldn't manage to recover was the inject js scripts with
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
var script = "your script";
js.ExecuteScript(script);
Any idea regarding how to recover the inject script functionality would be appreciated.

In case anyone is interested, I modified the previous class as following, so I can use the sendKeysToElement
public class ReuseRemoteWebDriver : OpenQA.Selenium.Remote.RemoteWebDriver
{
private String _sessionId;
public ReuseRemoteWebDriver(Uri remoteAddress, String sessionId, ChromeOptions options, ChromeDriverService service)
: base(remoteAddress, options)
{
//object x = driver;
this._sessionId = sessionId;
var sessionIdBase = this.GetType()
.BaseType
.GetField("sessionId",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic);
//System.Collections.Generic.Dictionary<string, object> x = this.GetCapabilitiesDictionary(capability);
sessionIdBase.SetValue(this, new OpenQA.Selenium.Remote.SessionId(sessionId));
}
protected override OpenQA.Selenium.Remote.Response
Execute(string driverCommandToExecute, System.Collections.Generic.Dictionary<string, object> parameters)
{
if (driverCommandToExecute == OpenQA.Selenium.Remote.DriverCommand.NewSession)
{
var resp = new OpenQA.Selenium.Remote.Response();
resp.Status = OpenQA.Selenium.WebDriverResult.Success;
resp.SessionId = this._sessionId;
resp.Value = new System.Collections.Generic.Dictionary<String, Object>();
return resp;
}
if (driverCommandToExecute == "sendKeysToElement")
{
object[] array = (object[])parameters["value"];
string stringfinal = (string)array[0].ToString();
parameters.Add("text", stringfinal);
}
if (driverCommandToExecute == "executeScript")
{
Console.WriteLine("");
}
var respBase = base.Execute(driverCommandToExecute, parameters);
return respBase;
}
}
}
In other class I used the following method to properly used Selenium waits.
public Boolean WaitInteligente(WebDriverWait wait, string condition, By selector = null,
IWebElement optionalWebElement = null,string optionalstring = null,
bool optionalbool = false,bool devolverexcepcion=true )
{
TimeSpan Tiempo = wait.Timeout;
var globalclock = Stopwatch.StartNew();
Boolean stop = false;
double segundos = globalclock.Elapsed.TotalSeconds;
Exception exception = null;
//globalclock.Stop();
while (segundos <= Tiempo.TotalSeconds)
{
Thread.Sleep(500);
try
{
segundos = globalclock.Elapsed.TotalSeconds;
if (condition == "ElementExists")
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(selector));
if (condition == "ElementIsVisible")
wait.Until(ExpectedConditions.ElementIsVisible(selector));
if (condition == "ElementToBeClickable")
wait.Until(ExpectedConditions.ElementToBeClickable(selector));
if (condition == "ElementToBeSelected")
wait.Until(ExpectedConditions.ElementToBeSelected(selector));
if (condition == "FrameToBeAvailableAndSwitchToIt")
wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(selector));
if (condition == "InvisibilityOfElementLocated")
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(selector));
if (condition == "PresenceOfAllElementsLocatedBy")
wait.Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(selector));
if (condition == "VisibilityOfAllElementsLocatedBy")
wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(selector));
if (condition == "AlertIsPresent")
wait.Until(ExpectedConditions.AlertIsPresent());
if (condition == "ElementToBeSelected")
wait.Until(ExpectedConditions.ElementToBeSelected(optionalWebElement));
if (condition == "InvisibilityOfElementWithText")
wait.Until(ExpectedConditions.InvisibilityOfElementWithText(selector,optionalstring));
if (condition == "StalenessOf")
wait.Until(ExpectedConditions.StalenessOf(optionalWebElement));
if (condition == "TextToBePresentInElement")
wait.Until(ExpectedConditions.TextToBePresentInElement(optionalWebElement,optionalstring));
if (condition == "TextToBePresentInElementLocated")
wait.Until(ExpectedConditions.TextToBePresentInElementLocated(selector, optionalstring));
if (condition == "TextToBePresentInElementValue")
wait.Until(ExpectedConditions.TextToBePresentInElementValue(selector, optionalstring));
if (condition == "TitleContains")
wait.Until(ExpectedConditions.TitleContains(optionalstring));
if (condition == "TitleIs")
wait.Until(ExpectedConditions.TitleIs(optionalstring));
if (condition == "UrlContains")
wait.Until(ExpectedConditions.UrlContains(optionalstring));
if (condition == "UrlMatches")
wait.Until(ExpectedConditions.UrlMatches(optionalstring));
if (condition == "UrlToBe")
wait.Until(ExpectedConditions.UrlToBe(optionalstring));
if (condition == "FrameToBeAvailableAndSwitchToIt")
wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(optionalstring));
if (condition == "AlertState")
wait.Until(ExpectedConditions.AlertState(optionalbool));
if (condition == "ElementSelectionStateToBe")
wait.Until(ExpectedConditions.ElementSelectionStateToBe(selector,optionalbool));
if (condition == "ElementSelectionStateToBe")
wait.Until(ExpectedConditions.ElementSelectionStateToBe(selector, optionalbool));
stop = true;
break;
}
catch (Exception e)
{
e = new Exception(selector.ToString() + condition + e.Message);
exception = e;
}
}
if (!stop && devolverexcepcion)
throw exception;
return stop;
}
The methods that are not working properly when attached are
driver.FindElement(By.Id) and driver.FindElement(By.ClassName) which can be easily circumvented by using a By.CssSelector call to the ID or Classname respectively.
The most important functionality I couldn't recover was the inject js scripts with
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
var script = "your script";
js.ExecuteScript(script);
Any idea regarding how to recover the inject script functionality would be appreciated.

Related

How can I make an auto injection detector in c#?

I want to make an auto injection scanner in any given website and I have to use c#.
I tried some things that I found online and none of them worked for me, until i find selenium but i keep getting this error message: "OpenQA.Selenium.ElementNotInteractableException: 'element not interactable", and I have no idea why.
I didn't find anything helpful online and I think the problem may be with selenium.
I tried to find SQL, JS and BASH injections, but the script fails when i try to interact with an input. I am using OWASP juice shop to test my code.
This is my code:
static int _crntTypeOfInjection;
const int ESQL = 0, EJS = 1, EBASH = 2;
static public bool IsImportantInput(string type)
{
bool valid = false;
string[] importantTypes = new string[] { "text", "email", "password", "search", "url" };
foreach (string check in importantTypes)
{
if (type == check)
{
return true;
}
}
return false;
}
public static string getCrntInjection()
{
switch (_crntTypeOfInjection)
{
case ESQL:
return "\' OR 1=1;--";
break;
case EBASH:
return "; echo Test";
break;
case EJS:
return "<img src=\"http:\\\\url.to.file.which\\not.exist\" onerror=alert(\"JS injection success\");>";
break;
}
return "defult";
}
static public bool AttackSuccessful(string normalPage, string InjectedPage, string MainUrl, string afterClickUrl)
{
if (afterClickUrl != MainUrl || InjectedPage.Contains("Internal Server Error") || InjectedPage.Contains("JS injection success") || InjectedPage.Contains("Test"))
{
return true;
}
return false;
}
static public void Injection(string url)
{
string InjectedPage = "", NormalPage = "", AfterClickUrl = "";
var driver = new ChromeDriver("C:\\Users\\nirya\\");
driver.Url = url;
Console.WriteLine(driver.PageSource);
Actions a = new Actions(driver);
foreach (var button in driver.FindElements(By.CssSelector("button")))
{
// INJECTED PAGE
a.MoveByOffset(0, 0).Click().Perform();
foreach (IWebElement input in driver.FindElements(By.TagName("input")))
{
Console.WriteLine(input.Text);
Console.WriteLine(input.TagName);
try
{
if (IsImportantInput(input.GetAttribute("type")))
{
input.Click(); // *** HERE IS THE PROBLEM ***
input.Clear();
input.SendKeys(getCrntInjection());
}
}
catch (NoSuchElementException)
{
continue;
}
}
button.Click();
InjectedPage = driver.PageSource;
AfterClickUrl = driver.Url;
driver.Navigate().Back();
// NORMAL PAGE
a.MoveByOffset(0, 0).Click().Perform();
foreach (IWebElement input in driver.FindElements(By.CssSelector("input")))
{
try
{
if (IsImportantInput(input.GetAttribute("type")))
{
input.Clear();
input.SendKeys("normal");
}
}
catch (NoSuchElementException)
{
continue;
}
}
button.Click();
NormalPage = driver.PageSource;
driver.Navigate().Back();
if (AttackSuccessful(NormalPage, InjectedPage, url, AfterClickUrl))
{
// add to database
}
}
}
static void Main(string[] args)
{
Injection("http://localhost:3000/#/login");
}
Is there a problem with my code? Or is there another library that i can use instead?

Program closes instead of getting info from API

Okay so I'm still quite new to coding and mostly only knows the basics. I have never worked with API. I'm trying to make a program that gets the number of subs from PewDiePie and Cocomelon and compare them.
namespace PewdiepieVsCoco
{
class Program
{
static void Main(string[] args)
{
try
{
var len = args?.Length;
if (len == null || len.Value == 0)
{
PrintStart();
return;
}
var pdpSubCount = args[0];
var pdpSub = GetPDPSubcount(pdpSubCount).Result;
PrintPDPResult(pdpSub);
}
catch (AggregateException agg)
{
foreach (var e in agg.Flatten().InnerExceptions)
Console.WriteLine(e.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
private static async Task<dynamic> GetPDPSubcount(string pdpSubCount)
{
var parameters = new Dictionary<String, String>
{
["key"] = ConfigurationManager.AppSettings["APIKey"],
["channelsId"] = "UC-lHJZR3Gqxm24_Vd_AJ5Yw",
["part"] = "statistics",
["forUsername"] = "PewDiePie",
["fields"] = "items/statistics(subscriberCount)"
};
var baseUrl = "https://www.googleapis.com/youtube/v3/channels";
var fullUrl = MakeUrlWithQuery(baseUrl, parameters);
var pdpSub = await new HttpClient().GetStringAsync(fullUrl);
if (pdpSub != null)
{
//Does the thing
return JsonConvert.DeserializeObject(pdpSubCount);
}
return default(dynamic);
}
private static string MakeUrlWithQuery(string baseUrl,
IEnumerable<KeyValuePair<string, string>> parameters)
{
if (string.IsNullOrEmpty(baseUrl))
throw new ArgumentException(nameof(baseUrl));
if (parameters == null || parameters.Count() == 0)
return baseUrl;
return parameters.Aggregate(baseUrl,
(accumulated, kvp) => string.Format($"{accumulated}{kvp.Value}&"));
}
private static void PrintPDPResult(dynamic pdpSub)
{
Console.WriteLine($"PewDiePie currently have: {pdpSub} subscribers");//insert subs
}
private static void PrintStart()
{
Console.WriteLine("The war is on!");
Thread.Sleep(500);
Console.WriteLine("PewDiePie Vs Cocomelon – Nursery Rhymes");
Thread.Sleep(500);
}
}
}
Here is the code, I have followed what an Indian dude did in a YT video so some things I don't know what do but I have an idea on what's going on.
Your program is likely returning before making any API calls because you aren't executing it with any command line arguments. Remove this block of code, so it continues without returning early.
var len = args?.Length;
if (len == null || len.Value == 0)
{
PrintStart();
return;
}
Also, pdpSubCount should not be a function argument, and should not be passed into DeserializeObject. You should be deserializing the response from the api call
return JsonConvert.DeserializeObject(pdpSub)

iewebdriverserver. Internet Explorer changes system proxy instead of browser proxy

IE changes the system proxy instead of the browser proxy, what can go wrong?
I tried changing the property UsePerProcessProxy, but it did not fix it.
Please see the code below
public InternetExplorerOptions GetOptions()
{
InternetExplorerOptions options = new InternetExplorerOptions
{
IntroduceInstabilityByIgnoringProtectedModeSettings = true,
InitialBrowserUrl = "about:blank",
EnableNativeEvents = true,
EnsureCleanSession = true,
EnablePersistentHover = false,
PageLoadStrategy = InternetExplorerPageLoadStrategy.Normal,
};
options.UsePerProcessProxy = true;
options.Proxy = GetProxy();
return options;
}
public override IWebDriver CreateRemoteDriver()
{
var options = GetOptions();
foreach (var capability in CapabilityProperties)
{
options.AddAdditionalCapability(capability.Name, capability.Value);
}
return new RemoteWebDriver(new Uri(GridUri), options.ToCapabilities());
}
public Proxy GetProxy()
{
if (Proxy != null || ProxyAutoConfigUrl != null)
{
var proxy = new Proxy();
proxy.AddBypassAddresses("localhost", "127.0.0.1");
if (ProxyAutoConfigUrl != null)
{
proxy.Kind = ProxyKind.ProxyAutoConfigure;
proxy.ProxyAutoConfigUrl = ProxyAutoConfigUrl;
}
if (Proxy != null)
{
proxy.Kind = ProxyKind.Manual;
proxy.HttpProxy = Proxy;
proxy.SslProxy = Proxy;
}
return proxy;
}
return null;
}
Selenium Standalone Server version 3.10.0
iewebdriverserver 3.9.0 32 bit

How do I wait for a delegate to return a certain value?

I am currently using Selenium WebDriverWait to wait for things to happend where I don't need the IWebDriver functionality. My code looks like this:
public static T WaitForNotNull<T>(this IWebDriver driver, Func<T> func)
{
var result = default(T);
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => (result = func()) != null);
return result;
}
public static void WaitForNull<T>(this IWebDriver driver, Func<T> func)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => func() == null);
}
Is there a similar construct in .Net which I can use instead of WebDriverWait?
The answer is
No
There is no such thing in the .NET Framework, you will have to write such a method yourself.
This is the original Until implementation (source). You can improve it IMO.
And if you don't want to block the calling thread (in case of UI thread), you can easily use the async\await pattern
public TResult Until<TResult>(Func<T, TResult> condition)
{
if (condition == null)
{
throw new ArgumentNullException("condition", "condition cannot be null");
}
var resultType = typeof(TResult);
if ((resultType.IsValueType && resultType != typeof(bool)) || !typeof(object).IsAssignableFrom(resultType))
{
throw new ArgumentException("Can only wait on an object or boolean response, tried to use type: " + resultType.ToString(), "condition");
}
Exception lastException = null;
var endTime = this.clock.LaterBy(this.timeout);
while (true)
{
try
{
var result = condition(this.input);
if (resultType == typeof(bool))
{
var boolResult = result as bool?;
if (boolResult.HasValue && boolResult.Value)
{
return result;
}
}
else
{
if (result != null)
{
return result;
}
}
}
catch (Exception ex)
{
if (!this.IsIgnoredException(ex))
{
throw;
}
lastException = ex;
}
// Check the timeout after evaluating the function to ensure conditions
// with a zero timeout can succeed.
if (!this.clock.IsNowBefore(endTime))
{
string timeoutMessage = string.Format(CultureInfo.InvariantCulture, "Timed out after {0} seconds", this.timeout.TotalSeconds);
if (!string.IsNullOrEmpty(this.message))
{
timeoutMessage += ": " + this.message;
}
this.ThrowTimeoutException(timeoutMessage, lastException);
}
Thread.Sleep(this.sleepInterval);
}
}

Get url from firefox 8 not working anymore

I have a windows applicaiton c# catching the url of a running firefox instance.
I have always used "MozillaContentWindow" to get firefox URL but i dont understand why it dont work anymore.
string s = GetUrlFromBrowsersWithIdentifier("MozillaContentWindow", foreGround);
public string GetUrlFromBrowsersWithIdentifier(string identifier, int foreground)
{
try
{
IntPtr ptr = new IntPtr(foreground);
var aeBrowser = AutomationElement.FromHandle(ptr);
return aeBrowser == null ? "" : GetURLfromBrowser(aeBrowser, identifier);
}
catch (Exception ex)
{
return "";
}
}
string GetURLfromBrowser(AutomationElement rootElement, string identifier)
{
try
{
Condition condition1 = new PropertyCondition(AutomationElement.IsContentElementProperty, true);
Condition condition2 = new PropertyCondition(AutomationElement.ClassNameProperty, identifier);
var walker = new TreeWalker(new AndCondition(condition1, condition2));
var elementNode = walker.GetFirstChild(rootElement);
if (elementNode != null)
{
var p = elementNode.GetSupportedPatterns();
if (p.Any(autop => autop.ProgrammaticName.Equals("ValuePatternIdentifiers.Pattern")))
{
var valuePattern = elementNode.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
if (valuePattern != null)
return (valuePattern.Current.Value);
}
}
}
catch
{
return "";
}
return "";
}
Now when it enters "walker.GetFirstChild(rootElement);" it just stops there. I cant figure out why. This only happend on latest version of firefox.
Did they change the name of the value bar containing the url?
Thank you
Try using MozillaWindowContentClass for newer versions.

Categories

Resources