首页
社区
课程
招聘
[原创]0ctf 2016 State of the ART writeup
发表于: 2016-3-22 19:44 6431

[原创]0ctf 2016 State of the ART writeup

2016-3-22 19:44
6431

首先点我下载题目,这道题提供了三个文件,分别为:

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);

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 3
支持
分享
最新回复 (2)
雪    币: 53
活跃值: (106)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
赞一个,出题思路和解题思路都很棒!
2016-3-22 21:57
0
雪    币: 485
活跃值: (78)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
3
666666
2016-3-22 23:36
0
游客
登录 | 注册 方可回帖
返回
//