Skip to content

Instantly share code, notes, and snippets.

@hikalium
Created October 20, 2019 06:29
Show Gist options
  • Save hikalium/7567d487d32af63ec0f4bc68e5a354cb to your computer and use it in GitHub Desktop.
Save hikalium/7567d487d32af63ec0f4bc68e5a354cb to your computer and use it in GitHub Desktop.
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