void scan_directory(const char *dir) { DIR *pd; struct dirent *pe; char canonical_path[PATH_MAX+1] = { 0 }; char *end; struct stat sb; if (!(pd = opendir(dir))) { perror_str("[!] Unable to open dir \"%s\"", dir); return; } while ((pe = readdir(pd))) { if (pe->d_name[0] == '.') { if (pe->d_name[1] == '\0') continue; if (pe->d_name[1] == '.' && pe->d_name[2] == '\0') continue; } end = my_stpcpy(canonical_path, dir); if (end - canonical_path >= PATH_MAX - 1 - strlen(pe->d_name)) { fprintf(stderr, "[!] name too long \"%s/%s\"\n", dir, pe->d_name); continue; } if (end > canonical_path && *(end - 1) != '/') *end++ = '/'; strcpy(end, pe->d_name); #ifdef DEBUG printf("[*] checking: 0x%x 0x%x 0x%x 0x%x %s ...\n", (unsigned int)pe->d_ino, (unsigned int)pe->d_off, pe->d_reclen, pe->d_type, canonical_path); #endif /* decide where to put this one */ if (lstat(canonical_path, &sb) == -1) { perror_str("[!] Unable to lstat \"%s\"", canonical_path); continue; } /* skip symlinks.. */ if (S_ISLNK(sb.st_mode)) continue; record_access_level(canonical_path, &sb); /* can the child directory too */ if (S_ISDIR(sb.st_mode) && is_executable(&sb)) scan_directory(canonical_path); } closedir(pd); }
static int _adb_connect(const std::string& service, std::string* error) { D("_adb_connect: %s", service.c_str()); if (service.empty() || service.size() > MAX_PAYLOAD) { *error = android::base::StringPrintf("bad service name length (%zd)", service.size()); return -1; } std::string reason; int fd = socket_spec_connect(__adb_server_socket_spec, &reason); if (fd < 0) { *error = android::base::StringPrintf("cannot connect to daemon at %s: %s", __adb_server_socket_spec, reason.c_str()); return -2; } if (memcmp(&service[0], "host", 4) != 0 && switch_socket_transport(fd, error)) { return -1; } if (!SendProtocolString(fd, service)) { *error = perror_str("write failure during connection"); adb_close(fd); return -1; } if (!adb_status(fd, error)) { adb_close(fd); return -1; } D("_adb_connect: return fd %d", fd); return fd; }
bool ReadProtocolString(int fd, std::string* s, std::string* error) { char buf[5]; if (!ReadFdExactly(fd, buf, 4)) { *error = perror_str("protocol fault (couldn't read status length)"); return false; } buf[4] = 0; unsigned long len = strtoul(buf, 0, 16); s->resize(len, '\0'); if (!ReadFdExactly(fd, &(*s)[0], len)) { *error = perror_str("protocol fault (couldn't read status message)"); return false; } return true; }
int _adb_connect(const std::string& service, std::string* error) { D("_adb_connect: %s\n", service.c_str()); if (service.empty() || service.size() > 1024) { *error = android::base::StringPrintf("bad service name length (%zd)", service.size()); return -1; } int fd; if (__adb_server_name) { std::string reason; fd = network_connect(__adb_server_name, __adb_server_port, SOCK_STREAM, 0, &reason); if (fd == -1) { *error = android::base::StringPrintf("can't connect to %s:%d: %s", __adb_server_name, __adb_server_port, reason.c_str()); return -2; } } else { fd = socket_loopback_client(__adb_server_port, SOCK_STREAM); if (fd == -1) { *error = perror_str("cannot connect to daemon"); return -2; } } if (memcmp(&service[0],"host",4) != 0 && switch_socket_transport(fd, error)) { return -1; } if(!SendProtocolString(fd, service)) { *error = perror_str("write failure during connection"); adb_close(fd); return -1; } if (!adb_status(fd, error)) { adb_close(fd); return -1; } D("_adb_connect: return fd %d\n", fd); return fd; }
int main(int argc, char *argv[]) { char canonical_path[PATH_MAX+1] = { 0 }; int i, opt; char *user = NULL, *groups = NULL; /* process arguments */ while ((opt = getopt(argc, argv, "u:g:")) != -1) { switch (opt) { case 'u': user = optarg; break; case 'g': groups = optarg; break; default: usage(argv); return 1; } } argc -= optind; argv += optind; /* get user info */ obtain_user_info(user, groups); /* process remaining args as directories */ for (i = 0; i < argc; i++) { if (!realpath(argv[i], canonical_path)) { perror_str("[!] Unable to resolve path \"%s\"", argv[i]); return 1; } scan_directory(canonical_path); } /* report the findings */ report_findings("set-uid executable", &g_suid); report_findings("set-gid executable", &g_sgid); report_findings("writable", &g_writable); #ifdef RECORD_LESS_INTERESTING report_findings("readable", &g_readable); report_findings("only executable", &g_executable); #endif return 0; }
static int switch_socket_transport(int fd, std::string* error) { std::string service; if (__adb_transport_id) { service += "host:transport-id:"; service += std::to_string(__adb_transport_id); } else if (__adb_serial) { service += "host:transport:"; service += __adb_serial; } else { const char* transport_type = "???"; switch (__adb_transport) { case kTransportUsb: transport_type = "transport-usb"; break; case kTransportLocal: transport_type = "transport-local"; break; case kTransportAny: transport_type = "transport-any"; break; case kTransportHost: // no switch necessary return 0; } service += "host:"; service += transport_type; } if (!SendProtocolString(fd, service)) { *error = perror_str("write failure during connection"); adb_close(fd); return -1; } D("Switch transport in progress"); if (!adb_status(fd, error)) { adb_close(fd); D("Switch transport failed: %s", error->c_str()); return -1; } D("Switch transport success"); return 0; }
bool adb_status(int fd, std::string* error) { char buf[5]; if (!ReadFdExactly(fd, buf, 4)) { *error = perror_str("protocol fault (couldn't read status)"); return false; } if (!memcmp(buf, "OKAY", 4)) { return true; } if (memcmp(buf, "FAIL", 4)) { *error = android::base::StringPrintf("protocol fault (status %02x %02x %02x %02x?!)", buf[0], buf[1], buf[2], buf[3]); return false; } ReadProtocolString(fd, error, error); return false; }