AVI file reader for SECCON 2019 Online CTF
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
char buf[1024 * 1024 * 4]; | |
typedef struct _avimainheader { | |
uint32_t fcc; | |
uint32_t cb; | |
uint32_t dwMicroSecPerFrame; | |
uint32_t dwMaxBytesPerSec; | |
uint32_t dwPaddingGranularity; | |
uint32_t dwFlags; | |
uint32_t dwTotalFrames; | |
uint32_t dwInitialFrames; | |
uint32_t dwStreams; | |
uint32_t dwSuggestedBufferSize; | |
uint32_t dwWidth; | |
uint32_t dwHeight; | |
uint32_t dwReserved[4]; | |
} AVIMAINHEADER; | |
typedef struct { | |
uint32_t ckid; | |
uint32_t dwFlags; | |
uint32_t dwChunkOffset; | |
uint32_t dwChunkLength; | |
} AVIINDEXENTRY; | |
typedef struct { | |
uint32_t CompressedBMHeight; | |
uint32_t CompressedBMWidth; | |
uint32_t ValidBMHeight; | |
uint32_t ValidBMWidth; | |
uint32_t ValidBMXOffset; | |
uint32_t ValidBMYOffset; | |
uint32_t VideoXOffsetInT; | |
uint32_t VideoYValidStartLine; | |
} VIDEO_FIELD_DESC; | |
typedef struct { | |
uint32_t VideoFormatToken; | |
uint32_t VideoStandard; | |
uint32_t dwVerticalRefreshRate; | |
uint32_t dwHTotalInT; | |
uint32_t dwVTotalInLines; | |
uint32_t dwFrameAspectRatio; | |
uint32_t dwFrameWidthInPixels; | |
uint32_t dwFrameHeightInLines; | |
uint32_t nbFieldPerFrame; | |
VIDEO_FIELD_DESC FieldInfo[]; | |
} VideoPropHeader; | |
void pad(int depth) { | |
for (int i = 0; i < depth * 2; i++) putchar(' '); | |
} | |
void parse(int idx, int chunk_size, int depth) { | |
int i = idx; | |
while (i < chunk_size) { | |
i = (i + 1) & ~1; | |
pad(depth); | |
printf("@+0x%06X: %.4s\n", i, &buf[i]); | |
int size = *(uint32_t *)&buf[i + 4]; | |
pad(depth); | |
printf(" size = %d\n", size); | |
if (strncmp(&buf[i], "avih", 4) == 0) { | |
AVIMAINHEADER *avih = (AVIMAINHEADER *)&buf[i]; | |
pad(depth); | |
printf(" dwFlags=0x%X\n", avih->dwFlags); | |
pad(depth); | |
printf(" dwTotalFrames=%d\n", avih->dwTotalFrames); | |
pad(depth); | |
printf(" w=%d\n", avih->dwWidth); | |
pad(depth); | |
printf(" h=%d\n", avih->dwHeight); | |
} | |
if (strncmp(&buf[i], "LIST", 4) == 0) { | |
pad(depth); | |
printf(" %.4s\n", &buf[i + 8]); | |
parse(i + 12, size - 4, depth + 1); | |
} | |
if (strncmp(&buf[i], "RIFF", 4) == 0) { | |
pad(depth); | |
printf(" %.4s\n", &buf[i + 8]); | |
parse(i + 12, size - 4, depth + 1); | |
} | |
if (strncmp(&buf[i], "vprp", 4) == 0) { | |
VideoPropHeader *e = (VideoPropHeader *)&buf[i + 8]; | |
pad(depth); | |
printf(" VideoFormatToken: 0x%08X\n", e->VideoFormatToken); | |
printf(" VideoStandard: 0x%08X\n", e->VideoStandard); | |
printf(" dwVerticalRefreshRate: 0x%08X\n", e->dwVerticalRefreshRate); | |
printf(" dwHTotalInT: 0x%08X\n", e->dwHTotalInT); | |
printf(" dwVTotalInLines: 0x%08X\n", e->dwVTotalInLines); | |
printf(" dwFrameAspectRatio: 0x%08X\n", e->dwFrameAspectRatio); | |
printf(" dwFrameHeightInLines: 0x%08X\n", e->dwFrameHeightInLines); | |
printf(" nbFieldPerFrame: 0x%08X\n", e->nbFieldPerFrame); | |
} | |
if (strncmp(&buf[i], "00dc", 4) == 0) { | |
pad(depth); | |
int k = 0; | |
for (; k < 8; k++) { | |
printf(" %02X", (uint8_t)buf[i + 8 + k]); | |
} | |
for (; k < size; k++) { | |
if (k % 32 == 8) { | |
putchar('\n'); | |
pad(depth); | |
} | |
printf(" %02X", (uint8_t)buf[i + 8 + k]); | |
} | |
putchar('\n'); | |
} | |
if (strncmp(&buf[i], "idx1", 4) == 0) { | |
AVIINDEXENTRY *e = (AVIINDEXENTRY *)&buf[i + 8]; | |
for (int k = 0; k < size / sizeof(AVIINDEXENTRY); k++) { | |
pad(depth); | |
printf(" %3d: (%8X) +0x%8X %8d\n", k, e[k].dwFlags, e[k].dwChunkOffset, | |
e[k].dwChunkLength); | |
} | |
} | |
i += 8 + size; | |
} | |
} | |
int main(int argc, char *argv[]) { | |
FILE *fp = fopen(argv[1], "rb"); | |
if (!fp) return 1; | |
int file_size = fread(buf, 1, sizeof(buf), fp); | |
printf("file size: %d\n", file_size); | |
int i = 0; | |
while (buf[i] == 0) i++; | |
parse(i, file_size - i, 0); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment