📄 magic.c
字号:
while (isascii((u_char) *p) && isspace((u_char) *p)) p++; if (*p == 'u') { p++; m->flag |= UNSIGNED; } /* Get type, skip it. */ t = p; for (i = 0; i < 12; i++) { j = strlen(Magictypes[i]); if (strncmp(p, Magictypes[i], j) == 0) { m->type = i + 1; p += j; break; } } if (p == t) errx(1, "magic_parse: type %s invalid", p); /* New-style and'ing: "0 byte&0x80 =0x80 dynamically linked" */ if (*p == '&') { p++; m->mask = signextend(m, strtoul(p, &p, 0)); eatsize(&p); } else m->mask = ~0L; while (isascii((u_char) *p) && isspace((u_char) *p)) p++; switch(*p) { case '>': case '<': /* Old-style and'ing: "0 byte &0x80 dynamically linked" */ case '&': case '^': case '=': m->reln = *p; p++; break; case '!': if (m->type != STRING) { m->reln = *p; p++; break; } /* FALLTHRU */ default: if (*p == 'x' && isascii((u_char) p[1]) && isspace((u_char) p[1])) { m->reln = *p; p++; goto parse_get_desc; /* Bill The Cat */ } m->reln = '='; break; } while (isascii((u_char) *p) && isspace((u_char) *p)) p++; if (getvalue(m, &p)) return (0); parse_get_desc: /* Now get last part - the description. */ while (isascii((u_char) *p) && isspace((u_char) *p)) p++; strlcpy(m->desc, p, sizeof(m->desc)); if (Opt_debug) { mdump(m); } Magiccnt++; return (1);}voidmagic_init(char *filename){ FILE *f; char buf[BUFSIZ]; if ((f = fopen(filename, "r")) == NULL) { err(1, "magic_init"); } memset(&Magic, 0, sizeof(Magic)); while (fgets(buf, sizeof(buf), f) != NULL) { if (buf[0] == '#') continue; if (strlen(buf) <= 1) continue; buf[strlen(buf) - 1] = '\0'; magic_parse(buf); } fclose(f);}/* Convert the byte order of the data we are looking at */static intmconvert(union VALUETYPE *p, struct magic *m){ switch (m->type) { case BYTE: case SHORT: case LONG: case DATE: return (1); case STRING: { char *ptr; /* Null terminate and eat the return */ p->s[sizeof(p->s) - 1] = '\0'; if ((ptr = strchr(p->s, '\n')) != NULL) *ptr = '\0'; return (1); } case BESHORT: p->h = (short)((p->hs[0]<<8)|(p->hs[1])); return (1); case BELONG: case BEDATE: p->l = (int32_t)((p->hl[0]<<24)|(p->hl[1]<<16)| (p->hl[2]<<8)|(p->hl[3])); return (1); case LESHORT: p->h = (short)((p->hs[1]<<8)|(p->hs[0])); return (1); case LELONG: case LEDATE: p->l = (int32_t)((p->hl[3]<<24)|(p->hl[2]<<16)| (p->hl[1]<<8)|(p->hl[0])); return (1); default: errx(1, "mconvert: invalid type %d", m->type); } return (0);}static intmget(union VALUETYPE* p, u_char *s, struct magic *m, int nbytes){ int32_t offset = m->offset; if (offset + sizeof(union VALUETYPE) <= nbytes) memcpy(p, s + offset, sizeof(*p)); else { /* * the usefulness of padding with zeroes eludes me, it * might even cause problems */ int32_t have = nbytes - offset; memset(p, 0, sizeof(*p)); if (have > 0) memcpy(p, s + offset, have); } if (!mconvert(p, m)) return (0); if (m->flag & INDIR) { switch (m->in.type) { case BYTE: offset = p->b + m->in.offset; break; case SHORT: offset = p->h + m->in.offset; break; case LONG: offset = p->l + m->in.offset; break; } if (offset + sizeof(*p) > nbytes) return (0); memcpy(p, s + offset, sizeof(*p)); if (!mconvert(p, m)) return (0); } return (1);}static intmcheck(union VALUETYPE* p, struct magic *m){ register u_int32_t l = m->value.l; register u_int32_t v = 0; int matched; if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) { warnx("mcheck: BOINK"); return (1); } switch (m->type) { case BYTE: v = p->b; break; case SHORT: case BESHORT: case LESHORT: v = p->h; break; case LONG: case BELONG: case LELONG: case DATE: case BEDATE: case LEDATE: v = p->l; break; case STRING: l = 0; /* What we want here is: * v = strncmp(m->value.s, p->s, m->vallen); * but ignoring any nulls. bcmp doesn't give -/+/0 * and isn't universally available anyway. */ v = 0; { register u_char *a = (u_char *) m->value.s; register u_char *b = (u_char *) p->s; register int len = m->vallen; while (--len >= 0) if ((v = *b++ - *a++) != '\0') break; } break; default: errx(1, "mcheck: invalid type %d", m->type); /* NOTREACHED */ } v = signextend(m, v) & m->mask; switch (m->reln) { case 'x': matched = 1; break; case '!': matched = v != l; break; case '=': matched = v == l; break; case '>': if (m->flag & UNSIGNED) { matched = v > l; } else matched = (int32_t) v > (int32_t) l; break; case '<': if (m->flag & UNSIGNED) { matched = v < l; } else matched = (int32_t) v < (int32_t) l; break; case '&': matched = (v & l) == l; break; case '^': matched = (v & l) != l; break; default: matched = 0; errx(1, "mcheck: can't happen: invalid relation %d", m->reln); /* NOTREACHED */ } if (matched && Opt_debug) mdump(m); return (matched);}static int32_tmprint(union VALUETYPE *p, struct magic *m){ int32_t t = 0; switch (m->type) { case BYTE: t = m->offset + sizeof(char); break; case SHORT: case BESHORT: case LESHORT: t = m->offset + sizeof(short); break; case LONG: case BELONG: case LELONG: t = m->offset + sizeof(int32_t); break; case STRING: if (m->reln == '=') { t = m->offset + strlen(m->value.s); } else { if (*m->value.s == '\0') { char *cp = strchr(p->s,'\n'); if (cp) *cp = '\0'; } t = m->offset + strlen(p->s); } break; case DATE: case BEDATE: case LEDATE: t = m->offset + sizeof(time_t); break; default: errx(1, "mprint: invalid m->type (%d)", m->type); } strncpy(Match, m->desc, sizeof(Match)); return (t);}/* * Go through the whole list, stopping if you find a match. Process all * the continuations of that match before returning. * * We support multi-level continuations: * * At any time when processing a successful top-level match, there is a * current continuation level; it represents the level of the last * successfully matched continuation. * * Continuations above that level are skipped as, if we see one, it * means that the continuation that controls them - i.e, the * lower-level continuation preceding them - failed to match. * * Continuations below that level are processed as, if we see one, * it means we've finished processing or skipping higher-level * continuations under the control of a successful or unsuccessful * lower-level continuation, and are now seeing the next lower-level * continuation and should process it. The current continuation * level reverts to the level of the one we're seeing. * * Continuations at the current level are processed as, if we see * one, there's no lower-level continuation that may have failed. * * If a continuation matches, we bump the current continuation level * so that higher-level continuations are processed. */char *magic_match(u_char *s, int len){ int i, cont_level = 0; union VALUETYPE p; static int32_t *tmpoff = NULL; static size_t tmplen = 0; int32_t oldoff = 0; Match[0] = '\0'; if (tmpoff == NULL) if ((tmpoff = (int32_t *) malloc(tmplen = 20)) == NULL) err(1, "malloc"); for (i = 0; i < Magiccnt; i++) { /* if main entry matches, print it... */ if (!mget(&p, s, &Magic[i], len) || !mcheck(&p, &Magic[i])) { /* * main entry didn't match, * flush its continuations */ while (i < Magiccnt && Magic[i + 1].cont_level != 0) i++; continue; } tmpoff[cont_level] = mprint(&p, &Magic[i]); /* and any continuations that match */ if (++cont_level >= tmplen) { tmplen += 20; if (!(tmpoff = (int32_t *) realloc(tmpoff, tmplen))) err(1, "magic_match: malloc"); } while (Magic[i + 1].cont_level != 0 && ++i < Magiccnt) { if (cont_level >= Magic[i].cont_level) { if (cont_level > Magic[i].cont_level) { /* * We're at the end of the level * "cont_level" continuations. */ cont_level = Magic[i].cont_level; } if (Magic[i].flag & ADD) { oldoff = Magic[i].offset; Magic[i].offset += tmpoff[cont_level - 1]; } if (mget(&p, s, &Magic[i], len) && mcheck(&p, &Magic[i])) { /* This continuation matched. */ tmpoff[cont_level] = mprint(&p, &Magic[i]); /* * If we see any continuations * at a higher level, process them. */ if (++cont_level >= tmplen) { tmplen += 20; if (!(tmpoff = (int32_t *) realloc(tmpoff, tmplen))) err(1, "magic_check: " "malloc"); } } if (Magic[i].flag & ADD) { Magic[i].offset = oldoff; } } } return (strlen(Match) ? Match : NULL); /* all through */ } return (NULL); /* no match at all */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -