I know it is possible to check the traffic usage of wifi and Data through built-in settings in iphone. But is there any solution like a library or function to fetch realtime network usage (upload/download) of the device? (like a real time netstat)
Reachability is one of the things that I found with regard to the mentioned.
http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007324-Intro-DontLinkElementID_2
this app does something similar:
https://itunes.apple.com/us/app/data-control-manage-data-usage/id390646992?mt=8
Does anyone know what class to call or look for what certain method to access the real time traffic?
I hope that my question is understandable.
There is no high level API to support this, but since iOS is simply a rather pretty unix, you can of course go to the standard APIs.
In this case you would be looking for getifaddrs, which retrieves the in memory structures describing the various interfaces on the device.
You then have to parse these C structures, to get the interface details you want.
The getifaddr interface is documented ( man getifaddr), so you can use this.
I'll add a bit of code, but first a few caveats.
Apple don't really bother maintaining this stuff, so the network counts are 32 bit, so you have to handle 4Gb roll over.
The packet counts are mostly there, I think the tx packet count is always 0, but who is interested in packet counts anyway.
You can probably find better code here by searching for getifaddrs, but here is a short version to get you started.
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if_var.h>
struct ifaddrs* addrs;
int getIFAddrsResult = getifaddrs(&addrs);
if (getIFAddrsResult == 0)
{
struct ifaddrs* addrsPtr = addrs; // need to keep original for freeifaddrs
while (addrsPtr != NULL)
{
NSString *name = [NSString stringWithFormat:#"%s",addrsPtr->ifa_name];
//NSLog(#"ifa_name %s == %#\n", cursor->ifa_name,name);
// names of interfaces: en0 is WiFi ,pdp_ip0 is WWAN
if (addrsPtr->ifa_addr->sa_family == AF_LINK)
{
const struct if_data* stats = (const struct if_data *) addrsPtr->ifa_data;
// We only consider the active data interface, and that will normally be the '0' interface.
if ([name isEqualToString:#"en0"])
{
// Wifi
// look at stats->ifi_obytes & ifi_ibytes
} else if ([name isEqualToString:#"pdp_ip0"])
{
// mobile broad band
} else {
// could be bluetooth, usb, ad hoc wifi, out of band signalling...
}
}
addrsPtr = addrsPtr->ifa_next;
}
freeifaddrs(addrs);
} else {
NSLog(#"getifaddrs failed with error : %s", strerror(getIFAddrsResult));
return nil;
}
P.S. I'm going for my diamond resurrect old questions badge :)
There is no such API in iOS, the App that you mentioned (and all similar apps), rely on an API provided by the carrier (or parsing the carriers website). If you want to implement this kind of App, I'm afraid you have to find something for every possible carrier you are interested in.
Related
I want to send an array to the IP design through SDK rather than just a number as shown in the following code snippet. Can somebody help me in doing that?
code in SDK
let's start saying that there are different way to send data to IP (for example from an ARM processor to a custom IP in a Zynq). Xilinx gives you the possibility to communicate using:
AXI4 FULL interface
AXI4 LITE interface
AXI4 STREAM interface
Depending on the interface you use, the way to write the SDK-code running on the ARM may be quite different. There are a lot of details but in general when you create an IP, after exporting the hardware and lunching the SDK, Vivado creates library and drivers for you in order to send data and commands to the every specific IP. Just to give you an example let's say that you are using the AXI STREAM interface. Here you should add another IP (provided from Xilinx) that manage the data transfer from memory to the IP and vice versa (DMA - direct memory access). Here the code should be :
#include <stdio.h>
#include "xil_cache.h"
#include "xaxidma.h"
#include "xparameters.h"
#include "math.h"
#include "xtime_l.h"
XTime tstart,tstop;
//#define DEBUG
#define N_samples 64
int main()
{
printf("Hello\n");
Xil_DCacheDisable();
Xil_ICacheDisable();
/***************** Variables *******************/
float input_R_IM[N_samples*2];
float output_R_IM[N_samples*2];
int error=-1;
XAxiDma dma0_pointer;
XAxiDma_Config *dma0_Config;
/**********************DMA initialization***************************/
dma0_Config=XAxiDma_LookupConfig(XPAR_AXIDMA_0_DEVICE_ID);
error=XAxiDma_CfgInitialize(&dma0_pointer,dma0_Config);
#ifdef DEBUG
if(error==XST_SUCCESS)
printf("...initialization successful\n");
else
printf("**ERROR INITIALIZATION\n");
#endif
float d = 2 * (float)M_PI / N_samples;
size_t i=NULL;
for (i = 0; i < N_samples; i++)
{
input_R_IM[i*2]=sin(0 + d*i);
input_R_IM[i*2+1]=0;
}
/**********************STARTING FFT************************/
error=-1;
XTime_GetTime(&tstart);
error = XAxiDma_SimpleTransfer(&dma0_pointer,(u32)input_R_IM,2*N_samples*sizeof(float),XAXIDMA_DMA_TO_DEVICE);
#ifdef DEBUG
if(error==XST_SUCCESS)
printf("...simply transfer 1 successful\n");
else
printf("**ERROR SIMPLY TRANSFER 1\n");
#endif
/***********************COPY BACK THE RESULTS************************/
// error=-1;
error = XAxiDma_SimpleTransfer(&dma0_pointer,(u32)output_R_IM,2*N_samples*sizeof(float),XAXIDMA_DEVICE_TO_DMA);
#ifdef DEBUG
if(error==XST_SUCCESS)
printf("...simply transfer 2 successful\n");
else
printf("**ERROR SIMPLY TRANSFER 2\n");
#endif
XTime_GetTime(&tstop);
u64 cycles = tstop-tstart;
float t = ((float)cycles / COUNTS_PER_SECOND)*1000000;
printf("cycles= %lld (time = %f us)\n",cycles,t);
for (i = 0; i < N_samples; i++)
{
printf("i: %d real=> %f --imag==> %f \n" ,i, output_R_IM[i*2], output_R_IM[i*2+1]);
}
printf("Goodbye\n");
return 0;
}
This is an old code used to send data from one of the ARM processor to the FFT IP using and AXI-DMA.
Here you can find an AXI reference Guide in order to have a better idea on how to manage the data between IP on Xilinx FPGA
This question seems to have come up a few times, but I'm attempting to read from a DHT22 with a ESP-12e (ESP8266).
Wiring diagram is here:
Wiring Diagram
Code is here:
status, temp, humi, temp_dec, humi_dec = dht.read(1)
if status == dht.OK then
-- Integer firmware using this example
print(string.format("DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n",
math.floor(temp),
temp_dec,
math.floor(humi),
humi_dec
))
-- Float firmware using this example
print("DHT Temperature:"..temp..";".."Humidity:"..humi)
elseif status == dht.ERROR_CHECKSUM then
print( "DHT Checksum error." )
elseif status == dht.ERROR_TIMEOUT then
print( "DHT timed out." )
end
I've found articles that state the GPIO numbers don't match up with the pins on the NodeMCU board, and that you should use the pin on the board, which will be internally mapped to the real GPIO pin number (https://nodemcu.readthedocs.io/en/dev/en/modules/gpio/) . So, I've used what is labled as D1 on the board, which actually maps to GPIO5. I've tried both "1" and "5" for the pin number in the code and it makes no difference. I've also tried other pins, to no avail.
When the code attempts to run, I get the following error message:
> dofile("tempMon")
DHT timed out.
Other than a possible hardware issue with the sensor, is there anything that I could possibly be missing?
IMO, it looks like hardware issue but to be sure I wrote a simple program in Arduino IDE for your ESP8266 that should give the answer whether this is software or hardware issue.
The only thing the program does is outputing temperatures of DHT22 sensors connected to pin 1, 5 or 14.
#include <DHT.h>
DHT dht1(1, DHT22, 11);
DHT dht5(5, DHT22, 11);
DHT dht14(14, DHT22, 11);
float temp;
void setup() {
Serial.begin(115200);
dht1.begin();
dht5.begin();
dht14.begin();
}
void loop() {
temp = dht1.readTemperature(false);
Serial.print("DHT22 on pin1 - temp: ");
Serial.println(temp);
temp = dht5.readTemperature(false);
Serial.print("DHT22 on pin5 - temp: ");
Serial.println(temp);
temp = dht14.readTemperature(false);
Serial.print("DHT22 on pin14 - temp: ");
Serial.println(temp);
}
I compiled binary file for you so that you don't have to download Arduino IDE and compile it again: dht22test.bin
I tried the same example with the pull-up resistor and without it and received the same error in the two cases.
In order to be sure that no hardware issue with the sensor, I built up a code for arduino and using the same sensor everything went ok (consul displayed the temperate and humidity).
Has to be a hardware issue in the DHT22 module. Going to order another module and try again.
I've dug into this situation and found out that I'm having the same problem (and actually stepped on a few different errors).
Came 4 years later but further information is always helpfull for future reference.
Regarding you comment above:
I'm going to guess it's a hardware issue at this point. Whenever I run
the sketch, I get garbage output to the console. Upon investigation,
it starts spewing garbage after the first time that dht1.begin() is
called. I also wrote a lua script that looped through all the pins
looking for a DHT message and got nothing there either. – Michael
Wheeler Sep 20 '16 at 0:12
Note: Garbage Output usually means that Serial Bit Rates are different in your Serial Initialization and Console Output. Check it then if you still have problems; give the Troubleshooter bellow a try.
Troubleshooting:
1. Garbage Output : Receiving Garbage Output Continuously
- Set Bit Rate to 115200.
- Check Serial Bit Rates (Code and Serial Monitor).
- Delay DHT Initialization for: 2 Seconds (2000ms).
- Check Wiring.
2. Sensor Output is nan or 0
- Check Wiring.
- Test with Different Micro-Controller.
- See: 2.1 Bellow
2.1 Testing With Different Micro Controller
- If the Test Fails with a Different Controller Consider:
a) Possibly using the Wrong Library.
b) Possible Defective Module.
**Note:** For ESP32 and ESP8266 you need use a different library.
Include "DHTesp.h" instead of "DHT.h".
See code example bellow.
- If it Succeeds with different Controller:
a) DHT22 is not Compatible with Esp8266.
**Note:** I couldn't find a viable Pin that actually worked on my
ESP8266 (NodeMCU).
I'm relying on my own experience; and considering some people
have managed to make it work; consider that perhaps a
different DHT22 sensor model or ESP8266 could work.
3. No Output
- Usually Error in Code.
- Possible Short Circuit in Module and/or Controller.
enter code here
Remarks : Micro Controllers and Pins for DHT
Uno: Pin D02
Nano: Pin D02
ESP32: RX2 (Pin17)
ESP8266: None Worked (Try: 1,2,4,5,7)
Code for each Micro Controller (Including ESP8266)
Arduino Uno / Nano
#include "DHT.h"
/* Sensor Type */
#define dhtType DHT22
/* Define DHT22 Pin on Arduino */
#define dhtPin 0 // ESP8266 D1 (GPIO 5)
/* Configure DHT Pin and Model */
DHT dht(dhtPin, dhtType);
/* Initialize DHT22 Sensor */
void Init_DHT22()
{
dht.begin();
// Wait a little for the Sensor to Start and Calibrate.
delay(1000);
}
/* Read and Retrieve Temperature from DHT Pin. */
float GetTemperature() { return dht.readTemperature(); }
/* Read and Retrieve Humidity from DHT Pin. */
float GetHumidity() { return dht.readHumidity(); }
ESP32
#include "DHTesp.h"
#ifndef ESP32
#pragma message(THIS EXAMPLE IS FOR ESP32 ONLY!)
#error Select ESP32 board.
#endif
DHTesp dht;
/** Pin Number for DHT Data Pin */
#define dhtPin 17
void DHT22_Init()
{
// Initialize temperature sensor
dht.setup(dhtPin, DHTesp::DHT22);
}
float Temperature() { return dht.getTemperature(); }
float Humidity() { return dht.getHumidity(); }
ESP8266
/*
* Common Pins used for on ESP8266 are: D1, D2; D4 (None Worked for Me).
*/
#include "DHTesp.h"
#ifdef ESP32
#pragma message(THIS EXAMPLE IS FOR ESP8266 ONLY!)
#error Select ESP8266 board.
#endif
#define dhtPin 4
#define dhtType DHT22
DHTesp dht;
void DHT22_Init()
{
dht.setup(dhtPin, DHTesp::dhtType);
}
float Temperature()
{
delay(dht.getMinimumSamplingPeriod());
return dht.getTemperature();
}
float Humidity()
{
delay(dht.getMinimumSamplingPeriod());
return dht.getHumidity();
}
Best Regards
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.
I am building an app like RootMetrics - Cell Phone Coverage link https://itunes.apple.com/us/app/cell-phone-coverage-map/id399701910 here
or OpenSignal - https://itunes.apple.com/app/opensignal/id598298030
I need help to understand how they measure call/voice quality. As far as I understand such APIs are private and apps using them, would not be authorized on App Store. Can anyone tell me how to measure signal strength in such cases.
I do not believe this is possible without the use of private API:s. And as you said, Apple's bots will probably (definitely) find out when you try to upload the app to App Store.
If you still want to use a private API, this method for measuring carrier signal strength should to the trick:
-(int) getSignalStrength() {
void *libHandle = dlopen("/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
int (*CTGetSignalStrength)();
CTGetSignalStrength = dlsym(libHandle, "CTGetSignalStrength");
if( CTGetSignalStrength == NULL)
NSLog(#"Could not find CTGetSignalStrength");
int result = CTGetSignalStrength();
dlclose(libHandle);
return result;
}
I would suggest taking the average value of about 10 measurements since I believe that these can differ a lot.
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.