How do you retain uniqueness of virtual MIDI source from MIDISourceCreate()? - ios

I'm working on a little hack sending MIDI messages from an app using RtMidi as a wrapper for CoreMIDI on OS X. I use RtMidiOut::openVirtualPort("MyAwesomePort") so I can select my app as an input source in a DAW.
However, if my program closes and I open it again, my DAW does not recognize the input device as the same port, despite being given the same name.
I was originally using pyrtmidi, so went and verified the behavior writing in C++ directly with RtMidi. "My DAW" in this case is Reaper 4, but I've duplicated the behavior in Pro Tools, Logic, and MuLab.
I know it's possible to retain some uniqueness of a virtual midi port, since MidiKeys behaves just as I'd like my application to behave: my DAWs remember it even if MidiKeys closes and re-opens while my DAW is still running.
So I dug into the RtMidi source, and the CoreMIDI wrapper seemed straightforward enough. All that the MIDISourceCreate asks for is a string. The client parameter is (what I presume after browsing the docs) an identifier for my application, it being a client of the CoreMIDI services.
void RtMidiOut :: openVirtualPort( std::string portName )
{
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
if ( data->endpoint ) {
errorString_ = "RtMidiOut::openVirtualPort: a virtual output port already exists!";
error( RtError::WARNING );
return;
}
// Create a virtual MIDI output source.
MIDIEndpointRef endpoint;
OSStatus result = MIDISourceCreate( data->client,
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
&endpoint );
if ( result != noErr ) {
errorString_ = "RtMidiOut::initialize: error creating OS-X virtual MIDI source.";
error( RtError::DRIVER_ERROR );
}
// Save our api-specific connection information.
data->endpoint = endpoint;
}
So I looked at the MIDISourceCreate documentation, and read this:
After creating a virtual source, it's a good idea to assign it the same unique ID it had the last time your application created it. (Although you should be prepared for this to fail in the unlikely event of a collision.) This will permit other clients to retain persistent references to your virtual source more easily.
This seems like exactly what I'm looking for. Except I have no idea how to assign the source a unique ID. The out parameter for MIDISourceCreate is a MIDIEndpointRef, which according to the docs is just typedef'd to a UInt32 down the line. So I hypothesized that maybe I should keep track of this UInt32, but that seems like a bad idea.
After digging through all of this I feel like I'm hitting a bit of a brick wall. How do I retain the uniqueness of my MIDI port in between runs of my application?

According to the docs,
kMIDIPropertyUniqueID
The system assigns unique ID's to all objects. Creators of virtual endpoints may set this property on their endpoints, though doing so may fail if the chosen ID is not unique.
So maybe something like this:
// Try to set the ID if it's saved.
if (savedUniqueId) {
OSStatus result = MIDIObjectSetIntegerProperty(endpoint, kMIDIPropertyUniqueID, myUniqueId);
if (result == kMIDIIDNotUnique) {
savedUniqueId = 0;
}
}
// If not saved, record the system-assigned ID
if (!savedUniqueId) {
OSStatus result = MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyUniqueID, &savedUniqueId);
// Handle the error?
}
The unique ID is typedefed to a SInt32. I've made the assumption that 0 is an invalid unique ID, which is at least true for connections (the docs for kMIDIPropertyConnectionUniqueID say it's "non-existant or 0 if there is no connection").
I'm not sure how you maintain long-term uniqueness with only 32 bits, but it'll hopefully be sufficient for relaunches of your app.

Related

NativeScript: Get string from interop.reference

To start, here is my code:
var buffer = malloc(interop.sizeof(interop.types.UTF8CString));
var fillBuffer = mac.getBytes(buffer);
var bytes = new interop.Reference(interop.types.UTF8CString, buffer);
var hexMac = bytes[0];
The variable 'Mac' is an NSData objected retrieved from CoreBluetooth. It is the scan response from a BLE device, which contains the peripheral's MAC address (00:0b:57:a2:fb:a0).
This problem is linked to THIS question I had posted earlier.
The solution provided is great; however, I cannot seem to implement this in nativescript :
(instancetype)stringWithFormat:(NSString *)format, ...;
Intellisense tells me the method doesnt exist on type NSString.
Due to that issue, I decided to go another route (as you can tell). I am filling a buffer with the bytes of the MAC address. In the code above, bytes[0] equates to 0xb57a2fba0.
I am now trying to convert that (which is an interop.Reference) into a string that I can store on the back-end (preferably in the xx:xx:xx:xx:xx format).
I have been at this all weekend, and cannot seem to find a solution. I even broke down objc!foundation.d.ts to figure out if stringWithFormat was supported, to no avail.
The nativescript community slack was unable to provide a resolution as well.
Please help if you can!
I don't know anything about NativeScript at all, but given the other code you wrote, I assume you're calling +alloc first, and so mean to use -initWithFormat: (an instance method that initializes) rather than +stringWithFormat: (a class method which handles allocation and initialization).

What is the format of the optionsFile for the IotFDevice class in Quarks?

The IotfDevice Class in Quarks has a constructor with an optionsFile. What is the format of this file and what are the necessary values?
The options file has five values: org, type, id, auth-method, auth-token. This is an example of mine with the values obfuscated.
[device]
org = 4pj4r4
type = rustQuark
id = rustIIa
auth-method = token
auth-token = 8jLWEY(P4SVJl5oi!V
When you register a device the set of values are issued, details and examples can be found here.
A little context.
Internet of Things Foundation (IoTf) is an infrastructure for application's to communicate with devices. IoTf requires that you register the application and all
devices that send data to the application.
Why would you use IoTf? Getting the communication setup between devices is
a pain: firewalls, retry, failover, QoS, debugging, monitoring. This is facility especially nice if you're doing a proof of concept.
For a better description of IoTf look here.

Detect if Cycript/Substrate or gdb is attached to an iOS app's process?

I am building an iOS app that transmits sensitive data to my server, and I'm signing my API requests as an additional measure. I want to make reverse engineering as hard as possible, and having used Cycript to find signing keys of some real-world apps, I know it's not hard to find these keys by attaching to a process. I am absolutely aware that if someone is really skilled and tries hard enough, they eventually will exploit, but I'm trying to make it as hard as possible, while still being convenient for myself and users.
I can check for jailbroken status and take additional measures, or I can do SSL pinning, but both are still easy to bypass by attaching to the process and modifying the memory.
Is there any way to detect if something (whether it be Cycript, gdb, or any similar tool that can be used for cracking the process) is attached to the process, while not being rejected from App Store?
EDIT: This is not a duplicate of Detecting if iOS app is run in debugger. That question is more related to outputting and it checks an output stream to identify if there's an output stream attached to a logger, while my question is not related to that (and that check doesn't cover my condition).
gdb detection is doable via the linked stackoverflow question - it uses the kstat to determine if the process is being debugged. This will detect if a debugger is currently attached to the process.
There is also a piece of code - Using the Macro SEC_IS_BEING_DEBUGGED_RETURN_NIL in iOS app - which allows you to throw in a macro that performs the debugger attached check in a variety of locations in your code (it's C/Objective-C).
As for detecting Cycript, when it is run against a process, it injects a dylib into the process to deal with communications between the cycript command line and the process - the library has part of the name looking like cynject. That name doesn't look similar to any libraries that are present on a typical iOS app. This should be detectable with a little loop like (C):
BOOL hasCynject() {
int max = _dyld_image_count();
for (int i = 0; i < max; i++) {
const char *name = _dyld_get_image_name(i);
if (name != NULL) {
if (strstr(name, "cynject") == 0) return YES;
}
}
}
Again, giving it a better name than this would be advisable, as well as obfuscating the string that you're testing.
These are only approaches that can be taken - unfortunately these would only protect you in some ways at run-time, if someone chooses to point IDA or some other disassembler at it then you would not be protected.
The reason that the check for debugger is implemented as a macro is that you would be placing the code in a variety of places in the code, and as a result someone trying to fix it would have to patch the app in a variety of places.
Based on #petesh's answer, I found the below code achieved what I wanted on a jailbroken phone with Cycript. The existence of printf strings is gold to a reverse engineer, so this code is only suitable for demo / crack-me apps.
#include <stdio.h>
#include <string.h>
#include <mach-o/dyld.h>
int main ()
{
int max = _dyld_image_count();
for (int i = 0; i < max; i++) {
const char *name = _dyld_get_image_name(i);
const char needle[11] = "libcycript";
char *ret;
if ((ret = strstr(name, needle)) != NULL){
printf("%s\nThe substring is: %s\n", name, ret);
}
}
return 0;
}
As far as I know, Cycript process injection is made possible by debug symbols. So, if you strip out debug symbols for the App Store release (the default build setting for the Release configuration), that would help.
Another action you could take, which would have no impact on the usability of the App, would be to use an obfuscator. However, this would render any crash reports useless, since you wouldn't be able to make sense of the symbols, even if the crash report was symbolicated.

How to use ScriptProcessorNode

I am trying to create a Web Audio script processor in Dart. I noticed this question that shows using a "javascriptnode":ScriptProcessorNode
This doesn't seem to be present in the current Dart build. Does anyone have an example of how to use it. I am trying to create a BitCrusher processor.
It seems the latest api doesn't have the "onAudioProcess" method and I am guessing I should be using the "addEventListener" method but I don't know what the message type should be. I even tried the "setEventListener" method but I still don't get events.
_script = _context.createScriptProcessor(2048, 1, 1);
_script.addEventListener("message", _onProcess);
_script.setEventListener(_onProcess); //<--- this doesn't work either.
void _onProcess(Event e) { //<---- This is never called
// Perform bit crush algorithm
}
In the mean time (i.e. assuming that soon you could use directly _script.onAudioProcess) you can use the following stub
// stub as onAudioProcess has disappeared from sdk 1.7
Stream<AudioProcessingEvent> onAudioProcess(ScriptProcessorNode node) {
return node.on['audioprocess'];
}
and use it like this
onAudioProcess(_script).listen((AudioProcessingEvent event) {
// example to get output data (for playback)
Float32List data = event.outputBuffer.getChannelData(0);
// example to get input data (for recording)
Float32List data = event.inputBuffer.getChannelData(0);
});

Is there a (legal) way to capture the ENTIRE screen under iOS?

I've tried several techniques to capture a screenshot of an app from within that app. None of the techniques appear to capture the status bar -- it ends up being black.
There apparently was once a way to do this, but that interface is internal and Apple will not let you use it.
Any ideas?
Note: This is an attempt to solve this problem, where I need to determine if airplane mode is on or off (and no, simply knowing if the network is reachable is not sufficient).
However, it would seem that this question is of more general interest, and is distinct from that question.
Your actual issue, determining if a network interface is active, can be resolved with BSD networking functions. BEHOLD.
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if.h>
BOOL IsNICTurnedOn(const char *nicName) {
BOOL result = NO;
struct ifaddrs *addrs = NULL;
if (0 == getifaddrs(&addrs)) {
for (struct ifaddrs *addr = addrs; addr != NULL; addr = addr->ifa_next) {
if (0 == strcmp(addr->ifa_name, nicName)) {
result = (0 != (addr->ifa_flags & (IFF_UP | IFF_RUNNING)));
break;
}
}
freeifaddrs(addrs);
}
return result;
}
To use this function:
BOOL isWWANEnabled = IsNICTurnedOn("pdp_ip0");
BOOL isWiFiEnabled = IsNICTurnedOn("en0");
At this point it seems clear that there is no simple way to detect if Airplane Mode is enabled. Although you could probably infer it by looking at low-level network stack info or scraping status bar pixels, either method would be relying on undocumented behavior. It's very possible that on a future release of iOS or a future iOS device, the behavior will change and your code will generate a false positive or false negative.
(Not to mention that, on future devices, the interference may not even be there.)
If I were in your shoes, I would:
File a bug to let Apple know you want this feature.
Work the notice into the app, regardless of whether Airplane Mode is enabled. Yes, it might be kind of annoying to the user if it is enabled, but the overall harm is minimal. I would probably make this an alert that pops up only once (storing a key in NSUserDefaults to indicate whether its already been displayed).
If you want to get super-fancy, analyze the recorded audio and, if the buzz is detected, remind the user again to enable Airplane Mode while recording. You could do this in real time or after the clip has been recorded, whatever makes more sense for your app.
As an alternative solution, perhaps you could detect the connection type, similar to: https://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html . With some additional checking for the device type, you could then warn the user only in the case where they need to act.
Kind of a different approach, but you can also link to pages within the Settings application. You could perhaps link to the primary page and tell the user the changes you require.
There appears to be no way to do this.

Resources