【逆向分析】静态分析_Navtive_ISCC_2017
分析
Java层jadx反编译

目标函数是native函数,所以这里需要静态分析native
直接搜目标函数

开始读汇编
; ================ B E G I N N I N G O F P R O C E D U R E ================
; Variables:
; var_1C: int32_t, -28
; var_28: int32_t, -40
native_checkFlag:
push {r4, r5, r6, r7, lr}
sub sp, #0x14
adds r6, r0, #0x0
adds r0, r3, #0x0 ; argument "__size" for method malloc@PLT
adds r5, r3, #0x0
str r2, [sp, #0x28 + var_1C] (r2存下来)
blx malloc@PLT ; malloc (创建空间)
ldr r2, [r6] (r2 = r6)
movs r3, #0xc8 (r3 = 200)
str r0, [sp, #0x28 + var_28] (r0 存下来)
lsls r3, r3, #0x2 (r3 = r3 左移两位)
ldr r4, [r2, r3] (r4 = r2 + r3 )
ldr r1, [sp, #0x28 + var_1C]
adds r3, r5, #0x0
movs r2, #0x0
adds r7, r0, #0x0
adds r0, r6, #0x0
blx r4
adds r4, r5, #0x1
adds r0, r4, #0x0 ; argument "__size" for method malloc@PLT
blx malloc@PLT ; malloc
movs r1, #0x0 ; argument "__c" for method memset@PLT
adds r6, r0, #0x0
adds r2, r4, #0x0 ; argument "__n" for method memset@PLT
blx memset@PLT ; memset
adds r2, r5, #0x0 ; argument "__n" for method memcpy@PLT
adds r0, r6, #0x0 ; argument "__dest" for method memcpy@PLT
adds r1, r7, #0x0 ; argument "__src" for method memcpy@PLT
blx memcpy@PLT ; memcpy
lsrs r0, r5, #0x1f
adds r0, r0, r5
asrs r0, r0, #0x1
movs r2, #0x0
str r0, [sp, #0x28 + var_1C]
adds r3, r2, #0x0 (r3 = r2 + 0)
b loc_d5a
loc_d5a:
ldr r1, [sp, #0x28 + var_1C] ; CODE XREF=native_checkFlag+78
subs r2, #0x1 (r2 = r2 -1 ,这里就是r3 一开始和 r2 相同然后一个+1 一个 -1)
cmp r3, r1 (r3 和 r1比较)
blt loc_d4c (小于就跳loc_d4c)
loc_d4c:
ldrb r4, [r6, r3] ; CODE XREF=native_checkFlag+100 (r4 = r6 + r3)
adds r1, r6, r5 ( r1 = r6 + r5)
ldrb r0, [r1, r2] (r0 = r1 + r2)
subs r4, #0x5(r4 = r4 - 5)
strb r0, [r6, r3] ( r6+ r3 = r0)
strb r4, [r1, r2] (r1 + r2 = r4 ) (也就是r1 + r2 的值放到了r6 + r3上面,r6 + r3的值-5放到了r1+r2的位置)
adds r3, #0x1 (r3 = r3+1)
ldr r1, =0x15f8 ; 0xd88,0x15f8
movs r3, #0x0
strb r3, [r6, r5]
add r1, pc ; argument "__s2" for method strcmp@PLT, "=0HWYl1SE5UQWFfN?I+PEo.UcshU"
adds r0, r6, #0x0 ; argument "__s1" for method strcmp@PLT
blx strcmp@PLT ; strcmp
adds r4, r0, #0x0
adds r0, r6, #0x0 ; argument "__ptr" for method free@PLT
blx free@PLT ; free
adds r0, r7, #0x0 ; argument "__ptr" for method free@PLT
blx free@PLT ; free
add sp, #0x14
rsbs r0, r4, #0x0
adcs r0, r4
pop {r4, r5, r6, r7, pc}
转成C语言来看看
int native_checkFlag(int arg0, int arg1, int arg2, int arg3) {
r4 = arg3;
r0 = malloc(arg3);(内存分配arg3大小)
r5 = r0;(r5新开辟了一个空间)
(*(*arg0 + 0x320))(arg0, arg2, 0x0, r4, r0);
r0 = malloc(r4 + 0x1);
r6 = r0;(r6新开辟了一个空间)
memset(r0, 0x0, r4 + 0x1);(将新开辟的空间填充字符0x0)
memcpy(r6, r5, r4);(从r5复制东西到r6,也就是r0呗,也就是都变成了0x0,长度是r4和r4+1,可以理解r0,r5,r6都是装满0的空间)
r2 = 0x0;
r1 = r6 + r4;
r0 = SAR(r4 + r4 / 0x80000000, 0x1); (看汇编:asrs r0, r0, #0x1 就是r0 = r0 >> 1 也就是 r0 = r0/2 )
r3 = r2;
do {
r2 = r2 - 0x1; (r2从0开始-1)
if (r3 >= r0) {(此时的r0是原来的一半)
break;
}
lr = *(int8_t *)(r1 + r2);(r6+r4-r3)(r6是起点,r4是终点)
r7 = *(int8_t *)(r6 + r3);(r6+r3)
*(int8_t *)(r6 + r3) = lr;
r3 = r3 + 0x1;(r3从0开始+1)
*(int8_t *)(r1 + r2) = r7 - 0x5;(互换位置,并且后面的换到前面还-5)
} while (true);
*(int8_t *)(r6 + r4) = 0x0; 直到首位碰头
r4 = strcmp(r6, "=0HWYl1SE5UQWFfN?I+PEo.UcshU");(将我们的r6和这个字符串进行比较)
free(r6);
free(r5);
r0 = 0x1 - r4;(
这里来看汇编吧:
rsbs.w r0, r4, #0x1 (逆向减法 r0 = 1 - r4)
00000d80 it lo (如果小于)
00000d82 movslo r0, #0x0 (没懂)
00000d84 pop.w {r2, r3, r4, r5, r6, r7, r8, pc}
)
if (r0 < 0x0) {
asm { movslo r0, #0x0 };
}
return r0;
}
虽然有些细节没明白,大概意思是一个字符串首位互换,并且尾换到首时-5 和指定字符串比较就行,可以逆推回去原始字符串。
import base64
ans = '=0HWYl1SE5UQWFfN?I+PEo.UcshU'
length = len(ans)
flag_suf = []
flag_pre = []
for i in range(length//2):
flag_suf.append(ans[i])
flag_pre.append(chr(ord(ans[(i+1)*(-1)]) + 5))
print(base64.b64decode("".join(flag_pre + flag_suf[::-1])))

flag{ISCCJAVANDKYXX}
文章详细展示了对Java层Native函数的静态分析过程,通过反编译和汇编代码解析,重点讨论了内存分配、字符串处理及位操作等技术,包括malloc、memset、memcpy和strcmp函数的使用,以及如何通过位移和比较操作实现特定的字符串操作。最终,文章给出了一个基于分析结果的解密示例,涉及字符串首位互换和比较的逻辑。

862

被折叠的 条评论
为什么被折叠?



