Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Quick, dirty and really painfully ugly way to parse the data fields out of an app store receipt.
#import <Foundation/Foundation.h>
typedef struct _ASNObject {
NSInteger index;
uint8_t type;
NSUInteger datap;
NSUInteger length;
NSUInteger next;
} ASNObject;
NSUInteger intValueFromDataAtIndexWithSize(uint16_t index, uint8_t * data, NSUInteger * value, uint16_t size ) {
while( size-- ) {
*value <<= 8;
*value |= data[ index++ ];
}
return index;
}
NSUInteger readLengthBytes(NSInteger index, uint8_t * data, NSUInteger * length) {
return intValueFromDataAtIndexWithSize(
(data[index] & 0x80) == 0x80 ? index + 1 : index,
data,
length,
(data[index] & 0x80) == 0x80 ? data[index] - 0x80 : 1
);
}
ASNObject objectAtIndex(NSInteger index, uint8_t * data) {
ASNObject obj = {0,0,0,0,0};
obj.index = index;
obj.type = data[index];
obj.datap = readLengthBytes(index + 1, data, &obj.length);
obj.next = (0x20 & obj.type) == 0x20 ? obj.datap : obj.datap + obj.length;
return obj;
}
NSInteger indexOfNextObjectOfType(NSInteger index, uint8_t * data, uint8_t type) {
ASNObject obj = objectAtIndex(index, data);
while (obj.type != type) {
obj = objectAtIndex(obj.next, data);
}
return obj.index;
}
NSInteger indexOfNextObjectOfTypeWithValue(NSInteger index, uint8_t * data, uint8_t type, uint8_t * value, uint16_t length) {
while( 1 ) {
index = indexOfNextObjectOfType(index, data, type);
ASNObject obj = objectAtIndex(index, data);
if( obj.length == length ) {
if( 0x00 == memcmp(&data[obj.datap], value, length) ) {
return obj.index;
}
}
index = obj.next;
}
return -1;
}
NSUInteger intValueFromObject(ASNObject obj, uint8_t * data) {
NSUInteger value = 0;
intValueFromDataAtIndexWithSize(obj.datap, data, &value, obj.length);
return value;
}
NSString * stringValueFromObject(ASNObject obj, uint8_t * data) {
ASNObject strobj = objectAtIndex(obj.datap, data);
if( strobj.datap + strobj.length == obj.next ) {
if( strobj.type == 0x0c || strobj.type == 0x16 ) {
return [[NSString alloc] initWithBytes: &data[strobj.datap] length: strobj.length encoding: NSUTF8StringEncoding];
}
if( strobj.type == 0x02 ) {
return [NSString stringWithFormat:@"%@", @(intValueFromObject(strobj, data))];
}
}
return [[NSData dataWithBytes:&data[obj.datap] length:obj.length] description];
}
void dumpDataSection(uint8_t * receipt_bytes) {
uint8_t data_obj_id[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01};
NSUInteger index = 0;
ASNObject octets = {};
ASNObject aapl_typ_int;
ASNObject aapl_ver_int;
ASNObject aapl_oct_str;
index = indexOfNextObjectOfTypeWithValue(0,receipt_bytes,0x06,data_obj_id, 9);
octets = objectAtIndex(indexOfNextObjectOfType(index, receipt_bytes, 0x04), receipt_bytes);
index = octets.datap;
while( index < octets.next ) {
index = indexOfNextObjectOfType(index, receipt_bytes, 0x02);
aapl_typ_int = objectAtIndex(index, receipt_bytes);
aapl_ver_int = objectAtIndex(aapl_typ_int.next, receipt_bytes);
aapl_oct_str = objectAtIndex(aapl_ver_int.next, receipt_bytes);
index = indexOfNextObjectOfType(aapl_oct_str.next, receipt_bytes, 0x30);
NSLog(
@"Type : %@ Version : %@ Octets : %@",
@(intValueFromObject(aapl_typ_int, receipt_bytes)),
@(intValueFromObject(aapl_ver_int, receipt_bytes)),
stringValueFromObject(aapl_oct_str, receipt_bytes)
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.