static void svc_process_smtp_id(char *hostname, int port, char *buf) { char *id, *t; id = strstr(buf, "SMTP ") + 5; if((t = strchr(id, ';')) != NULL) *t = '\0'; svc_display_type(hostname, port, "SMTP server", guess_version(id)); }
int do_extract(const char *output, int argc, char **argv) { if(argc != 1) { printf("You need to specify exactly one input file to extract from.\n"); return 3; } FILE *fout = NULL; if(output) { fout = fopen(output, "w"); if(fout == NULL) { printf("Cannot open output file '%s'\n", output); return 4; } } /* read elf file */ g_elf_buf = read_file(argv[0], g_elf_size); if(g_elf_buf == nullptr) { printf("Cannot open input file '%s'\n", argv[0]); return 1; } if(!elf_init()) { printf("This is not a valid ELF file\n"); return 1; } if(g_elf_symtab == nullptr) { printf("This ELF file does not have a symbol table\n"); return 1; } /* look for symbol 'AreaInfo' */ Elf32_Sym *sym_AreaInfo = elf_get_symbol_by_name("AreaInfo"); if(sym_AreaInfo == nullptr) { printf("Cannot find symbol 'AreaInfo'\n"); return 1; } printf("AreaInfo:\n"); if(g_verbose) { printf("[%u bytes at address %#x in section %u (%s)]\n", (unsigned)sym_AreaInfo->st_size, (unsigned)sym_AreaInfo->st_value, (unsigned)sym_AreaInfo->st_shndx, elf_get_section_name(sym_AreaInfo->st_shndx)); } /* guess version */ int ver = guess_version(elf_get_symbol_ptr(sym_AreaInfo, sizeof(area_info_v1_t))); if(g_verbose) printf("[guessed version: %d]\n", ver); size_t sizeof_area_info = (ver == 1) ? sizeof(area_info_v1_t) : sizeof(area_info_v2_t); size_t sizeof_zone_info = (ver == 1) ? sizeof(zone_info_v1_t) : sizeof(zone_info_v2_t); /* sanity check AreaInfo */ size_t area_count = sym_AreaInfo->st_size / sizeof_area_info; if(!g_unsafe && (sym_AreaInfo->st_size % sizeof_area_info) != 0) { printf("AreaInfo size (%u) is a not a multiple of area_info_t size (%zu).\n", (unsigned)sym_AreaInfo->st_size, sizeof_area_info); printf("Use unsafe option to override this check\n"); return 1; } area_info_v1_t *AreaInfo_v1 = (area_info_v1_t *)elf_get_symbol_ptr(sym_AreaInfo, sym_AreaInfo->st_size); area_info_v2_t *AreaInfo_v2 = (area_info_v2_t *)AreaInfo_v1; if(AreaInfo_v1 == nullptr) { printf("Symbol does not point to a valid address\n"); return 1; } for(size_t i = 0; i < area_count; i++) { uint32_t type; uint32_t *zoneinfo_ptr; uint32_t zonecount; uint32_t *name_ptr; if(ver == 1) { type = AreaInfo_v1[i].type; zoneinfo_ptr = &AreaInfo_v1[i].zoneinfo; zonecount = AreaInfo_v1[i].zonecount; name_ptr = &AreaInfo_v1[i].name; } else { type = AreaInfo_v2[i].type; zoneinfo_ptr = &AreaInfo_v2[i].zoneinfo; zonecount = AreaInfo_v2[i].zonecount; name_ptr = &AreaInfo_v2[i].name; } if(g_verbose) { printf(" [type=%u info=%#x count=%u name=%#x]\n", type, *zoneinfo_ptr, zonecount, *name_ptr); } /* translate name address */ const char *name = (const char *)elf_reloc_addr32_ptr(name_ptr); if(name == nullptr || !elf_is_str_ptr_safe(name)) { printf(" Entry name is not a string\n"); continue; } /* skip reserved entries */ if(*zoneinfo_ptr == 0) { printf(" %s\n", name); continue; } /* relocate the zoneinfo pointer */ void *Zone = elf_reloc_addr32_ptr(zoneinfo_ptr);; if(Zone == nullptr) { printf(" %s\n", name); printf(" Zone info pointer is not valid\n"); continue; } /* in safe mode, make sure the zone info pointer is a symbol */ Elf32_Sym *zoneinfo_sym = elf_get_symbol_by_ptr((void *)Zone); const char *zoneinfo_sym_name = "<no symbol>"; if(zoneinfo_sym) zoneinfo_sym_name = elf_get_symbol_name(zoneinfo_sym); printf(" %s (%s)\n", name, zoneinfo_sym_name); if(!g_unsafe && !zoneinfo_sym) { printf(" Zone info pointer does not correspond to any symbol.\n"); printf(" Use unsafe option to override this check\n"); continue; } /* if we have the symbol, make sure the claimed size match */ if(!g_unsafe && zoneinfo_sym) { if(zoneinfo_sym->st_size != sizeof_zone_info * zonecount) { printf(" Zone info symbol size (%u) does not match expected size (%zu)\n", (unsigned)zoneinfo_sym->st_size, sizeof_zone_info * zonecount); printf(" Use unsafe option to override this check\n"); continue; } } /* sanity check */ if(!elf_is_ptr_safe((void *)Zone, sizeof_zone_info * zonecount)) { printf(" Zone info pointer is not valid\n"); continue; } /* read zone */ zone_info_v1_t *Zone_v1 = (zone_info_v1_t *)Zone; zone_info_v2_t *Zone_v2 = (zone_info_v2_t *)Zone; for(size_t j = 0; j < zonecount; j++) { uint32_t node, start, count, size; uint32_t *name_ptr; if(ver == 1) { node = Zone_v1[j].node; start = Zone_v1[j].start; count = Zone_v1[j].count; size = Zone_v1[j].size; name_ptr = &Zone_v1[j].name; } else { node = Zone_v2[j].node; start = Zone_v2[j].start; count = Zone_v2[j].count; size = Zone_v2[j].size; name_ptr = &Zone_v2[j].name; } if(g_verbose) { printf(" [node=%u start=%#x count=%u size=%u name=%#x]\n", node, start, count, size, *name_ptr); } /* translate name address */ const char *name = (const char *)elf_reloc_addr32_ptr(name_ptr); if(name == nullptr || !elf_is_str_ptr_safe(name)) { printf(" Entry name is not a string\n"); continue; } printf(" %s: node %03u, size %u\n", name, node, size); if(fout) fprintf(fout, "%u,%u,%s\n", node, size, name); } } if(fout) fclose(fout); /* success */ return 0; }
static void svc_process_reply(int fd, char *hostname, int port) { FILE *sock; char buf[512], *t; if((sock = fdopen(fd, "r")) == NULL) { reply("Couldn't buffer socket: %s", strerror(errno)); close(fd); return; } fgets(buf, 512, sock); if(!strncmp(buf, "HTTP/", 5)) { while(strncmp(buf, "Server: ", 8)) { if(!fgets(buf, 512, sock)) { svc_display_type(hostname, port, "Non-RFC compliant HTTP server", NULL); return; } } chop_crlf(buf); svc_display_type(hostname, port, "HTTP server", buf + 8); } else if(!strncmp(buf, "200 ", 4)) svc_display_type(hostname, port, "NNTP server", NULL); else if(!strncmp(buf, "220 ", 4) || !strncmp(buf, "220-", 4)) { chop_crlf(buf); if(strstr(buf, " ESMTP ")) svc_process_smtp_id(hostname, port, buf); else if(!strstr(buf, "ESMTP")) svc_display_type(hostname, port, "FTP server", guess_version(buf + 4)); else { write(fd, "HELP\n", 5); fgets(buf, 512, sock); chop_crlf(buf); if((t = strchr(buf, ' ')) == NULL) t = buf; else t++; svc_display_type(hostname, port, "SMTP server", t); } } else if(!strncmp(buf, "SSH-", 4)) svc_process_ssh_id(hostname, port, buf); else if(!strncmp(buf, "* OK ", 5)) { chop_crlf(buf); svc_display_type(hostname, port, "IMAP server", guess_version(buf + 5)); } else if(!strncmp(buf, "+OK ", 4)) { chop_crlf(buf); svc_display_type(hostname, port, "POP server", guess_version(buf + 4)); } else if(!strncmp(buf, "0 , 0 :", 7) || !strncmp(buf, "0, 0 :", 6) || !strncmp(buf, "0,0 :", 5) || !strncmp(buf, "0,0:", 4)) svc_display_type(hostname, port, "IDENT server", NULL); else if(!strncmp(buf, "lpd ", 4) || strstr(buf, "lpd: ") != NULL) svc_display_type(hostname, port, "LPD server", NULL); else if(!strncmp(buf, "HEAD / HTTP/1.0", 15)) svc_display_type(hostname, port, "ECHO server", NULL); else if(strstr(buf, "NOTICE AUTH")) svc_display_type(hostname, port, "IRC server", NULL); else svc_display_type(hostname, port, "Active server of unknown type", NULL); fclose(sock); }