Closed akaDuality closed 5 years ago
I can agree that in offering a solution to this sort of request could in fact accelerate that process.
a bit more follow-up from Apple today, where the tech acknowledged an ongoing discussion about the issue:
"It is safe to assume that this has been discussed, and there is always room for further discussion. But the case is, security trumps convenience ... Your best bet would be to file an Enhancement Request (https://bugreports.apple.com) on this, to add to the discussion, and to let the decision making teams to hear about the pain points encountered by developers. It is usually more helpful to word the request in terms of how the end users would benefit from such a change, rather than how you as a developer is inconvenienced"
I submitted a report (Bug Report Number: 29935293) with explaining my necessary use case scenario that would require me to use the MAC Address. I hope that other developers follow suit so that we can help to our cause.
Here is my solution, it is only test code, not something, I would use direct in a product .But I am sure Apple will block it in the next release.
` for (int a=0;a<255;a++) { NSString * myhost = [NSString stringWithFormat:@"192.168.1.%d",a]; [self jan_mac_addr_test:[myhost UTF8String]];
}`
` -(void) jan_mac_addr_test:(const char*) host {
int sockfd;
unsigned char buf[BUFLEN];
unsigned char buf2[BUFLEN];
ssize_t n;
struct rt_msghdr *rtm;
struct sockaddr_in *sin;
memset(buf,0,sizeof(buf));
memset(buf2,0,sizeof(buf2));
sockfd = socket(AF_ROUTE, SOCK_RAW, 0);
rtm = (struct rt_msghdr *) buf;
rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
rtm->rtm_version = RTM_VERSION;
rtm->rtm_type = RTM_GET;
rtm->rtm_addrs = RTA_DST;
rtm->rtm_flags = RTF_LLINFO;
rtm->rtm_pid = 1234;
rtm->rtm_seq = SEQ;
sin = (struct sockaddr_in *) (rtm + 1);
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = inet_addr(host);
write(sockfd, rtm, rtm->rtm_msglen);
n = read(sockfd, buf2, BUFLEN);
if (n != 0) {
int index = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_inarp) + 8;
// savedata("test",buf2,n);
NSLog(@"IP %s :: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",host,buf2[index+0], buf2[index+1], buf2[index+2], buf2[index+3], buf2[index+4], buf2[index+5]);
}
} `
@mochasoft It works thanks a lot . And Learn a lot from U.
@mochasoft Cool, thanks a lot!
I just tested your sample code there @mochasoft, the output that I receive is all 00's. That even includes the first octet of the MAC Address. Is your code sample supposed to be for looping through the subnet as a scanner? What about the device that is scanning that network? Please note that I am testing this on iOS 9.3.5, and I also tested with the same results on 10.2.1 Beta 3.
@mochasoft You are my hero! Thank you very much for sharing!
ndenlinger, if the iOS arp table is empty, you get zero values. You could select first in your code to ping the IP address, as to get the iOS to do the arp protocol, before "reading" a mac address using my code example.
Spot on @mochasoft. That worked beautifully. I suppose that in the future Apple will find out about these exploits and close them. But we'll see.
@mochasoft I think the sample code should add close(sockfd);
in the end of the function.
luoshihui, it is just an example, where the goal is to make it easy to read. In a real world application, there should also be checks for different return values for the function calls.
@mochasoft Are you sure this works for iOS? I tried something similar before but I was not able to use SOCK_RAW when creating the socket.
Nvm. I was using the AF_INET protocol instead of AF_ROUTE. Tried your code and works great! Thank you for this solution. Even if it's only temporary. I had attempted to read the link layer off of the callback on the icmp packet but no luck. So luckily I already had that part in place :) Cheers.
@mochasoft thank you very much for your solution. Also, I would like to thanks anyone here for your contribution and feedback. I will update the project as soon as I have some free time. Pull request are welcome :)
Yes thank you everyone!
Has anyone recompiled this solution with Xcode 8.3 Beta and iOS 10.3 Beta Yet? I'm waiting on my IT Security Team to say it's okay to upgrade OS X to macOS Sierra so as of right now I'm unable to install 8.3.
@mochasoft @luoshihui Guys I have updated MacFinder repo which is used by MMLanScan and I will update MMLanScan soon. Please check if we can optimize it a little bit since I am not fully aware what's the code is doing. Let me know or send me a pull request.
ndenlinger; I see no problems with iOS 10.3 beta.
How to get the ethernet address from an IPv6 address?
@mochasoft Hi I have use this block of code in iOS 10.3 beta 3 but it doesn't work.
(void)PingSelf { fillARPTable([FindMac deviceIPAdress]); [SimplePingHelper ping:[FindMac deviceIPAdress] target:self sel:@selector(pingResult:)]; } // ping result
(void)pingResult:(NSNumber)success { if (success.boolValue) { NSString macADDr = [FindMac ipToMac:[[FindMac deviceIPAdress] cStringUsingEncoding:NSASCIIStringEncoding]];//after ping get mac address NSLog(@"%@",macADDr); } else { NSLog(@"fial"); } }
(NSString) ipToMac:(const char) host { int sockfd; unsigned char buf[BUFLEN]; unsigned char buf2[BUFLEN]; ssize_t n; struct rt_msghdr rtm; struct sockaddr_in sin; memset(buf,0,sizeof(buf)); memset(buf2,0,sizeof(buf2)); sockfd = socket(AF_ROUTE, SOCK_RAW, 0); rtm = (struct rt_msghdr ) buf; rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in); rtm->rtm_version = RTM_VERSION; rtm->rtm_type = RTM_GET; rtm->rtm_addrs = RTA_DST; rtm->rtm_flags = RTF_LLINFO; rtm->rtm_pid = 1234; rtm->rtm_seq = SEQ; sin = (struct sockaddr_in ) (rtm + 1); sin->sin_len = sizeof(struct sockaddr_in); sin->sin_family = AF_INET; sin->sin_addr.s_addr = inet_addr(host); write(sockfd, rtm, rtm->rtm_msglen); n = read(sockfd, buf2, BUFLEN); if (n != 0) { int index = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_inarp) + 8; return [NSString stringWithFormat:@"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",buf2[index+0], buf2[index+1], buf2[index+2], buf2[index+3], buf2[index+4], buf2[index+5]]; } else { return nil; } }
Is anything wrong with this code? Thank U
It is true, this solution are not working with iOS 10.3 betas. Also I have noticed that Fing does not show MAC address with this version...
You might be right @arivas87. This was originally working in a project that I had successfully implemented this method and it's no longer showing the MAC Address. Apple's too quick to patch a function like this.
Would directly sending ARP packets work on iOS 10.3?
Had anyone tested the Code and got the Mac Address on an actual Iphone 6/7 with 10.2.1 OS?
We used Mavris code and include it on a test app, we run it on an ipad with ios 10.2.1 and it worked.
When installed and run on iphone, something is crashing the app, has anyone experienced this?
@Andresmtz89 Put a breakpoint here:
//Getting the available IPs to ping based on our network subnet.
self.ipsToPing = [LANProperties getAllHostsForIP:self.device.ipAddress andSubnet:self.device.subnetMask];
in MMLANScan.m and let me know the range. Also make sure that iPhone is not using IPV6
Many Thanks @mavris
It is working across multiple ios devices!
Heres what I'm using based off the above.. Obviously you'd want to replace the delegate calls with some other sort of callback of your own for when
- (void)scan {
int mib[6];
size_t needed;
char *host, *lim, *buf, *next;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sin;
struct sockaddr_dl *sdl;
struct hostent *hp;
int _nflag = 0;
extern int h_errno;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
mib[5] = RTF_LLINFO;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
err(1, "route-sysctl-estimate");
if ((buf = malloc(needed)) == NULL)
err(1, "malloc");
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
err(1, "actual retrieval of routing table");
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next;
sin = (struct sockaddr_inarp *)(rtm + 1);
sdl = (struct sockaddr_dl *)(sin + 1);
if (_nflag == 0) {
NSDate *hostStart = [NSDate date];
hp = gethostbyaddr((caddr_t)&(sin->sin_addr),sizeof sin->sin_addr, AF_INET);
NSDate *hostEnd = [NSDate date];
NSTimeInterval executionTime = [hostEnd timeIntervalSinceDate:hostStart];
//NSLog(@"Execution Time: %f",executionTime);
if (executionTime > 1) {
_nflag = 1;
}
} else
hp = 0;
if (hp)
host = hp->h_name;
else {
host = "";
if (h_errno == TRY_AGAIN)
_nflag = 1;
}
if (sdl->sdl_alen) {
NSString* newAddress = [NSString stringWithFormat:@"%s",inet_ntoa(sin->sin_addr)];
gethostbyaddr((caddr_t)&(sin->sin_addr),sizeof sin->sin_addr, AF_INET);
NSString* newHost = [NSString stringWithFormat:@"%s", host];
[self ipToMac:newAddress
completion:^(NSString *macAddress) {
NSArray *ipSplit = [newAddress componentsSeparatedByString:@"."];
if ([ipSplit[0] isEqualToString:@"169"] || [macAddress isEqualToString:@"FF:FF:FF:FF:FF:FF"]) { //Broadcast address and self assigned IP's
//skip sending to delegate
} else {
// TODO: Replace this code below with a callback of your own
if ([self.delegate respondsToSelector:@selector(discoveredGatewaySibling:macAddress:host:)]) {
[self.delegate discoveredGatewaySibling:newAddress macAddress:macAddress host:newHost];
}
}
}];
} else{
if (rtm->rtm_rmx.rmx_expire == 0)
printf(" permanent");
if (sin->sin_other & SIN_PROXY)
printf(" published (proxy only)");
if (rtm->rtm_addrs & RTA_NETMASK) {
sin = (struct sockaddr_inarp *)
(sdl->sdl_len + (char *)sdl);
if (sin->sin_addr.s_addr == 0xffffffff)
printf(" published");
if (sin->sin_len != 8)
printf("(weird)");
}
}
}
}
- (void)ipToMac:(NSString *)ip
completion:(void (^)(NSString* macAddress))completion {
#define BUFLEN (sizeof(struct rt_msghdr) + 512)
#define SEQ 9999
#define RTM_VERSION 5 // important, version 2 does not return a mac address!
#define RTM_GET 0x4 // Report Metrics
#define RTF_LLINFO 0x400 // generated by link layer (e.g. ARP)
#define RTF_IFSCOPE 0x1000000 // has valid interface scope
#define RTA_DST 0x1 // destination sockaddr present
const char* host = [ip UTF8String];
int sockfd;
unsigned char buf[BUFLEN];
unsigned char buf2[BUFLEN];
ssize_t n;
struct rt_msghdr *rtm;
struct sockaddr_in *sin;
memset(buf,0,sizeof(buf));
memset(buf2,0,sizeof(buf2));
sockfd = socket(AF_ROUTE, SOCK_RAW, 0);
rtm = (struct rt_msghdr *) buf;
rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
rtm->rtm_version = RTM_VERSION;
rtm->rtm_type = RTM_GET;
rtm->rtm_addrs = RTA_DST;
rtm->rtm_flags = RTF_LLINFO;
rtm->rtm_pid = 1234;
rtm->rtm_seq = SEQ;
sin = (struct sockaddr_in *) (rtm + 1);
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = inet_addr(host);
write(sockfd, rtm, rtm->rtm_msglen);
n = read(sockfd, buf2, BUFLEN);
if (n != 0) {
int index = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_inarp) + 8;
NSString* mac = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
buf2[index+0], buf2[index+1], buf2[index+2], buf2[index+3], buf2[index+4], buf2[index+5]];
close(sockfd);
completion(mac);
}
}
This code does not works on 10.3 iOS version...
I have tested my code (mocha ping) and mmlanscandemo with iOS 10.3 beta 5 (14E5296a, mar 8 2017) on an iPad (compiled with 8.3 beta 4 (8w143q) and I can read the mac address with both Apps. Only difference I see is: the IP address for my iPad cannot be listed, it has mac address 02:00...
@mochasoft That makes sense! It seems that Apple will restrict the device's MAC address but they will allow as to use ARP Table for other devices. It's not perfect solution but it's something.
Seems strange but after you run the app several times, the mac address is no more retrieved. Is anyone facing this issue?
Which iOS? 10.3?
It's 10.2.1
I am on 10.2.1 too and I never experienced that issue. I tried it today and seems fine. Can you debug the MacFinder and post your findings? We might be able to reproduce it
I see same behavior on iPhone and iPad. I did debug a little and looked like this is happening after I ran my version of the code which used ipv6 addresses. Now even if I run original code from macfinder it never returns mac
Fing is updated to say compatible with iOS 10.3. Anyone tried?
Yes. Everything seems fine except when you query for device's MAC Address. Then you will get the 02:00...
However the same technique seems to work on tvOS 10.2 (which is about the same generation of updates with iOS 10.3) – able to see other devices’ MAC addresses.
On 7 Apr 2017, at 14:14, Michael Mavris notifications@github.com wrote:
Yes. Everything seems fine except when you query for device's MAC Address. Then you will get the 02:00...
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mavris/MMLanScan/issues/3#issuecomment-292450672, or mute the thread https://github.com/notifications/unsubscribe-auth/AAKv0dgvbIdXstyh132-uO3zDLJf_0Zlks5rtdRJgaJpZM4K-50O.
I'm able to get other devices mac address in 10.3.2 but not the device the code is running on.
Hello, Has anyone been able to make it work on IOS 10.3?
We are using this library and we are able to get mac address in 10.2 and 10.3.2. Will the app will be rejected if we are going to upload the app on the appstore? Is anyone using the library in apps on appstore ?
Please let us know Thanks
I have had an app accepted recently. It did require IPv6 support but that was a small tweak. You should be fine.
@gregpardo Yes,You can get other device mac address no matter which version it is. First of all, the one you want to get mac address must in your arp table. That's trick. Now I can only ping all of the device in private network region.
@Darshanptl7500 & @gregpardo , have you had it running in 10.3.2? because @Darshanptl7500 told that it works on 10.3.2. If you had it working how? Please help :)
@iremkorkmaz It's working for every other device except yours (It cant' retrieve MAC address from arp table for your device). Other than that the scanning is fine
ah ok, I thought it was working also for the running device for them. We had an application that relies on Mac Address, it now worths nothing... :(
Can you tell us more? How/why did it rely on MacAddress? When they blocked the device macaddress, Apple provided other ways to do a lot of things, depending on your purpose.
@jpalten , it was a wi-fi analytic platform supported with an app. so app side is nothing now :)
Why don't you ask the user to enter his mac address manually? He will do that once (Settings-General-About-Wifi Address). (If you just want to display the MAC Address of WiFi, of course, this is not an acceptable solution).
https://github.com/mavris/MMLanScan/issues/23 Any one found something about iOS 11?
Is seems that iOS 10.2 has damaged something and MAC-resolving isn't working. Every IP has MAC like "02:00:00:00:00:00"
Do you have any idea how to fix it?