detect hotspot enabling in iOS with private api's - ios

ok so i want to detect weather the user has enabled hotspot/tethering or not in a iOS device. I can use private api's knowing it wont make it to the app store.
i was trying to go through private api's list/ runtime headers but there are too many to decide which might be helpful.
or if i could get to know where UIApplicationWillChangeStatusBarFrameNotification gets fired from in private api's(probably called for active call and activated hotspot etc)
i tried this detect personal hotspot and also used CaptiveNetwork but it only returns the connected wi-fi ssid and not the created hotspot.
any knowledge shared will be extremely helpful
Update: #creker
With the above code the compiler shows the error " SCDynamicStoreCreate is unavailable: not available on iOS. So i went into SCDynamicStore.h and changed the following
SCDynamicStoreRef
SCDynamicStoreCreate (
CFAllocatorRef allocator,
CFStringRef name,
SCDynamicStoreCallBack callout,
SCDynamicStoreContext *context
) __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_NA);
to
SCDynamicStoreRef
SCDynamicStoreCreate (
CFAllocatorRef allocator,
CFStringRef name,
SCDynamicStoreCallBack callout,
SCDynamicStoreContext *context
) __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_6_0);
now i am able to get the dictionary with the states 1022 and 1023. Just wanted to confirm by changing the file like this(not done before) will i have any problem in archiving build(or any other problem) other then the fact that we know this code won't make it to the app store

Without Private APIs
You can detect active personal hotspot by enumerating network interfaces using C APIs. When hotpost is active and someone is connected to it there will be interface with bridge prefix. On my iPhone 5 it's bridge100. If hotspot is disabled or no one is connected to it that interfaces will not even be in the list.
C APIs will even return you IP address and subnet mask in that network.
That's what I'm using in my applications to detect active hotspot.
To get SSID you need [[UIDevice currentDevice] name] - personal hotspot SSID always matches device name.
With Private APIs
You can obtain all the information about personal hotspot using this code:
SCDynamicStoreRef sc = SCDynamicStoreCreate(NULL, CFSTR("com.apple.wirelessmodemsettings.MISManager"), NULL, NULL);
NSDictionary* info = (__bridge_transfer NSDictionary*)SCDynamicStoreCopyValue(sc, CFSTR("com.apple.MobileInternetSharing"));
CFRelease(sc);
info dictionary will look something like this when hotspot is active and has connections:
{
Errnum = 0;
ExternalInterfaces = (
"pdp_ip0"
);
Hosts = {
Current = 1;
Max = 5;
MoreAllowed = 1;
Type = {
AirPort = 0;
Bluetooth = 0;
Ethernet = 0;
"USB-Ethernet" = 1;
};
};
InternalInterfaces = (
bridge100
);
Reason = 0;
State = 1023;
Version = 2;
}
When hotspot is active but there are no connections:
{
Errnum = 0;
ExternalInterfaces = (
);
Hosts = {
Current = 0;
Max = 5;
MoreAllowed = 1;
Type = {
AirPort = 0;
Bluetooth = 0;
Ethernet = 0;
"USB-Ethernet" = 0;
};
};
InternalInterfaces = (
);
Reason = 0;
State = 1023;
Version = 2;
}
When hotspot is not active:
{
Errnum = 45;
ExternalInterfaces = (
);
Hosts = {
Current = 0;
Max = 5;
MoreAllowed = 1;
Type = {
AirPort = 0;
Bluetooth = 0;
Ethernet = 0;
"USB-Ethernet" = 0;
};
};
InternalInterfaces = (
);
Reason = 0;
State = 1022;
Version = 2;
}
State key will be equal to 1023 when hotspot is active regardless of active connections. I don't know whether that value contains bit-flags or not. iOS is actually checking if value is equal to 1023.
SCDynamicStore APIs are from public SystemConfiguration framework but marked as not available on iOS platform. That means all the headers are there, you just need to copy definitions without __OSX_AVAILABLE_STARTING macro.
You can even observe changes to that setting - you can specify a key which value you want to observe. Read Apple documentation for implementation details.
UPDATE
So i went into SCDynamicStore.h and changed the following
I wouldn't do that. It shouldn't cause any problems but for me changing SDK headers is not a good solution. I suggest the following. Don't include the framework headers. Make your own header where you copy all the methods you need with __OSX_AVAILABLE_STARTING changed or removed.

Related

Block access to specific path with minifilters

I am trying to write a minifilter that block access to any file within a specific path. I have been able to do it for any path in C:. This is what I´ve done. First, I declare:
const WCHAR* internal_drives[] = { L"C:" };
Then, in instant_setup I start the minifilter for C: by doing:
int internal_drives_length = sizeof internal_drives / sizeof * internal_drives;
for (size_t i = 0; i < internal_drives_length; i++)
{
if (wcscmp(ctx->Name.Buffer, internal_drives[i]) == 0)
{
status = STATUS_SUCCESS;
}
}
I can block access to C: then by adding in functions: mini_pre_create, mini_post_create:
status = STATUS_ACCESS_DENIED;
data->IoStatus.Status = status;
data->IoStatus.Information = 0;
That works, I am able to block the access to any file in C:
But I´d like to be able to specify to which folder I want to block the access. I´ve trying specifying the path in the variable internal_drives but It does not work, I am blocking nothing :
const WCHAR* internal_drives[] = { L"D:\\path" };
Am I missing something? is there a more correct way to do this with minifilters? I am a complete beginner with minifilters.
You setup to the drivers, then you filter in the specific IRP_MJ_CREATE. To do that, you have to use FltGetFileNameInformation plus FltParseFileNameInformation.
Do note that the filesystem does not work with DOS name drive letters, so you will have to transform \Device\Harddiskvolumex\folder\file.txt to c:\folder\file.txt. You can do that mapping on setup.

How to get USB Token (Feitian Auto ePass 2003 FIPS USB Token) serial number in UEFI Application?

Developing UEFI Based application for enabling pre-boot authentication using
Feitian Auto ePass 2003 FIPS USB Token. I'm still in the initial stage of the development process.
Now I'm able to fetch Manufacturer, Product Code of the token by using UsbIo->UsbGetDeviceDescriptor protocol. But when I try to find serial number it's throwing an error.
Is there any other way to find the serial number of the USB Token? Please help me on this..
This is my sample code for finding serial number
EFI_USB_DEVICE_DESCRIPTOR DevDesc;
EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
EFI_USB_CONFIG_DESCRIPTOR ConfigDescriptor;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_STATUS Status;
EFI_HANDLE *HandleBuffer = NULL;
BOOLEAN LangFound;
UINTN HandleCount;
UINT8 EndpointNumber;
CHAR16* ManufacturerString = NULL;
CHAR16* ProductString = NULL;
CHAR16* SerialNumber = NULL;
UINT16* LangIDTable;
UINT16 TableSize;
INTN Index;
int index;
unsigned char* device_descriptor, * ccid_descriptor;
EFI_USB_DEVICE_REQUEST DevReq;
UINT32 Status_uint;
Status = gBS->LocateHandleBuffer( ByProtocol,
&gEfiUsbIoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer );
if (EFI_ERROR(Status)) {
Print(L"ERROR: LocateHandleBuffer.\n");
goto ErrorExit;
}
UINT8 usbIndex;
for (usbIndex = 0; usbIndex < HandleCount; usbIndex++) {
Status = gBS->HandleProtocol( HandleBuffer[usbIndex],
&gEfiUsbIoProtocolGuid,
(VOID**)&UsbIo );
if (EFI_ERROR(Status)) {
Print(L"ERROR: Open UsbIo.\n");
goto ErrorExit;
}
Status = UsbIo->UsbGetDeviceDescriptor( UsbIo, &DevDesc );
if (EFI_ERROR(Status)) {
Print(L"ERROR: UsbGetDeviceDescriptor.\n");
goto ErrorExit;
}
Status = UsbIo->UsbGetConfigDescriptor( UsbIo, &ConfigDescriptor );
if (EFI_ERROR (Status))
{
Print(L"UsbGetConfigDescriptor %d", Status);
goto ErrorExit;
}
Status = UsbIo->UsbGetInterfaceDescriptor( UsbIo, &InterfaceDescriptor );
if (EFI_ERROR (Status)) {
Print(L"ERROR: UsbGetInterfaceDescriptor.\n");
goto ErrorExit;
}
if (InterfaceDescriptor.InterfaceClass != CLASS_CCID) {
continue;
}
Print(L":::::::::::::::::::::: CCID ::::::::::::::::::::::\n");
//
// Get all supported languages.
//
TableSize = 0;
LangIDTable = NULL;
Status = UsbIo->UsbGetSupportedLanguages(UsbIo, &LangIDTable, &TableSize);
if (EFI_ERROR(Status)) {
Print(L"ERROR: UsbGetSupportedLanguages.\n");
return Status;
}
/* Get Manufacturer string */
for (Index = 0; Index < TableSize / sizeof(LangIDTable[0]); Index++) {
ManufacturerString = NULL;
Status = UsbIo->UsbGetStringDescriptor(UsbIo,
LangIDTable[Index],
DevDesc.StrManufacturer,
&ManufacturerString);
if (EFI_ERROR(Status) || (ManufacturerString == NULL)) {
continue;
}
Print(L"StrManufacturer ::%s\n", ManufacturerString);
FreePool(ManufacturerString);
break;
}
/* Get Product string */
for (Index = 0; Index < TableSize / sizeof(LangIDTable[0]); Index++) {
ProductString = NULL;
Status = UsbIo->UsbGetStringDescriptor(UsbIo,
LangIDTable[Index],
DevDesc.StrProduct,
&ProductString);
if (EFI_ERROR(Status) || (ProductString == NULL)) {
continue;
}
Print(L"StrProduct ::%s\n", ProductString);
FreePool(ProductString);
break;
}
/* Get Serial string */
for (Index = 0; Index < TableSize / sizeof(LangIDTable[0]); Index++) {
SerialNumber = NULL;
Status = UsbIo->UsbGetStringDescriptor(UsbIo,
LangIDTable[Index],
DevDesc.StrSerialNumber,
&SerialNumber);
if (EFI_ERROR(Status) || (SerialNumber == NULL)) {
Print(L"Error in finding SerialNumber \n");
continue;
}
Print(L"SerialNumber :: %s\n", SerialNumber);
FreePool(SerialNumber);
break;
}
Print(L"usbIndex ::%d\n", usbIndex);
Print(L"IdVendor ::%d\n", DevDesc.IdVendor);
Print(L"IdProduct ::%d\n", DevDesc.IdProduct);
}
Print(L"\n");
FreePool(HandleBuffer);
return Status;
From what I have read, the Feitian Technologies ePass2003 uses an Infineon M7893 or SLE 78CUFX5000PH (M7893-B) security chip.
As you have found out, the serial number for the ePass2003 is not stored in the USB device descriptor but in the security chip.
To obtain chip global data such as OEM information, algorithm support, FIPS mode indicator, RAM size and serial number, the GetData primitive is used. See the M7893 programming guide. if you can obtain access to it.
The driver for ePass2003 in OpenSC is called “epass2003”. The source code is currently available at https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-epass2003.c. It has dependencies on OpenSSL and ASN.1 and some non-EDK2 headers, but these are easily worked around.
If all you are looking for is the serial number, it should be fairly easy to write a UEFI application (or driver) to get that information either by studying how the OpenSC ePass2003 driver does it (hint - look at epass2003_get_serialnr or studying the ePass2003 SDK which is available for free from Feitain and elsewhere.
The UEFI 2.5 specification released in April 2015 detailed 2 protocols relating to smart cards, i.e. Smart Card Reader and Smart Card Edge.
typedef struct _EFI_SMART_CARD_READER_PROTOCOL {
EFI_SMART_CARD_READER_CONNECT SCardConnect;
EFI_SMART_CARD_READER_DISCONNECT SCardDisconnect;
EFI_SMART_CARD_READER_STATUS SCardStatus;
EFI_SMART_CARD_READER_TRANSMIT SCardTransmit;
EFI_SMART_CARD_READER_CONTROL SCardControl;
EFI_SMART_CARD_READER_GET_ATTRIB SCardGetAttrib;
} EFI_SMART_CARD_READER_PROTOCOL;
typedef struct _EFI_SMART_CARD_EDGE_PROTOCOL {
EFI_SMART_CARD_EDGE_GET_CONTEXT GetContext;
EFI_SMART_CARD_EDGE_CONNECT Connect;
EFI_SMART_CARD_EDGE_DISCONNECT Disconnect;
EFI_SMART_CARD_EDGE_GET_CSN GetCsn;
EFI_SMART_CARD_EDGE_GET_READER_NAME GetReaderName;
EFI_SMART_CARD_EDGE_VERIFY_PIN VerifyPin;
EFI_SMART_CARD_EDGE_GET_PIN_REMAINING GetPinRemaining;
EFI_SMART_CARD_EDGE_GET_DATA GetData;
EFI_SMART_CARD_EDGE_GET_CREDENTIAL GetCredential;
EFI_SMART_CARD_EDGE_SIGN_DATA SignData;
EFI_SMART_CARD_EDGE_DECRYPT_DATA DecryptData;
EFI_SMART_CARD_EDGE_BUILD_DH_AGREEMENT BuildDHAgreement;
} EFI_SMART_CARD_EDGE_PROTOCOL;
EDK2 does not contain a sample implementation at present. However, you may be interested in the GPL2-licensed sample implementation by Ludovic Rousseau which is available at https://github.com/LudovicRousseau/edk2/tree/SmartCard. The implementation code, which is circa 5 years old and which I have not tested, is at MdeModulePkg/Library/SmartCardReader. Read his blog (https://ludovicrousseau.blogspot.com/) also as he provides useful sample applications also.

Stm32f4 dma m2m

I'm using STM32F407VG Discovery Board and I've issue with DMA memory to memory transfer. I want to copy 32 bytes of data from one place in memory to other using DMA by writing copy_dma() function. In while loop i'm checking Transfer Complete flag but DMA never returns it. I want to ask where i'm making mistake? Maybe something in configuration is wrong. I'm using Standart Peripheral Libraries. Here's my code.
#include "stm32f4xx.h"
#define BUFFER_SIZE 32
uint8_t src_buffer[BUFFER_SIZE];
uint8_t dst_buffer[BUFFER_SIZE];
void copy_dma(void);
int main(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
int i;
DMA_InitTypeDef dma;
DMA_DeInit(DMA1_Stream4);
DMA_StructInit(&dma);
dma.DMA_Channel = DMA_Channel_1;
dma.DMA_PeripheralBaseAddr = (uint32_t)src_buffer;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
dma.DMA_Memory0BaseAddr = (uint32_t)dst_buffer;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_BufferSize = BUFFER_SIZE;
dma.DMA_DIR = DMA_DIR_MemoryToMemory;
dma.DMA_FIFOMode = DMA_FIFOMode_Disable;
dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_Mode = DMA_Mode_Normal;
dma.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Stream4, &dma);
for (i = 0; i < BUFFER_SIZE; i++) {
src_buffer[i] = 100 + i;
}
copy_dma();
while(1) {
}
}
void copy_dma(void) {
DMA_Cmd(DMA1_Stream4, ENABLE);
while (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) == RESET);
}
In app note "Using the STM32F2 and STM32F4 DMA controller"(http://stm32.eefocus.com/download/index.php?act=down&id=6312)
is mentioned:
"Memory to memory (only DMA2 is able to do such transfer, in this mode, the circular and direct modes are not allowed.)"
So, try to use DMA2.
In addition to Mariusz Górka's awnser:
When using the DMA you need to know which memory region you are using. The stm32f4 has a memory section called Core Coupled Memory (CCM). The DMA does not have access to this region.
Check your map file and make sure your buffers are not in the region 0x10000000 - 0x1000FFFF.

Get parent process information at runtime on iOS application

I'm trying to obtain some process information at runtime on iOS, particularly the parent process name.
While I'm able to obtain the current process name, it seems that I can't to do the same for its parent.
Here is what I'm doing:
static inline bool is_debugserver_present() {
int err;
int mib[4];
struct kinfo_proc info;
size_t size;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info.kp_proc.p_flag = 0;
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a the parent process ID.
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getppid();
// Call sysctl.
size = sizeof(info);
int n = sizeof(mib) / sizeof(*mib);
err = sysctl(mib, n, &info, &size, NULL, 0);
return (strncmp(info.kp_proc.p_comm, "launchd", sizeof("launchd") - 1) != 0);
}
The problem is that the call to sysctl always return -1 thus an error.
The parent process id obtained by getppid()is that same if I ask to the current process for its kp_eproc.e_ppid.
Am I missing something?
You cannot obtain the information of other processes since iOS 9. sysctl is sandboxed now. You can do this only in a iDevice previous iOS 9 or a Simulator.
sysctl() retrieves system information for processes with appropriate privileges
iOS apps are not permitted to see what other apps are running
In iOS 9, the sandbox now prevents a process from accessing the kern.proc,
kern.procargs, and kern.procargs2 values for other processes
see:
WWDC Privacy Introduction
Privacy and your app (Page 29)

WiFiManager.bundle WiFiManager returns NULL when I try to load by using dlopen, iOS

For private usage I try to load WiFi Manager (iOS 6.1) by using following code:
airportHandle = 0;
libHandle = 0;
libHandle = dlopen(
"/System/Library/SystemConfiguration/WiFiManager.bundle/WiFiManager"
//"/System/Library/SystemConfiguration/IPConfiguration.bundle/IPConfifuration"
, RTLD_LAZY);
if(libHandle != 0)
{
disassociate = (int (*)())dlsym(libHandle, "Apple80211Disassociate");
open = (int (*)(void*))dlsym(libHandle, "Apple80211Open");
bind = (int (*)(void*, NSString*))dlsym(libHandle, "Apple80211BindToInterface");
close = (int (*)(void*))dlsym(libHandle, "Apple80211Close");
scan = (int (*)(void*, NSArray**, void*))dlsym(libHandle, "Apple80211Scan");
associate = (int (*)(void*, void*, NSString*))dlsym(libHandle, "Apple80211Associate");
info = (int (*)(void*, NSDictionary**))dlsym(libHandle, "Apple80211GetInfoCopy");
GetPower = (int (*)(void*, char*))dlsym(libHandle, "Apple80211GetPower");
SetPower = (int (*)(void*, char))dlsym(libHandle, "Apple80211SetPower");
listinfo = (int (*)(void*, NSDictionary**))dlsym(libHandle, "Apple80211GetIfListCopy");
open(&airportHandle);
bind(airportHandle, #"en0");
}
However libHandle is NULL.
Do I need to use jailbreak device or there is no way to stay with Private API only.
Thanks,
This is not a answer, but rather a directions to look.
As I remember, Apple moved WiFi API's around (from one framework to another) several times.
So, most likely this path ("/System/Library/SystemConfiguration/WiFiManager.bundle/WiFiManager") is obsolete.
You should be able to use dlopen and get a handle even on non jailbroken iOS device. So, this is not a problem. However, I am not sure whether these API's which you mentioned are not protected by entitlement.
If you have iOS 6 simulator, I would recommend to go there and try to grepr and find where these API's live.
BTW. Look at this question. He claims that his code works on iOS 6 - Iphone 802.11 Scan

Resources