format value::pp(bool unicode) const { return unicode ? format(get_unicode_name()) : pp(); }
vba_project_t * cli_vba_readdir(const char *dir, struct uniq *U, uint32_t which) { unsigned char *buf; const unsigned char vba56_signature[] = { 0xcc, 0x61 }; uint16_t record_count, buflen, ffff, byte_count; uint32_t offset; int i, j, fd, big_endian = FALSE; vba_project_t *vba_project; struct vba56_header v56h; off_t seekback; char fullname[1024], *hash; cli_dbgmsg("in cli_vba_readdir()\n"); if(dir == NULL) return NULL; /* * _VBA_PROJECT files are embedded within office documents (OLE2) */ if (!uniq_get(U, "_vba_project", 12, &hash)) return NULL; snprintf(fullname, sizeof(fullname), "%s"PATHSEP"%s_%u", dir, hash, which); fullname[sizeof(fullname)-1] = '\0'; fd = open(fullname, O_RDONLY|O_BINARY); if(fd == -1) return NULL; if(cli_readn(fd, &v56h, sizeof(struct vba56_header)) != sizeof(struct vba56_header)) { close(fd); return NULL; } if (memcmp(v56h.magic, vba56_signature, sizeof(v56h.magic)) != 0) { close(fd); return NULL; } i = vba_read_project_strings(fd, TRUE); if ((seekback = lseek(fd, 0, SEEK_CUR)) == -1) { cli_dbgmsg("vba_readdir: lseek() failed. Unable to guess VBA type\n"); close(fd); return NULL; } if (lseek(fd, sizeof(struct vba56_header), SEEK_SET) == -1) { cli_dbgmsg("vba_readdir: lseek() failed. Unable to guess VBA type\n"); close(fd); return NULL; } j = vba_read_project_strings(fd, FALSE); if(!i && !j) { close(fd); cli_dbgmsg("vba_readdir: Unable to guess VBA type\n"); return NULL; } if (i > j) { big_endian = TRUE; if (lseek(fd, seekback, SEEK_SET) == -1) { cli_dbgmsg("vba_readdir: call to lseek() while guessing big-endian has failed\n"); close(fd); return NULL; } cli_dbgmsg("vba_readdir: Guessing big-endian\n"); } else { cli_dbgmsg("vba_readdir: Guessing little-endian\n"); } /* junk some more stuff */ do if (cli_readn(fd, &ffff, 2) != 2) { close(fd); return NULL; } while(ffff != 0xFFFF); /* check for alignment error */ if(!seekandread(fd, -3, SEEK_CUR, &ffff, sizeof(uint16_t))) { close(fd); return NULL; } if (ffff != 0xFFFF) { if (lseek(fd, 1, SEEK_CUR) == -1) { cli_dbgmsg("call to lseek() while checking alignment error has failed\n"); close(fd); return NULL; } } if(!read_uint16(fd, &ffff, big_endian)) { close(fd); return NULL; } if(ffff != 0xFFFF) { if (lseek(fd, ffff, SEEK_CUR) == -1) { cli_dbgmsg("call to lseek() while checking alignment error has failed\n"); close(fd); return NULL; } } if(!read_uint16(fd, &ffff, big_endian)) { close(fd); return NULL; } if(ffff == 0xFFFF) ffff = 0; if (lseek(fd, ffff + 100, SEEK_CUR) == -1) { cli_dbgmsg("call to lseek() failed\n"); close(fd); return NULL; } if(!read_uint16(fd, &record_count, big_endian)) { close(fd); return NULL; } cli_dbgmsg("vba_readdir: VBA Record count %d\n", record_count); if (record_count == 0) { /* No macros, assume clean */ close(fd); return NULL; } if (record_count > MAX_VBA_COUNT) { /* Almost certainly an error */ cli_dbgmsg("vba_readdir: VBA Record count too big\n"); close(fd); return NULL; } vba_project = create_vba_project(record_count, dir, U); if(vba_project == NULL) { close(fd); return NULL; } buf = NULL; buflen = 0; for(i = 0; i < record_count; i++) { uint16_t length; char *ptr; vba_project->colls[i] = 0; if(!read_uint16(fd, &length, big_endian)) break; if (length == 0) { cli_dbgmsg("vba_readdir: zero name length\n"); break; } if(length > buflen) { unsigned char *newbuf = (unsigned char *)cli_realloc(buf, length); if(newbuf == NULL) break; buflen = length; buf = newbuf; } if (cli_readn(fd, buf, length) != length) { cli_dbgmsg("vba_readdir: read name failed\n"); break; } ptr = get_unicode_name((const char *)buf, length, big_endian); if(ptr == NULL) break; if (!(vba_project->colls[i]=uniq_get(U, ptr, strlen(ptr), &hash))) { cli_dbgmsg("vba_readdir: cannot find project %s (%s)\n", ptr, hash); free(ptr); break; } cli_dbgmsg("vba_readdir: project name: %s (%s)\n", ptr, hash); free(ptr); vba_project->name[i] = hash; if(!read_uint16(fd, &length, big_endian)) break; lseek(fd, length, SEEK_CUR); if(!read_uint16(fd, &ffff, big_endian)) break; if (ffff == 0xFFFF) { lseek(fd, 2, SEEK_CUR); if(!read_uint16(fd, &ffff, big_endian)) break; lseek(fd, ffff + 8, SEEK_CUR); } else lseek(fd, ffff + 10, SEEK_CUR); if(!read_uint16(fd, &byte_count, big_endian)) break; lseek(fd, (8 * byte_count) + 5, SEEK_CUR); if(!read_uint32(fd, &offset, big_endian)) break; cli_dbgmsg("vba_readdir: offset: %u\n", (unsigned int)offset); vba_project->offset[i] = offset; lseek(fd, 2, SEEK_CUR); } if(buf) free(buf); close(fd); if(i < record_count) { free(vba_project->name); free(vba_project->colls); free(vba_project->dir); free(vba_project->offset); free(vba_project); return NULL; } return vba_project; }
static int vba_read_project_strings(int fd, int big_endian) { unsigned char *buf = NULL; uint16_t buflen = 0; int ret = 0; for(;;) { off_t offset; uint16_t length; char *name; if(!read_uint16(fd, &length, big_endian)) break; if (length < 6) { lseek(fd, -2, SEEK_CUR); break; } if(length > buflen) { unsigned char *newbuf = (unsigned char *)cli_realloc(buf, length); if(newbuf == NULL) { if(buf) free(buf); return 0; } buflen = length; buf = newbuf; } offset = lseek(fd, 0, SEEK_CUR); if(cli_readn(fd, buf, length) != (int)length) { cli_dbgmsg("read name failed - rewinding\n"); lseek(fd, offset, SEEK_SET); break; } name = get_unicode_name((const char *)buf, length, big_endian); cli_dbgmsg("length: %d, name: %s\n", length, (name) ? name : "[null]"); if((name == NULL) || (memcmp("*\\", name, 2) != 0) || (strchr("ghcd", name[2]) == NULL)) { /* Not a string */ lseek(fd, -(length+2), SEEK_CUR); if(name) free(name); break; } free(name); if(!read_uint16(fd, &length, big_endian)) { if(buf) free(buf); break; } ret++; if ((length != 0) && (length != 65535)) { lseek(fd, -2, SEEK_CUR); continue; } offset = lseek(fd, 10, SEEK_CUR); cli_dbgmsg("offset: %lu\n", (unsigned long)offset); vba56_test_middle(fd); } if(buf) free(buf); return ret; }
/* return count of valid strings found, 0 on error */ static int vba_read_project_strings(int fd, int big_endian) { unsigned char *buf = NULL; uint16_t buflen = 0; uint16_t length = 0; int ret = 0, getnewlength = 1; for(;;) { off_t offset; char *name; /* if no initial name length, exit */ if(getnewlength && !read_uint16(fd, &length, big_endian)) { ret = 0; break; } getnewlength = 0; /* if too short, break */ if (length < 6) { if (lseek(fd, -2, SEEK_CUR) == -1) { cli_dbgmsg("vba_read_project_strings: call to lseek() has failed\n"); ret = 0; } break; } /* ensure buffer is large enough */ if(length > buflen) { unsigned char *newbuf = (unsigned char *)cli_realloc(buf, length); if(newbuf == NULL) { ret = 0; break; } buflen = length; buf = newbuf; } /* save current offset */ offset = lseek(fd, 0, SEEK_CUR); if (offset == -1) { cli_dbgmsg("vba_read_project_strings: call to lseek() has failed\n"); ret = 0; break; } /* if read name failed, break */ if(cli_readn(fd, buf, length) != (int)length) { cli_dbgmsg("read name failed - rewinding\n"); if (lseek(fd, offset, SEEK_SET) == -1) { cli_dbgmsg("call to lseek() in read name failed\n"); ret = 0; } break; } name = get_unicode_name((const char *)buf, length, big_endian); cli_dbgmsg("length: %d, name: %s\n", length, (name) ? name : "[null]"); /* if invalid name, break */ if((name == NULL) || (memcmp("*\\", name, 2) != 0) || (strchr("ghcd", name[2]) == NULL)) { /* Not a valid string, rewind */ if (lseek(fd, -(length+2), SEEK_CUR) == -1) { cli_dbgmsg("call to lseek() after get_unicode_name has failed\n"); ret = 0; } free(name); break; } free(name); /* can't get length, break */ if(!read_uint16(fd, &length, big_endian)) { break; } ret++; /* continue on reasonable length value */ if ((length != 0) && (length != 65535)) { continue; } /* determine offset and run middle test */ offset = lseek(fd, 10, SEEK_CUR); if (offset == -1) { cli_dbgmsg("call to lseek() has failed\n"); ret = 0; break; } cli_dbgmsg("offset: %lu\n", (unsigned long)offset); vba56_test_middle(fd); getnewlength = 1; } free(buf); return ret; }
void wm_decode_macro (unsigned char *buff, uint32_t len, int hex_output) { int i, j; uint8_t s_length; uint16_t w_length, int_val; unsigned char *tmp_buff, *tmp_name, *line_start; i = 2; line_start = buff; while (i < len) { switch (buff[i]) { case 0x65: s_length = (uint8_t) buff[i + 1]; tmp_buff = (unsigned char *) malloc (s_length + 1); strncpy ((char *) tmp_buff, (char *) (buff + i + 2), s_length); tmp_buff[s_length] = '\0'; print_hex_buff (line_start, buff + i + 2 + s_length, hex_output); printf ("\n%s", tmp_buff); free (tmp_buff); i += 2 + s_length; line_start = buff + i; break; case 0x69: s_length = (uint8_t) buff[i + 1]; tmp_buff = (unsigned char *) malloc (s_length + 1); strncpy ((char *) tmp_buff, (char *) (buff + i + 2), s_length); tmp_buff[s_length] = '\0'; printf (" %s", tmp_buff); free (tmp_buff); i += 2 + s_length; break; case 0x6a: s_length = (uint8_t) buff[i + 1]; tmp_buff = (unsigned char *) malloc (s_length + 1); strncpy ((char *) tmp_buff, (char *) (buff + i + 2), s_length); tmp_buff[s_length] = '\0'; printf (" \"%s\"", tmp_buff); free (tmp_buff); i += 2 + s_length; break; case 0x6b: s_length = (uint8_t) buff[i + 1]; tmp_buff = (unsigned char *) malloc (s_length + 1); strncpy ((char *) tmp_buff, (char *) (buff + i + 2), s_length); tmp_buff[s_length] = '\0'; printf (" '%s", tmp_buff); free (tmp_buff); i += 2 + s_length; break; case 0x6d: s_length = (uint8_t) buff[i + 1]; tmp_buff = (unsigned char *) malloc (s_length + 1); strncpy ((char *) tmp_buff, (char *) (buff + i + 2), s_length); tmp_buff[s_length] = '\0'; printf (" %s", tmp_buff); free (tmp_buff); i += 2 + s_length; break; case 0x70: s_length = (uint8_t) buff[i + 1]; tmp_buff = (unsigned char *) malloc (s_length + 1); strncpy ((char *) tmp_buff, (char *) (buff + i + 2), s_length); tmp_buff[s_length] = '\0'; printf ("REM%s", tmp_buff); free (tmp_buff); i += 2 + s_length; break; case 0x76: s_length = (uint8_t) buff[i + 1]; tmp_buff = (unsigned char *) malloc (s_length + 1); strncpy ((char *) tmp_buff, (char *) (buff + i + 2), s_length); tmp_buff[s_length] = '\0'; printf (" .%s", tmp_buff); free (tmp_buff); i += 2 + s_length; break; case 0x77: s_length = (uint8_t) buff[i + 1]; tmp_buff = (unsigned char *) malloc (s_length + 1); strncpy ((char *) tmp_buff, (char *) (buff + i + 2), s_length); tmp_buff[s_length] = '\0'; printf ("%s", tmp_buff); free (tmp_buff); i += 2 + s_length; break; case 0x79: /* unicode "string" */ w_length = (uint16_t) (buff[i + 2] << 8) + buff[i + 1]; tmp_buff = (unsigned char *) malloc ((w_length * 2) + 1); memcpy (tmp_buff, buff + i + 3, w_length * 2); tmp_name = (unsigned char *) get_unicode_name ((char *) tmp_buff, w_length * 2); free (tmp_buff); printf ("\"%s\"", tmp_name); free (tmp_name); i += 3 + (w_length * 2); break; case 0x7c: /* unicode 'string */ s_length = (uint8_t) buff[i + 1]; tmp_buff = (unsigned char *) malloc ((s_length * 2) + 1); memcpy (tmp_buff, buff + i + 2, s_length * 2); tmp_name = (unsigned char *) get_unicode_name ((char *) tmp_buff, s_length * 2); free (tmp_buff); printf ("'%s", tmp_name); free (tmp_name); i += 2 + (s_length * 2); break; case 0x66: int_val = (uint8_t) (buff[i + 2] << 8) + buff[i + 1]; print_hex_buff (line_start, buff + i + 3, hex_output); printf ("\n%d", int_val); i += 3; line_start = buff + i; break; case 0x67: w_length = (uint16_t) (buff[i + 2] << 8) + buff[i + 1]; output_token67 (w_length); i += 3; break; case 0x68: /* 8-byte float */ printf ("(float)"); i += 9; break; case 0x6c: int_val = (uint16_t) (buff[i + 2] << 8) + buff[i + 1]; printf (" %d", int_val); i += 3; break; case 0x6e: s_length = (uint8_t) buff[i + 1]; for (j = 0; j < s_length; j++) { printf (" "); } i += 2; break; case 0x6f: s_length = (uint8_t) buff[i + 1]; for (j = 0; j < s_length; j++) { printf ("\t"); } i += 2; break; case 0x73: w_length = (uint16_t) (buff[i + 2] << 8) + buff[i + 1]; output_token73 (w_length); i += 3; break; case 0x64: print_hex_buff (line_start, buff + i + 1, hex_output); printf ("\n"); i++; line_start = buff + i; break; default: output_token (buff[i]); i++; break; } } print_hex_buff (line_start, buff + i, hex_output); }