-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Abstract system APIs for common data stores to place honey data #123
Comments
For iOS, creating events could be done using the Events and Reminders API On Android, you might be able to send an Intent: https://stackoverflow.com/questions/7160231/how-to-add-a-calendar-event-on-an-android-device-with-a-given-date |
On Android, you can trigger many actions using common intents: https://developer.android.com/guide/components/intents-common You can trigger these events using For the calendar, this looks like this:
This only works, if the user already has a configured calendar. If not, it will fail with an error message in the GUI. For the contacts, this is similar. We can call up the contacts with
But we can not affirmatively close the then opened save dialog, because |
There is also the possibility to import contacts as vcards (https://stackoverflow.com/questions/23488290/android-importing-contacts-through-vcards-via-adb), however, this has a similar problem, because it requires interaction with the GUI. different versions of Android/different contacts apps act very differently here, so it is hard implement a general solution. |
Another option for adding contacts without having to interact with the GUI might be via the database. According to this article: https://www.dev2qa.com/android-contacts-database-structure/, contacts are saved in the /data/data/com.android.providers.contacts/databases/contacts2.db. |
Ok, with the help of this article I managed to write a frida skript that can be attached to // This follows https://github.com/frida/frida/issues/1049
function loadMissingClass(className) {
const loaders = Java.enumerateClassLoadersSync();
let classFactory;
for (const loader of loaders) {
try {
loader.findClass(className);
classFactory = Java.ClassFactory.get(loader);
break;
} catch {
// There was an error while finding the class, try another loader;
continue;
}
}
return classFactory.use(className);
}
function addContact(name) {
const appContext = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
const ContentProviderOperation = Java.use('android.content.ContentProviderOperation');
const ContactsContract = loadMissingClass('android.provider.ContactsContract');
const RawContacts = loadMissingClass('android.provider.ContactsContract$RawContacts');
const SyncColumns = loadMissingClass('android.provider.ContactsContract$SyncColumns');
const Data = loadMissingClass('android.provider.ContactsContract$Data');
const DataColumns = loadMissingClass('android.provider.ContactsContract$DataColumns');
const StructuredName = loadMissingClass('android.provider.ContactsContract$CommonDataKinds$StructuredName');
const ops = Java.use('java.util.ArrayList').$new();
ops.add(
ContentProviderOperation.newInsert(RawContacts.CONTENT_URI.value)
.withValue(SyncColumns.ACCOUNT_TYPE.value, null)
.withValue(SyncColumns.ACCOUNT_NAME.value, null)
.build()
);
ops.add(
ContentProviderOperation.newInsert(Data.CONTENT_URI.value)
.withValueBackReference(DataColumns.RAW_CONTACT_ID.value, 0)
.withValue(DataColumns.MIMETYPE.value, StructuredName.CONTENT_ITEM_TYPE.value)
.withValue(StructuredName.DISPLAY_NAME.value, name)
.build()
);
try {
appContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY.value, ops);
} catch (e) {
console.log(e);
}
} |
It took some figuring out, but now I also have a script to create events on iOS. I do this while attached to the Calendar app, because it obviously already has the correct permissions. This is the script: function addCalendarEvent(eventData) {
const eventStore = ObjC.classes.EKEventStore.alloc().init();
const NSError = ObjC.classes.NSError;
const NSISO8601DateFormatter = ObjC.classes.NSISO8601DateFormatter;
const NSString = ObjC.classes.NSString;
const EKEvent = ObjC.classes.EKEvent;
const formatter = NSISO8601DateFormatter.alloc().init();
const evt = EKEvent.eventWithEventStore_(eventStore);
evt.setTitle_(NSString.stringWithString_(eventData.title));
const start = formatter.dateFromString_(NSString.stringWithString_(eventData.startDate));
evt.setStartDate_(start);
const end = formatter.dateFromString_(NSString.stringWithString_(eventData.endDate));
evt.setEndDate_(end);
evt.setCalendar_(eventStore.defaultCalendarForNewEvents());
// https://github.com/frida/frida/issues/729
const errorPtr = Memory.alloc(Process.pointerSize);
Memory.writePointer(errorPtr, NULL);
eventStore.saveEvent_span_commit_error_(evt, 0, 1, errorPtr);
const error = Memory.readPointer(errorPtr);
if (!error.isNull()) {
const errorObj = new ObjC.Object(error); // now you can treat errorObj as an NSError instance
console.error(errorObj.toString());
}
} It is based on Apple’s documentation and an example from an article. |
And here is a script for adding contacts (attached to the Contacts app) based on this stackoverflow answer: function addContact(contactData) {
const CNMutableContact = ObjC.classes.CNMutableContact;
const NSString = ObjC.classes.NSString;
const CNLabeledValue = ObjC.classes.CNLabeledValue;
const CNPhoneNumber = ObjC.classes.CNPhoneNumber;
const CNSaveRequest = ObjC.classes.CNSaveRequest;
const NSMutableArray = ObjC.classes.NSMutableArray;
const CNContactStore = ObjC.classes.CNContactStore;
const contact = CNMutableContact.alloc().init();
contact.setLastName_(NSString.stringWithString_(contactData.lastName));
if(contactData.firstName) contact.setFirstName_(NSString.stringWithString_(contactData.firstName));
if (contactData.phoneNumber) {
const number = CNPhoneNumber.phoneNumberWithStringValue_(NSString.stringWithString_(contactData.phoneNumber));
const homePhone = CNLabeledValue.labeledValueWithLabel_value_(NSString.stringWithString_('home'), number);
const numbers = NSMutableArray.alloc().init();
numbers.addObject_(homePhone);
contact.setPhoneNumbers_(numbers);
}
if(contactData.email) {
const email = NSString.stringWithString_(contactData.email);
const homeEmail = CNLabeledValue.labeledValueWithLabel_value_(NSString.stringWithString_('home'), email);
const emails = NSMutableArray.alloc().init();
emails.addObject_(homeEmail);
contact.setEmailAddresses_(emails);
}
const request = CNSaveRequest.alloc().init();
request.addContact_toContainerWithIdentifier_(contact, null);
// https://github.com/frida/frida/issues/729
const errorPtr = Memory.alloc(Process.pointerSize);
Memory.writePointer(errorPtr, NULL);
const store = CNContactStore.alloc().init();
store.executeSaveRequest_error_(request, errorPtr);
const error = Memory.readPointer(errorPtr);
if (!error.isNull()) {
var errorObj = new ObjC.Object(error); // now you can treat errorObj as an NSError instance
console.error(errorObj.toString());
}
} |
I implemented setting the device name here |
We put Geolocation on hold, while we decide on whether we want to use Appium, because it already implements this (see #21). |
Co-authored-by: Benjamin Altpeter <[email protected]>
System APIs that should be supported:
Both:
iOS:
The text was updated successfully, but these errors were encountered: