UNPKG

js-apk-parser

Version:

Parse the AndroidManifest.xml and resources.arsc file in the apk package.

244 lines 11.9 kB
import * as util from './util'; var AndroidManifest = /** @class */ (function () { function AndroidManifest(buffer) { var _a; var _this = this; this.magicNumber = util.uint8ArrayToHex(new Uint8Array(buffer, 0, 4)); this.fileSize = util.uint8ArrayToInt(new Uint8Array(buffer, 4, 4)); // console.log(`magicNumber: ${this.magicNumber}, fileSize: ${this.fileSize}`); var chunkOffset = 8; var chunkSize = util.uint8ArrayToInt(new Uint8Array(buffer, chunkOffset + 4 * 1, 4)); this.stringChunk = new StringChunk(new Uint8Array(buffer, chunkOffset, chunkSize)); // console.log('stringChunk', this.stringChunk); chunkOffset += chunkSize; chunkSize = util.uint8ArrayToInt(new Uint8Array(buffer, chunkOffset + 4 * 1, 4)); this.resourceIdChunk = new ResourceIdChunk(new Uint8Array(buffer, chunkOffset, chunkSize)); // console.log('resourceIdChunk', this.resourceIdChunk); var chunkType = ''; chunkOffset += chunkSize; var chunks = []; var startTagChunk = null; this.attributes = []; for (; chunkOffset < this.fileSize;) { chunkType = util.uint8ArrayToHex(new Uint8Array(buffer, chunkOffset + 4 * 0, 4)); chunkSize = util.uint8ArrayToInt(new Uint8Array(buffer, chunkOffset + 4 * 1, 4)); if (chunkSize <= 0) { break; } if (chunkType === AndroidManifest.CHUNK_TYPE_START_NAMESPACE) { chunks.push(new StartNamespaceChunk(new Uint8Array(buffer, chunkOffset, chunkSize))); } else if (chunkType === AndroidManifest.CHUNK_TYPE_END_NAMESPACE) { chunks.push(new EndNamespaceChunk(new Uint8Array(buffer, chunkOffset, chunkSize))); } else if (chunkType === AndroidManifest.CHUNK_TYPE_START_TAG) { startTagChunk = new StartTagChunk(new Uint8Array(buffer, chunkOffset, chunkSize)); chunks.push(startTagChunk); (_a = this.attributes).push.apply(_a, startTagChunk.attributes); if (this.stringChunk.stringPool[startTagChunk.name] === 'application') { var attribute = startTagChunk.attributes.find(function (e) { return _this.stringChunk.stringPool[e.name] === 'label'; }); // console.log('atrribute', attribute) this.label = attribute; } } else if (chunkType === AndroidManifest.CHUNK_TYPE_END_TAG) { chunks.push(new EndTagChunk(new Uint8Array(buffer, chunkOffset, chunkSize))); } else if (chunkType === AndroidManifest.CHUNK_TYPE_TEXT) { chunks.push(new TextChunk(new Uint8Array(buffer, chunkOffset, chunkSize))); } // next loop chunkOffset += chunkSize; } this.xmlContentChunk = new XmlContentChunk(); this.xmlContentChunk.chunks = chunks; // console.log(this); } AndroidManifest.prototype.getStringValue = function (index) { return this.stringChunk.stringPool[index]; }; AndroidManifest.prototype.getTagAttribute = function (name) { var _this = this; return this.attributes.find(function (e) { return _this.stringChunk.stringPool[e.name] === name && e.valueString > 0; }); }; AndroidManifest.prototype.getTagAttributeValue = function (name) { var atrribute = this.getTagAttribute(name); return atrribute ? this.stringChunk.stringPool[atrribute.valueString] : ''; }; AndroidManifest.prototype.getLabelAttribute = function () { return this.label; }; AndroidManifest.MAGIC_NUMBER = '00080003'; AndroidManifest.CHUNK_TYPE_STRING = '001c0001'; AndroidManifest.CHUNK_TYPE_RESOURCE_ID = '00080180'; AndroidManifest.CHUNK_TYPE_START_NAMESPACE = '00100100'; AndroidManifest.CHUNK_TYPE_END_NAMESPACE = '00100101'; AndroidManifest.CHUNK_TYPE_START_TAG = '00100102'; AndroidManifest.CHUNK_TYPE_END_TAG = '00100103'; AndroidManifest.CHUNK_TYPE_TEXT = '00100104'; return AndroidManifest; }()); export { AndroidManifest }; var Chunk = /** @class */ (function () { function Chunk() { } return Chunk; }()); var StringChunk = /** @class */ (function () { function StringChunk(array) { // super(); this.chunkType = util.uint8ArrayToHex(array.subarray(4 * 0, 4 * 1)); this.chunkSize = util.uint8ArrayToInt(array.subarray(4 * 1, 4 * 2)); this.stringCount = util.uint8ArrayToInt(array.subarray(4 * 2, 4 * 3)); this.styleCount = util.uint8ArrayToInt(array.subarray(4 * 3, 4 * 4)); this.flags = util.uint8ArrayToInt(array.subarray(4 * 4, 4 * 5)); this.stringPoolOffset = util.uint8ArrayToInt(array.subarray(4 * 5, 4 * 6)); this.stylePoolOffset = util.uint8ArrayToInt(array.subarray(4 * 6, 4 * 7)); var utf8 = (this.flags & StringChunk.UTF8_FLAG) != 0; // console.log('flags', this.flags, 'utf8', utf8); // stringOffsets this.stringOffsets = []; var offset = 0; for (var i = 0; i < this.stringCount; i++) { offset = util.uint8ArrayToInt(array.subarray(4 * (7 + i), 4 * (8 + i))); this.stringOffsets.push(offset); } // styleOffsets this.styleOffsets = []; // TODO // stringPool this.stringPool = []; var str = ''; var length = 0; // offset = this.stringPoolOffset; for (var i = 0; i < this.stringCount; i++) { offset = this.stringPoolOffset + this.stringOffsets[i]; if (utf8) { length = array[offset + 1] & 0x7F; // 头2位的最后1个字节表示字符串长度 } else { length = util.uint8ArrayToShort(array.subarray(offset, offset + 2)) * 2; // 头2位表示字符串长度,并且一个字符占2个字节 } str = util.uint8ArrayToStr(array.subarray(offset + 2, offset + 2 + length), utf8); // console.log('index=',i,'length=',length,'str=',str); this.stringPool.push(str); // offset += length + 4; } // stylePool this.stylePool = []; // TODO } StringChunk.UTF8_FLAG = 1 << 8; return StringChunk; }()); var ResourceIdChunk = /** @class */ (function () { function ResourceIdChunk(array) { // super(); this.chunkType = util.uint8ArrayToHex(array.subarray(4 * 0, 4 * 1)); this.chunkSize = util.uint8ArrayToInt(array.subarray(4 * 1, 4 * 2)); // resourceIds this.resourceIds = []; var offset = 0; var id = 0; var size = this.chunkSize / 4 - 2; for (var i = 0; i < size; i++) { offset = 4 * 2 + 4 * i; id = util.uint8ArrayToInt(array.subarray(offset, offset + 4)); // console.log('index=',i,'id=',id); this.resourceIds.push(id); } } return ResourceIdChunk; }()); var XmlContentChunk = /** @class */ (function () { function XmlContentChunk() { } return XmlContentChunk; }()); var StartNamespaceChunk = /** @class */ (function () { function StartNamespaceChunk(array) { // super(); this.chunkType = util.uint8ArrayToHex(array.subarray(4 * 0, 4 * 1)); this.chunkSize = util.uint8ArrayToInt(array.subarray(4 * 1, 4 * 2)); this.lineNumber = util.uint8ArrayToInt(array.subarray(4 * 2, 4 * 3)); this.unknown = util.uint8ArrayToHex(array.subarray(4 * 3, 4 * 4)); this.prefix = util.uint8ArrayToInt(array.subarray(4 * 4, 4 * 5)); this.uri = util.uint8ArrayToInt(array.subarray(4 * 5, 4 * 6)); } return StartNamespaceChunk; }()); var EndNamespaceChunk = /** @class */ (function () { function EndNamespaceChunk(array) { // super(); this.chunkType = util.uint8ArrayToHex(array.subarray(4 * 0, 4 * 1)); this.chunkSize = util.uint8ArrayToInt(array.subarray(4 * 1, 4 * 2)); this.lineNumber = util.uint8ArrayToInt(array.subarray(4 * 2, 4 * 3)); this.unknown = util.uint8ArrayToHex(array.subarray(4 * 3, 4 * 4)); this.prefix = util.uint8ArrayToInt(array.subarray(4 * 4, 4 * 5)); this.uri = util.uint8ArrayToInt(array.subarray(4 * 5, 4 * 6)); } return EndNamespaceChunk; }()); var StartTagChunk = /** @class */ (function () { function StartTagChunk(array) { // super(); this.chunkType = util.uint8ArrayToHex(array.subarray(4 * 0, 4 * 1)); this.chunkSize = util.uint8ArrayToInt(array.subarray(4 * 1, 4 * 2)); this.lineNumber = util.uint8ArrayToInt(array.subarray(4 * 2, 4 * 3)); this.unknown = util.uint8ArrayToHex(array.subarray(4 * 3, 4 * 4)); this.namespaceUri = util.uint8ArrayToInt(array.subarray(4 * 4, 4 * 5)); this.name = util.uint8ArrayToInt(array.subarray(4 * 5, 4 * 6)); this.flags = util.uint8ArrayToHex(array.subarray(4 * 6, 4 * 7)); this.attributeCount = util.uint8ArrayToInt(array.subarray(4 * 7, 4 * 8)); this.classAtrribute = util.uint8ArrayToHex(array.subarray(4 * 8, 4 * 9)); // atrributes this.attributes = []; var offset = 0; for (var i = 0; i < this.attributeCount; i++) { offset = 4 * 9 + 4 * 5 * i; this.attributes.push(new TagAttribute(array.subarray(offset + 4 * 0, offset + 4 * 5))); // console.log('index=',i,'atrribute=',this.atrributes[i]); } } return StartTagChunk; }()); var EndTagChunk = /** @class */ (function () { function EndTagChunk(array) { // super(); this.chunkType = util.uint8ArrayToHex(array.subarray(4 * 0, 4 * 1)); this.chunkSize = util.uint8ArrayToInt(array.subarray(4 * 1, 4 * 2)); this.lineNumber = util.uint8ArrayToInt(array.subarray(4 * 2, 4 * 3)); this.unknown = util.uint8ArrayToHex(array.subarray(4 * 3, 4 * 4)); this.namespaceUri = util.uint8ArrayToInt(array.subarray(4 * 4, 4 * 5)); this.name = util.uint8ArrayToInt(array.subarray(4 * 5, 4 * 6)); } return EndTagChunk; }()); var TextChunk = /** @class */ (function () { function TextChunk(array) { // super(); this.chunkType = util.uint8ArrayToHex(array.subarray(4 * 0, 4 * 1)); this.chunkSize = util.uint8ArrayToInt(array.subarray(4 * 1, 4 * 2)); this.lineNumber = util.uint8ArrayToInt(array.subarray(4 * 2, 4 * 3)); this.unknown1 = util.uint8ArrayToHex(array.subarray(4 * 3, 4 * 4)); this.name = util.uint8ArrayToInt(array.subarray(4 * 4, 4 * 5)); this.unknown2 = util.uint8ArrayToHex(array.subarray(4 * 5, 4 * 6)); this.unknown3 = util.uint8ArrayToHex(array.subarray(4 * 6, 4 * 7)); } return TextChunk; }()); var TagAttribute = /** @class */ (function () { function TagAttribute(array) { this.namespaceUri = util.uint8ArrayToInt(array.subarray(4 * 0, 4 * 1)); this.name = util.uint8ArrayToInt(array.subarray(4 * 1, 4 * 2)); this.valueString = util.uint8ArrayToInt(array.subarray(4 * 2, 4 * 3)); this.type = util.uint8ArrayToInt(array.subarray(4 * 3, 4 * 4)) >> 24; // 在获取到type值的时候需要右移24位 this.data = util.uint8ArrayToInt(array.subarray(4 * 4, 4 * 5)); } TagAttribute.ATTR_REFERENCE = 1; TagAttribute.ATTR_ATTRIBUTE = 2; TagAttribute.ATTR_STRING = 3; return TagAttribute; }()); export { TagAttribute }; //# sourceMappingURL=AndroidManifest.js.map