首先点我下载题目,这道题提供了三个文件,分别为:
a:内存布局文件
b:oatdump的结果文件
c:boot.oat文件
经过对几个文件的初步观察,发现在b文件中找到一个可疑函数oat.sjl.gossip.oat.MainActivity.check(java.lang.String),函数名字可不会乱取,此函数肯定和Flag密切相关,因此需要还原出该方法。可惜,出题者有意抹去了oatdump中的dalvik字节码,不然这道题会简单的多。
我们分段分析汇编代码,首先看下面一段:
0x00371e8c: b099 sub sp, sp, #100
0x00371e8e: 9000 str r0, [sp, #0]
0x00371e90: 9121 str r1, [sp, #132]
0x00371e92: 9222 str r2, [sp, #136]
0x00371e94: f8d9e11c ldr.w lr, [r9, #284] ; pAllocArrayResolved
0x00371e98: 9900 ldr r1, [sp, #0]
0x00371e9a: 2606 movs r6, #6
0x00371e9c: 1c32 mov r2, r6
0x00371e9e: f64e0020 movw r0, #59424
0x00371ea2: f2c7005b movt r0, #28763
0x00371ea6: 47f0 blx lr
extern "C" mirror::Array* artAllocArrayFromCode##suffix##suffix2(uint32_t type_idx, mirror::ArtMethod* method, int32_t component_count, Thread* self, StackReference<mirror::ArtMethod>* sp)
0x00371ea8: f8d9e190 ldr.w lr, [r9, #400] ; pHandleFillArrayData
0x00371eac: 4682 mov r10, r0
0x00371eae: 4650 mov r0, r10
0x00371eb0: f20f6144 adr r1, +1604 (0x003724f8)
0x00371eb4: 47f0 blx lr
struct PACKED(4) ArrayDataPayload {
const uint16_t ident; // 标志
const uint16_t element_width; // 每一个元素的大小
const uint32_t element_count; // 元素的个数
const uint8_t data[]; //指向真正的数据
...
};
0x003724f8: 0300 lsls r0, r0, #12
0x003724fa: 0001 lsls r1, r0, #0
0x003724fc: 0006 lsls r6, r0, #0
0x003724fe: 0000 lsls r0, r0, #0
0x00372500: 4578 cmp r0, pc
0x00372502: 3278 adds r2, #120
0x00372504: 3757 adds r7, #87
0x00372506: 0000 lsls r0, r0, #0
// 每行的注释指的的是该数组对象的存放位置
byte[] s1 = new byte[]{0x78, 0x45, 0x78, 0x32, 0x57, 0x37}; // r10
byte[] s2 = new byte[]{0x22, 0x29, 0x44, 0x55, 0x60, 0x33}; // r7
byte[] s3 = new byte[]{0x17, 0x94, 0x35, 0x03, 0x90}; // [sp, #56]
byte[] s4 = new byte[]{0x45, 0x64, 0x5f, 0x41,0x52, 0x54, 0x7d}; // [sp, #60]
byte[] s5 = new byte[]{0x58, 0x75, 0x1b, 0xf0, 0x0f, 0x4c}; // r11
byte[] s6 = new byte[]{0x69, 0x0c, 0x1b, 0xbe, 0xf2, 0x49}; //[sp, #52]
0x00371f64: 42b5 cmp r5, r6
0x00371f66: f2808034 bge.w +104 (0x00371fd2) // 这里就是一个for循环
0x00371f6a: 68ba ldr r2, [r7, #8]
0x00371f6c: f117030c adds r3, r7, #12
0x00371f70: 4295 cmp r5, r2
0x00371f72: f0808248 bcs.w +1168 (0x00372406) // 对s2数组进行边界判断
0x00371f76: 575e ldrsb r6, [r3, r5] // r6 = s2[r5],也就是取出s2数组的元素
0x00371f78: 68b8 ldr r0, [r7, #8]
0x00371f7a: f1160636 adds r6, r6, #54 // r6 = s2[r5] + 54
0x00371f7e: f3460607 UNKNOWN 52 // SBFX.W R6, R6, #0, #8
0x00371f82: f1170c0c adds r12, r7, #12
0x00371f86: 4285 cmp r5, r0
0x00371f88: f0808242 bcs.w +1156 (0x00372410) // 对s2数组进行边界判断
0x00371f8c: f80c6005 strb r6, [r12, r5]
0x00371f90: 68b9 ldr r1, [r7, #8]
0x00371f92: f117020c adds r2, r7, #12
0x00371f96: 428d cmp r5, r1
0x00371f98: f080823f bcs.w +1150 (0x0037241a) // 对s2数组进行边界判断
0x00371f9c: 5756 ldrsb r6, [r2, r5]
0x00371f9e: 9b0d ldr r3, [sp, #52] // 取出s6数组的mirror::Array对象的首地址
0x00371fa0: f8d3c008 ldr.w r12, [r3, #8]
0x00371fa4: f113000c adds r0, r3, #12 // 取出s6数组的mirror::Array对象中数据区域的首地址
0x00371fa8: 4565 cmp r5, r12
0x00371faa: f080823a bcs.w +1140 (0x00372422) // 对s6数组进行边界判断
0x00371fae: f9108005 UNKNOWN 17 // ldrsb.w r8, [r0, r5],也就是r8 = s6[r5]
0x00371fb2: 68ba ldr r2, [r7, #8]
0x00371fb4: ea860608 eor.w r6, r6, r8 // r6 = (s2[r5] + 54) ^ s6[r5]
0x00371fb8: f3460607 UNKNOWN 52 // SBFX.W R6, R6, #0, #8
0x00371fbc: f117010c adds r1, r7, #12
0x00371fc0: 4295 cmp r5, r2
0x00371fc2: f0808233 bcs.w +1126 (0x0037242c) // 对s2数组进行边界判断
0x00371fc6: 554e strb r6, [r1, r5] // s2[r5] = (s2[r5] + 54) ^ s6[r5]
0x00371fc8: 1c6d adds r5, r5, #1 // r5 += 1
0x00371fca: 3c01 subs r4, #1
0x00371fcc: f47fafc9 bne.w -110 (0x00371f62) // 循环,这里跳回去
for (int i = 0; i < s2.length; ++i) {
s2[i] = (byte) ((s2[i] + 54) ^ s6[i]);
}
0x00371fd2: 2500 movs r5, #0
0x00371fd4: f8da6008 ldr.w r6, [r10, #8]
0x00371fd8: 42b5 cmp r5, r6
0x00371fda: f2808051 bge.w +162 (0x00372080) // 这里就是一个for循环
0x00371fde: f8da3008 ldr.w r3, [r10, #8]
0x00371fe2: f11a0c0c adds r12, r10, #12
0x00371fe6: 429d cmp r5, r3
0x00371fe8: f0808229 bcs.w +1106 (0x0037243e) // 对s1数组进行边界判断
0x00371fec: f91c6005 UNKNOWN 17 // ldrsb.w r6, [r12, r5],也就是r6 = s1[r5]
0x00371ff0: f04f0857 mov.w r8, #87
0x00371ff4: 4546 cmp r6, r8 // s1[r5]和87比较
0x00371ff6: f0408009 bne.w +18 (0x0037200c) // 如果不等则跳向0x0037200c,等于则跳向0x00371ffa
0x00371ffa: f8da1008 ldr.w r1, [r10, #8]
0x00371ffe: 2669 movs r6, #105 // r6 = 105
0x00372000: f11a000c adds r0, r10, #12
0x00372004: 428d cmp r5, r1
0x00372006: f080821f bcs.w +1086 (0x00372448) // 对s1数组进行边界判断
0x0037200a: 5546 strb r6, [r0, r5] // s1[r5] = 105
0x0037200c: f8da2008 ldr.w r2, [r10, #8]
0x00372010: f11a030c adds r3, r10, #12
0x00372014: 4295 cmp r5, r2
0x00372016: f080821b bcs.w +1078 (0x00372450) // 对s1数组进行边界判断
0x0037201a: 575e ldrsb r6, [r3, r5] // r6 = s1[r5]
0x0037201c: f04f0832 mov.w r8, #50
0x00372020: 4546 cmp r6, r8 // s1[r5]和50比较
0x00372022: f040800b bne.w +22 (0x0037203c) // 如果不等则跳向0x0037203c,等于则跳向0x00372026
0x00372026: f8da0008 ldr.w r0, [r10, #8]
0x0037202a: f06f067b mvn r6, #123 // r6 = ~123
0x0037202e: f11a0c0c adds r12, r10, #12
0x00372032: 4285 cmp r5, r0
0x00372034: f0808211 bcs.w +1058 (0x0037245a) // 对s1数组进行边界判断
0x00372038: f80c6005 strb r6, [r12, r5] // s1[r5] = ~123
0x0037203c: f8da1008 ldr.w r1, [r10, #8]
0x00372040: f11a020c adds r2, r10, #12
0x00372044: 428d cmp r5, r1
0x00372046: f080820d bcs.w +1050 (0x00372464) // 对s1数组进行边界判断
0x0037204a: 5756 ldrsb r6, [r2, r5]
0x0037204c: f8db3008 ldr.w r3, [r11, #8]
0x00372050: f11b0c0c adds r12, r11, #12
0x00372054: 429d cmp r5, r3
0x00372056: f0808209 bcs.w +1042 (0x0037246c) // 对s5数组进行边界判断
0x0037205a: f91c8005 UNKNOWN 17 // ldrsb.w r8, [r12, r5],也就是r8 = s5[r5]
0x0037205e: f8da1008 ldr.w r1, [r10, #8]
0x00372062: ea860608 eor.w r6, r6, r8 // r6 = s1[r5] ^ s5[r5]
0x00372066: f3460607 UNKNOWN 52 // SBFX.W R6, R6, #0, #8
0x0037206a: f11a000c adds r0, r10, #12
0x0037206e: 428d cmp r5, r1
0x00372070: f0808201 bcs.w +1026 (0x00372476) // 对s1数组进行边界判断
0x00372074: 5546 strb r6, [r0, r5] // s1[r5] = s1[r5] ^ s5[r5]
0x00372076: 1c6d adds r5, r5, #1
0x00372078: 3c01 subs r4, #1
0x0037207a: f47fafab bne.w -170 (0x00371fd4) // 循环,这里跳回去
for (int i = 0; i < s1.length; i++) {
if (s1[i] == 87) {
s1[i] = 105;
}
if (s1[i] == 50) {
s1[i] = ~(123);
}
s1[i] = (byte) (s1[i] ^ s5[i]);
}
0x00372080: f8da6008 ldr.w r6, [r10, #8] // r6 = s1.length
0x00372084: f8d9e11c ldr.w lr, [r9, #284] ; pAllocArrayResolved
0x00372088: f8d78008 ldr.w r8, [r7, #8] // r8 = s2.length
0x0037208c: 9900 ldr r1, [sp, #0]
0x0037208e: eb160608 adds.w r6, r6, r8 // r6 = s1.length + s2.length
0x00372092: 1c32 mov r2, r6
0x00372094: f64e0020 movw r0, #59424
0x00372098: f2c7005b movt r0, #28763
0x0037209c: 47f0 blx lr
byte[] d1 = new byte[s1.length + s2.length]; // [sp, #40]
0x0037209e: f8da2008 ldr.w r2, [r10, #8]
0x003720a2: 900a str r0, [sp, #40]
0x003720a4: 2600 movs r6, #0
0x003720a6: 9800 ldr r0, [sp, #0]
0x003720a8: f04f0800 mov.w r8, #0
0x003720ac: 9216 str r2, [sp, #88]
0x003720ae: 9a16 ldr r2, [sp, #88]
0x003720b0: f8cd8010 str.w r8, [sp, #16]
0x003720b4: 68c0 ldr r0, [r0, #12]
0x003720b6: f24f0cd8 movw r12, #61656
0x003720ba: f850000c ldr.w r0, [r0, r12]
0x003720be: 9205 str r2, [sp, #20]
0x003720c0: f8d0e028 ldr.w lr, [r0, #40]
0x003720c4: 9b0a ldr r3, [sp, #40] // r3为d1数组对象
0x003720c6: 4651 mov r1, r10 // r1为s1数组对象
0x003720c8: 1c32 mov r2, r6 // r2 = 0
0x003720ca: 47f0 blx lr // 这是执行什么函数?
3: java.lang.Object[] android.support.v4.content.FileProvider.copyOf(java.lang.Object[], int) (dex_method_idx=2961)
DEX CODE:
0x0000: const/4 v1, #+0
0x0001: new-array v0, v3, java.lang.Object[] // type@2035
0x0003: invoke-static {v2, v1, v0, v1, v3}, void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int) // method@15411
...
0x00216b14: 1c05 mov r5, r0
0x00216b16: 1c38 mov r0, r7
0x00216b18: 68c0 ldr r0, [r0, #12]
0x00216b1a: 2200 movs r2, #0
0x00216b1c: 9204 str r2, [sp, #16]
0x00216b1e: f24f0cd8 movw r12, #61656
0x00216b22: f850000c ldr.w r0, [r0, r12]
0x00216b26: 9605 str r6, [sp, #20]
0x00216b28: f8d0e028 ldr.w lr, [r0, #40]
0x00216b2c: 4641 mov r1, r8
0x00216b2e: 2200 movs r2, #0
0x00216b30: 1c2b mov r3, r5
0x00216b32: 47f0 blx lr
System.arraycopy(s1, 0, d1, 0, s1.length);
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!