Reverse engineering Android app to work out BLE handshake encryption - encryption

I have a BLE device (pool chlorinator) that I would like to control with a custom client, so I can integrate into Home Assistant.
I have sniffed the the BLE packets but the GATT payloads appear to be encrypted. I have decompiled the Android client app to see if I can resolve how to encrypt/decrypt.
Appears to be a Xamarin thing.
The manufacturer supplies an iOS app and an Android app.
I have downloaded and unpacked the android apk, and looked through a bunch of the assemblies using ILSpy.
There appears to be a static SecretKey that is used for creating a session key, but I can't work out how it is initialised.
static Settings()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
List<DeviceType> obj = new List<DeviceType>();
obj.Add((DeviceType)1);
obj.Add((DeviceType)129);
ValidDeviceTypes = obj;
LOADER_V1_DEVICE_NAME = "DfuTarg";
LOADER_V2_DEVICE_NAME = "DFU";
LandscapeScreenProportion = 0.5;
byte[] array = new byte[16];
RuntimeHelpers.InitializeArray((global::System.Array)array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
SecretKey = array;
}
How might I work out what SecretKey is?
Maybe the IL code could be inspected (foreign to me)?
Could I build an executable that runs the constructor in the dll somehow?

Related

How should I sign a CSR using a signature created in HSM, in C# .NET Core?

I'm exhausted after looking for an answer for 3 days. I don't know if my suggested flow is wrong or my Google skills have really deteriorated.
My API needs to create a valid certificate from a CSR it received, by signing it with a private key that exists ONLY inside an HSM-like service (Azure KeyVault), which unfortunately doesn't offer Certificate Authority functions BUT does offer signing data with a key that exists there. My CA certificate's private key is stored in the HSM. I'm using ECDSA.
My suggested flow:
Client generates Key Pair + CSR and sends CSR to API
API creates a certificate from the CSR
API asks HSM to sign the CSR data and receives back a signature
API appends the signature to the certificate and returns a signed (and including CA in chain) certificate to the Client
I'm using C# .NET Core and would like to keep it cross-platform (as it runs in Linux containers), so I have to keep it as native as possible or using Bouncy Castle (which I'm still not sure if runs in Linux .NET Core).
I really appreciate your help!
I had faced a similar issue and found a solution. You'll have to use the PKCS11Interop.X509Store library.
The solution uses dotnet core native System.Security.Cryptography.X509Certificates.CertificateRequest::Create method
for generating a certificate.
As per the docs:
Pkcs11Interop is managed library written in C# that brings the
full power of PKCS#11 API to the .NET environment
Pkcs11Interop.X509Store is managed library built on top of
Pkcs11Interop. It's main goal is to provide easy to use PKCS#11 based
read-only X.509 certificate store that can be easily integrated with
standard .NET ecosystem.
Till v0.3.0, implementation for issuing a certificate (i.e signing a CSR) is not available.
With minor modifications in the PKCS11Interop library, I was able to sign the CSR.
Mentioned in Issue #30, the code is now added in the PKCS11Interop.X509Store library version 0.4.0.
The below code is taken from test cases for BasicEcdsaCertificateRequestTest. Test cases for RSA CertificateRequest are also there.
// Load PKCS#11 based store
using (var pkcs11Store = new Pkcs11X509Store(SoftHsm2Manager.LibraryPath, SoftHsm2Manager.PinProvider))
{
// Find signing certificate (CA certificate)
Pkcs11X509Certificate pkcs11CertOfCertificateAuthority = Helpers.GetCertificate(pkcs11Store, SoftHsm2Manager.Token1Label, SoftHsm2Manager.Token1TestUserEcdsaLabel);
// Generate new key pair for end entity
ECDsa ecKeyPairOfEndEntity = ECDsa.Create(ECCurve.NamedCurves.nistP256);
// Define certificate request
CertificateRequest certificateRequest = new CertificateRequest(
new X500DistinguishedName("C=SK,L=Bratislava,CN=BasicEcdsaCertificateRequestTest"),
ecKeyPairOfEndEntity,
HashAlgorithmName.SHA256);
// Define certificate extensions
certificateRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, true));
certificateRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(certificateRequest.PublicKey, false));
certificateRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature, false));
// Issue X.509 certificate for end entity
X509Certificate2 certificateOfEndEntity = certificateRequest.Create(
pkcs11CertOfCertificateAuthority.Info.ParsedCertificate.SubjectName,
X509SignatureGenerator.CreateForECDsa(pkcs11CertOfCertificateAuthority.GetECDsaPrivateKey()),
DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddDays(365),
new BigInteger(1).ToByteArray());
// Verify signature on X.509 certificate for end entity
Assert.IsTrue(CaCertSignedEndEntityCert(pkcs11CertOfCertificateAuthority.Info.ParsedCertificate.RawData, certificateOfEndEntity.RawData));
// Asociate end entity certificate with its private key
certificateOfEndEntity = certificateOfEndEntity.CopyWithPrivateKey(ecKeyPairOfEndEntity);
// Export end entity certificate to PKCS#12 file
string basePath = Helpers.GetBasePath();
string pkcs12FilePath = Path.Combine(basePath, "BasicEcdsaCertificateRequestTest.p12");
File.WriteAllBytes(pkcs12FilePath, certificateOfEndEntity.Export(X509ContentType.Pkcs12, "password"));
}
Hope this helps.

Signalr send message from browser to .net client on the same machine

We need to communicate a native application with a web application.
We think to use signalr to send the message/command.
The pipeline would be:
User clicks to make an action.
Javascript (with signalr) send a message to a server in azure.
The server re-send the message a specific client. It must be the client installed on the same machine.
Once the result is completed, NET sends the resulting reverse.
The matter is, How I can find client from the same machine in the signalr Server?
The organization in our system is:
There is center/gym.
Every center has staff who can login.
We could identify client at the same center with some file configuration. Saving our key center, for example. But, in a center, could there are more than one.NET client installed on the different computer.
We think to use the private IP of the computer to make a key on the signalr server.
var ips = [];
var RTCPeerConnection = window.RTCPeerConnection ||
window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
var pc = new RTCPeerConnection({
// Don't specify any stun/turn servers, otherwise you will
// also find your public IP addresses.
iceServers: []
});
// Add a media line, this is needed to activate candidate gathering.
pc.createDataChannel('');
// onicecandidate is triggered whenever a candidate has been found.
pc.onicecandidate = function (e) {
if (!e.candidate) { // Candidate gathering completed.
pc.close();
console.log(ips);
return;
}
var ip = /^candidate:.+ (\S+) \d+ typ/.exec(e.candidate.candidate)[1];
ips.push(ip);
};
pc.createOffer(function (sdp) {
pc.setLocalDescription(sdp);
}, function onerror() { });
This data can be obtained in .NET client without a problem. But in javascript, the previous code works regularly. In some PC, it only returns ipv4. And in Mozilla it doesn't work.
How can we identify both clients? Do You know another way to reach the goal?
Thanks,
Finally, we didn't find a good solution filtering ip adress.
We did the as follow:
We used URI schema to launch our app. URI Schema windows
Public Class RegistrarURI
Const URI_SCHEME As String = "xxx"
Const URI_KEY As String = "URL:xxx"
Private Shared APP_PATH As String = Location.AssemblyDirectory() ' "C:\Program Files (x86)\xxx.exe"
Public Shared Sub RegisterUriScheme()
Using hkcrClass As RegistryKey = Registry.ClassesRoot.CreateSubKey(URI_SCHEME)
hkcrClass.SetValue(Nothing, URI_KEY)
hkcrClass.SetValue("URL Protocol", [String].Empty, RegistryValueKind.[String])
Using defaultIcon As RegistryKey = hkcrClass.CreateSubKey("DefaultIcon")
Dim iconValue As String = [String].Format("""{0}"",0", APP_PATH)
defaultIcon.SetValue(Nothing, iconValue)
End Using
Using shell As RegistryKey = hkcrClass.CreateSubKey("shell")
Using open As RegistryKey = shell.CreateSubKey("open")
Using command As RegistryKey = open.CreateSubKey("command")
Dim cmdValue As String = [String].Format("""{0}"" ""%1""", APP_PATH)
command.SetValue(Nothing, cmdValue)
End Using
End Using
End Using
End Using
End Sub
End Class
In an Azure WebApp we launch a SignalR Server. This server will send data from our .NET app to Chrome.
To achive that, when the web is loaded, we connect to the signalR server. To build de uri, We send the connectionId from Javascript client to the .NET Client.
Then, when the native process is completed. .NET client send the information to signalR server, and this server mirrored the data to javacript client using the connectionId.
To avoid launch some instance of our native app, we use IPC channel to send data to one instance to the previous and closind the new one.
Link to source Blog source

Apple Push Notifications on Windows Server 2008 not working

I'm stuck and I hope somebody here will help me.
For a few days I'm trying to send apple push notifications from windows server 2008. But nothing is send or received. In fact, I've moved everything to simple mvc application so it can be debug easier and I've noticed that it hangs when I try to force sending the push notifications (on push.StopAllServices(true); )
They were working (and still are) from windows server 2012R2 with the same approach to send notifications so I guess the certificates and code are fine.
I'm using windows service & push sharp to send notifications. target framework: 4
The test project is MVC 2.0 target framework 4
I've installed asp.net 4.5 on the server
I've installed certificate via mmc in Personal (the private key is available, granted permission for IUSR and IIS_USRS) and Trusted Root Certificate Authorities.
Port 2195 is open
Here's the code:
private void Initizalize()
{
push = new PushBroker();
//appleCert is path to my .p12 certificate on disk.
var cert = new ApplePushChannelSettings(false, appleCert, "***");
//I've read somewhere that it was helpful to force send notifications. Well, in my case it's not.
var settings = new PushServiceSettings();
settings.AutoScaleChannels = false;
settings.Channels = 3;
settings.MaxAutoScaleChannels = 3;
//Wire up the events for all the services that the broker registers
push.OnNotificationSent += NotificationSent;
push.OnChannelException += ChannelException;
push.OnServiceException += ServiceException;
push.OnNotificationFailed += NotificationFailed;
push.OnDeviceSubscriptionExpired += DeviceSubscriptionExpired;
push.OnDeviceSubscriptionChanged += DeviceSubscriptionChanged;
push.OnChannelCreated += ChannelCreated;
push.OnChannelDestroyed += ChannelDestroyed;
push.RegisterAppleService(cert, settings);
}
public void SendPush()
{
Initizalize();
var token = hard coded token that exists;
var output = "msg";
push.QueueNotification(new AppleNotification()
.ForDeviceToken(token)
.WithAlert(output)
.WithBadge(1)
.WithSound("default"));
push.StopAllServices(true);
}
It raises event "OnNotificationSent", nothing else.
One more thing that may be important. Sending and receiving push notifications was and is working from windows server 2012 but it's windows azure virtual machine so installing the certificate was different.
Any ideas?
Even the information that it cannot be done will be helpful!
edit:
One problem solved:
Apparently you need to have reference to NewtonSoft.Json in order to call StopAllServices. It doesn't hang now but nothing is received by the device.
Looks like on Windows Server 2008 apns certificates private key must have granted permission for user that wants to use it.
As I wrote before I've granted it for IIS_USRS but that's only for applications running under IIS. And since I was using windows service it wasn't working.
So what I did was check user for windows service (Services -> Log On As) and granted permission to certificates private key for this user.

Multiple threads in POCO HttpClient?

I am working on a project in C++, with POCO/NET. The Network code can be seen below:
URI uri("http://my.url.se" );
HTTPClientSession session(uri.getHost(), uri.getPort());
// prepare path
string path(uri.getPathAndQuery());
if (path. empty()) path = "/";
// send request
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
req.set("Accept", "AcceptString");
req.set("Consumer", "ALL");
req.set("Contract", "ALL");
session.sendRequest(req);
// recieve response
HTTPResponse res;
istream &is = session.receiveResponse(res);
The application is working on both Android 2.3.6 (Samsung Galaxy Gio) and the latest Android version, but according to the following post (and developer.android):
https://stackoverflow.com/questions/15606791/android-httppost-freezes-and-crashes-app
a NetworkOnMainThreadException would be thrown on the newest Android version (Honeycomb or higher) if the Networking part would not be in a separate thread. I have not created a new thread, so my question is:
Can anyone confirm my assumption that it is implemented already/automatically uses a new thread in the Poco Net library?
Greatful for help!
Can anyone confirm my assumption that it is implemented
already/automatically uses a new thread in the Poco Net library?
HTTPClientSession will not run on a separate thread, you will have to do that explicitly. You can use Poco:: Thread, Task or Activity.

Blackberry http connection not working on 3g

hi friends i'm a newbie in blackberry programming and have managed to make a small application... The application downloads an xml file through http and parses it and displays it on the screen... now the problem is that though it works fine on my simulator... the client complains that he's getting an error in connection if he connects it through 3G... do i need to add anything other than the following...
// Build a document based on the XML file.
url = <my clients url file>;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
hc = (HttpConnection)Connector.open(url+";deviceside=true");
hc.setRequestMethod(HttpConnection.GET);
InputStream inputStream = hc.openInputStream();
hc.getFile();
Document document = builder.parse(inputStream);
hc.close();
inputStream.close();
Do i need to add anything to make it download http content through 3G also??
Specifying "deviceside=true" requires the device have the APN correctly configured, or you include APN specification in the URL. Have a look at this video.
You need to be able to detect what sort of connection the device is using as was said above deviceside=true works only for APN. If you want to just test it out try using
;deviceside=false //for mds
;deviceside=false;ConnectionType=mds-public //for bis-b
;interface=wifi //for wifi

Resources