Created
March 21, 2019 20:14
-
-
Save lighth7015/ad90db974e15dc40e018bf2c3d14c0fd to your computer and use it in GitHub Desktop.
AOL packet parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdint.h> | |
const uint8_t* packet = (const uint8_t *) | |
"5A413800347F7FA3036B0100F5000000050F00002152CBCA070A1000080400000000035F0000010004000300080000000000000000000000020D"; | |
#ifndef NDEBUG | |
void g_log_write_event(const char *fmt, const char* filename, const char* source, int line, ...) | |
{ | |
va_list args; | |
va_start(args, line); | |
char *entry; | |
vasprintf(&entry, fmt, args); | |
printf("%s[%d] %-16s: %s\n", filename, line, source, entry); | |
va_end(args); | |
free(entry); | |
} | |
#define g_write_log(format, ...) \ | |
g_log_write_event(format, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) | |
#else | |
#define g_write_log(format, ...) | |
#endif | |
typedef | |
struct Header | |
{ | |
uint8_t magic; /* always 0x5a */ | |
uint16_t checksum; /* a simple CRC16 on the packet | |
not including magic */ | |
uint16_t size; /* total size of the packet from next byte, | |
* not including the stop byte | |
*/ | |
uint8_t seq; | |
uint8_t ack; | |
#if WORDS_BIGENDIAN | |
uint8_t client:1; /* this bit is always set for client */ | |
uint8_t type:7; /* see below */ | |
#else | |
uint8_t type:7; /* see below */ | |
uint8_t client:1; /* this is always set for client */ | |
#endif | |
} | |
__attribute__ ((packed)) *protocol_header_t; | |
typedef struct | |
Packet { | |
uint8_t magic; /* 0x03 for windows , 0x0c for Mac */ | |
uint8_t version; /* see above */ | |
uint8_t subversion; | |
uint8_t unused; | |
uint8_t machinemem; /* unused alway 0 */ | |
uint8_t appmem; /* unused always 16 */ | |
uint16_t pctype; /* unused always 0 */ | |
uint8_t release_month; /* unused alway 5 */ | |
uint8_t release_day; /* unused alway 15 */ | |
uint16_t customer_class; /* unused always 0 */ | |
uint32_t timestamp; /* timestamp of the version */ | |
uint16_t dosversion; | |
uint16_t flags; /* curently don't know what they are for */ | |
uint8_t video; | |
uint8_t processor; | |
uint32_t media; | |
uint32_t winversion; | |
uint8_t winmode; /* an old remanant field ;) alaways 1 */ | |
uint16_t xres; | |
uint16_t yres; | |
uint16_t nbcolors; /* for 16&24 bits depth: 0xffff */ | |
uint8_t filler; /* unused alway 0 */ | |
uint16_t region; /* it seems always 0 */ | |
uint16_t languages[4]; | |
uint8_t speed; /* don't know how it is coded */ | |
} | |
__attribute__ ((packed)) *protocol_packet_t; | |
uint16_t | |
CompCRC16( const unsigned char *buffer, size_t num_bytes ) | |
{ | |
unsigned char i; | |
unsigned int data, crc = 0xffff; | |
if (num_bytes == 0) | |
return (~crc); | |
do { | |
for ( i=0, data=(unsigned int)0xff & *buffer++ | |
; i < 8 | |
; i++, data >>= 1) | |
{ | |
if ((crc & 0x0001) ^ (data & 0x0001)) | |
crc = (crc >> 1) ^ 0x8408; | |
else crc >>= 1; | |
} | |
} while (--num_bytes); | |
crc =~ crc; | |
data = crc; | |
return (crc << 8) | (data >> 8 & 0xff); | |
} | |
void hexdump(void *addr, char *desc, int len) | |
{ | |
unsigned char buff[17]; | |
unsigned char *pc = (unsigned char*)addr; | |
int i = 0; | |
// Output description if given. | |
if (desc != NULL) | |
printf ("%s:\n", desc); | |
// Process every byte in the data. | |
for (; i < len; i++) { | |
// Multiple of 16 means new line (with line offset). | |
if ((i % 16) == 0) { | |
// Just don't print ASCII for the zeroth line. | |
if (i != 0) | |
printf(" %s\n", buff); | |
// Output the offset. | |
printf(" %04x ", i); | |
} | |
// Now the hex code for the specific character. | |
printf(" %02x", pc[i]); | |
// And store a printable ASCII character for later. | |
if ((pc[i] < 0x20) || (pc[i] > 0x7e)) { | |
buff[i % 16] = '.'; | |
} else { | |
buff[i % 16] = pc[i]; | |
} | |
buff[(i % 16) + 1] = '\0'; | |
} | |
// Pad out last line if not exactly 16 characters. | |
while ((i % 16) != 0) { | |
printf(" "); | |
i++; | |
} | |
// And print the final ASCII bit. | |
printf(" %s\n", buff); | |
} | |
int decode_hex(char c) | |
{ | |
int first = c / 16 - 3; | |
int second = c % 16; | |
int result = first * 10 + | |
second; | |
if(result > 9) | |
result--; | |
return result; | |
} | |
char decode_str(char c, char d) | |
{ | |
return (decode_hex(c) * 16 + | |
decode_hex(d)); | |
} | |
int main(){ | |
const char* st = (const char*) packet; | |
const uint32_t nbytes = strlen(st) / 2; | |
char* buffer = calloc(nbytes, sizeof(char)); | |
for(uint32_t c = packet[0], p = 0, i = 0; i < strlen(st) / 2; i++, c = packet[i]) | |
{ | |
if (i % 2 != 0) { | |
buffer[i / 2] = decode_str( p, st[i]); | |
} | |
else { | |
p = c; | |
} | |
} | |
size_t hdrlen = sizeof(struct Header), | |
offset = nbytes - sizeof(struct Header); | |
size_t length = nbytes - hdrlen; | |
protocol_header_t h = (protocol_header_t) buffer; | |
protocol_packet_t p = (protocol_packet_t) (buffer + hdrlen); | |
printf( "\n" ); | |
hexdump((void *) h, "Packet header", hdrlen); | |
printf( "\n" ); | |
hexdump((void *) p, "Packet content", length); | |
printf( "\n" ); | |
printf( "Packet info:\n" ); | |
printf( "\n" ); | |
g_write_log( "Request %-24s: %X, %x [%x + %x]", "magic/checksum", | |
h->magic, h->checksum, CompCRC16( (uint8_t *) buffer + offset, length), | |
CompCRC16( (uint8_t *) p, length )); | |
/* | |
g_write_log( "Machine %-24s: (%d, %d)", "resolution", p->xres, p->yres ); | |
g_write_log( "Machine %-24s: %d", "app memory", p->appmem ); | |
g_write_log( "Machine %-24s: %d", "video mode", p->video ); | |
g_write_log( "Machine %-24s: %x", "OS version", p->winversion ); | |
*/ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment