首页
社区
课程
招聘
[分享]libjiagu.so 解密,还原
发表于: 2021-4-14 15:22 22320

[分享]libjiagu.so 解密,还原

2021-4-14 15:22
22320

ELF 部分的解密流程

依次解密被抽调的数据和SO

public static jiagu decode_jiagu(byte[] bmp, byte[] mips){

}

修复方法。直接写回去就好了。
public int save(String out){

// long symtab_address = 0, stratb_address = 0;
for(int i = 0; i < size; i++){
Elf32_Dyn dyn = Bytes2Dyn( memcpy(this.elf, dyn_address + i * SIZEOF_Elf32_Dyn , SIZEOF_Elf32_Dyn) );
if(dyn.d_tag == DT_PLTREL){
if(dyn.d_un.d_val != DT_REL){
System.out.println("DT_PLTREL 异常");
err = 2;
break;
}
}else if(dyn.d_tag == DT_JMPREL){
plt_rel = dyn.d_un.d_ptr;
}else if(dyn.d_tag == DT_PLTRELSZ){
plt_rel_count = dyn.d_un.d_val / SIZEOF_Elf32_Rel;

// }else if(dyn.d_tag == DT_SYMTAB){
// symtab_address = dyn.d_un.d_ptr;
// }else if(dyn.d_tag == DT_STRTAB ){
// stratb_address = dyn.d_un.d_ptr;
}
}
if( rel != 0 && rel_count != 0 ){
size = (int) (rel_count SIZEOF_Elf32_Rel);
if( size > this.rel.length )
size = this.rel.length;
System.arraycopy(this.rel, 0, this.elf, (int)rel, size);
} else {
err = 3;
}
if( plt_rel != 0 && plt_rel_count != 0 ){
size = (int) (plt_rel_count
SIZEOF_Elf32_Rel);
if( size > this.plt_rel.length )
size = this.plt_rel.length;
System.arraycopy(this.plt_rel, 0, this.elf, (int)plt_rel, size);

DEX解密:
classes.dex 加固后的结构: 360的dex + 热修复信息 + 原APP的dex
1.读取360的dex大小,获取 热修复信息 偏移,大小,每个字节^ 0x52解密出信息

热修复信息的地址,大小调用makekey->_Z9arm_a_2PcjS_Rii->_Z9arm_a_0v->_Z10__fun_a_18Pcj 计算2组KEY。
翻译出来的代码如下
图片描述

public static Object[] makekey(byte[] fix, long xor){

}
3.依次读取每个DEX的数据,详细结构: dexindex+next+data1size+data1+data2
解密流程:

用makekey计算出来的rc4key 先解密,然后 LZMA:24解压,在把前0x70个字节和makeykey的第二个KEY^最后和dex_data2合并就得到完整的dex

其余的代码很好逆,菜鸟代码写的比较挫就不献丑了。

jiagu jg = new jiagu();
byte[] key = decode_bmp(bmp);
if( key != null ){
    byte[] zip = decode_mips(mips, key);
    byte[] md = new byte[zip.length -4];
    System.arraycopy(zip, 4, md, 0, md.length);
    byte[] uncompress = unjzlib(md);
    if( uncompress == null )
        return null;
 
    int off = 1;
    jg.Phdr = elf_decode(uncompress, off);
    off += jg.Phdr.length + 4;
 
    jg.plt_rel = elf_decode(uncompress, off);
    off += jg.plt_rel.length + 4;
 
    jg.rel = elf_decode(uncompress, off);
    off += jg.rel.length + 4;
 
    jg.Dyn = elf_decode(uncompress, off);
 
    int pElf = off + jg.Dyn.length + 4;
    jg.elf = new byte[ uncompress.length - pElf ];
    System.arraycopy(uncompress, pElf, jg.elf, 0, uncompress.length - pElf);
 
}
return jg;
jiagu jg = new jiagu();
byte[] key = decode_bmp(bmp);
if( key != null ){
    byte[] zip = decode_mips(mips, key);
    byte[] md = new byte[zip.length -4];
    System.arraycopy(zip, 4, md, 0, md.length);
    byte[] uncompress = unjzlib(md);
    if( uncompress == null )
        return null;
 
    int off = 1;
    jg.Phdr = elf_decode(uncompress, off);
    off += jg.Phdr.length + 4;
 
    jg.plt_rel = elf_decode(uncompress, off);
    off += jg.plt_rel.length + 4;
 
    jg.rel = elf_decode(uncompress, off);
    off += jg.rel.length + 4;
 
    jg.Dyn = elf_decode(uncompress, off);
 
    int pElf = off + jg.Dyn.length + 4;
    jg.elf = new byte[ uncompress.length - pElf ];
    System.arraycopy(uncompress, pElf, jg.elf, 0, uncompress.length - pElf);
 
}
return jg;
int err = 0;
int size = this.Phdr.length / SIZEOF_Elf32_Phdr;   
long dyn_address = 0, dyn_size = 0;
for(int i = 0; i < size; i++){
    // Type           Offset   VirtAddr   PhysAddr   FileSiz    MemSiz     Flg Align
    // PHDR           0x000034 0x00000034 0x00000034 0x00000100 0x00000100 R   0x4
    // DYNAMIC        0x031BFC 0x00032BFC 0x00032BFC 0x00000108 0x00000108 RW  0x4   
    Elf32_Phdr p = Bytes2Phdr( memcpy(this.Phdr, i * SIZEOF_Elf32_Phdr, SIZEOF_Elf32_Phdr) );
    if( p.p_type == PT_PHDR ){
        System.arraycopy(this.Phdr, 0, this.elf, (int)p.p_offset, this.Phdr.length);
        continue;
    }
    if( p.p_type == PT_DYNAMIC ){
        dyn_address = p.p_offset;
        dyn_size = p.p_filesz / SIZEOF_Elf32_Dyn;
        System.arraycopy(this.Dyn, 0, this.elf, (int)p.p_offset, this.Dyn.length);
        continue;
    }
}
 
if( dyn_address == 0 || dyn_size == 0 ){
    System.out.println("Elf32_Dyn 异常");
    return 1;
}
 
size = this.Dyn.length / SIZEOF_Elf32_Dyn;
long rel = 0, rel_count = 0;
long plt_rel = 0, plt_rel_count = 0;
int err = 0;
int size = this.Phdr.length / SIZEOF_Elf32_Phdr;   
long dyn_address = 0, dyn_size = 0;
for(int i = 0; i < size; i++){
    // Type           Offset   VirtAddr   PhysAddr   FileSiz    MemSiz     Flg Align
    // PHDR           0x000034 0x00000034 0x00000034 0x00000100 0x00000100 R   0x4
    // DYNAMIC        0x031BFC 0x00032BFC 0x00032BFC 0x00000108 0x00000108 RW  0x4   
    Elf32_Phdr p = Bytes2Phdr( memcpy(this.Phdr, i * SIZEOF_Elf32_Phdr, SIZEOF_Elf32_Phdr) );
    if( p.p_type == PT_PHDR ){
        System.arraycopy(this.Phdr, 0, this.elf, (int)p.p_offset, this.Phdr.length);
        continue;
    }
    if( p.p_type == PT_DYNAMIC ){
        dyn_address = p.p_offset;
        dyn_size = p.p_filesz / SIZEOF_Elf32_Dyn;
        System.arraycopy(this.Dyn, 0, this.elf, (int)p.p_offset, this.Dyn.length);
        continue;
    }
}
 
if( dyn_address == 0 || dyn_size == 0 ){
    System.out.println("Elf32_Dyn 异常");
    return 1;
}
 
size = this.Dyn.length / SIZEOF_Elf32_Dyn;
long rel = 0, rel_count = 0;
long plt_rel = 0, plt_rel_count = 0;
}else if(dyn.d_tag == DT_REL){
    rel = dyn.d_un.d_ptr;
}else if(dyn.d_tag == DT_RELSZ){
    rel_count = dyn.d_un.d_val / SIZEOF_Elf32_Rel;
}else if(dyn.d_tag == DT_REL){
    rel = dyn.d_un.d_ptr;
}else if(dyn.d_tag == DT_RELSZ){
    rel_count = dyn.d_un.d_val / SIZEOF_Elf32_Rel;
    } else {
        err = 4;
    }
 
 
    this.pshdr = ByteToDword(this.elf, 32);
    long e_shstrndx = ByteToWord(this.elf, 50);
    // 主动添加 .dynamic ,,否则readelf报错
    // [ 2] .dynsym           DYNSYM          00000148 000148 001b90 10   3   1  4
    long str = shstrtab();
    Elf32_Shdr es = new Elf32_Shdr();
    // [20] .dynamic          DYNAMIC         00032bfc 031bfc 000108 08  WA  3   0  4
    es.sh_name = sh_name(str, ".dynamic");
    es.sh_type = SHT_DYNAMIC;
    es.sh_addr = dyn_address;
    es.sh_offset = dyn_address;
    es.sh_size = dyn_size * SIZEOF_Elf32_Dyn;
    es.sh_entsize = SIZEOF_Elf32_Dyn;
    es.sh_flags = SHF_ALLOC | SHF_WRITE;
    es.sh_link = 3;
    es.sh_info = 0;
    es.sh_addralign = 4;
    System.arraycopy(Shdr2Bytes(es), 0, this.elf, (int)pshdr+ SIZEOF_Elf32_Shdr * 2, SIZEOF_Elf32_Shdr);
 
    // [32] .shstrtab         STRTAB          00000000 09c30f 000125 00      0   0  1
    es.sh_name = sh_name(str, ".shstrtab");
    es.sh_type = SHT_STRTAB;
    es.sh_addr = 0;
    es.sh_offset = shstrtab();
    es.sh_size = this.pshdr - str;
    es.sh_entsize = 0;
    es.sh_flags = 0;
    es.sh_link = 0;
    es.sh_info = 0;
    es.sh_addralign = 1;
    System.arraycopy(Shdr2Bytes(es), 0, this.elf, (int)(pshdr+ SIZEOF_Elf32_Shdr * e_shstrndx), SIZEOF_Elf32_Shdr);
 
    FileOutputStream fos = null;
    try {
        File file = new File(out);
        fos = new FileOutputStream(file);
        fos.write( this.elf );
        fos.close();
 
    } catch (Exception e) {
        err = 5;
    }
    return err;
}
    } else {
        err = 4;
    }
 
 
    this.pshdr = ByteToDword(this.elf, 32);
    long e_shstrndx = ByteToWord(this.elf, 50);
    // 主动添加 .dynamic ,,否则readelf报错
    // [ 2] .dynsym           DYNSYM          00000148 000148 001b90 10   3   1  4
    long str = shstrtab();
    Elf32_Shdr es = new Elf32_Shdr();
    // [20] .dynamic          DYNAMIC         00032bfc 031bfc 000108 08  WA  3   0  4
    es.sh_name = sh_name(str, ".dynamic");
    es.sh_type = SHT_DYNAMIC;
    es.sh_addr = dyn_address;
    es.sh_offset = dyn_address;
    es.sh_size = dyn_size * SIZEOF_Elf32_Dyn;
    es.sh_entsize = SIZEOF_Elf32_Dyn;
    es.sh_flags = SHF_ALLOC | SHF_WRITE;
    es.sh_link = 3;
    es.sh_info = 0;
    es.sh_addralign = 4;
    System.arraycopy(Shdr2Bytes(es), 0, this.elf, (int)pshdr+ SIZEOF_Elf32_Shdr * 2, SIZEOF_Elf32_Shdr);
 
    // [32] .shstrtab         STRTAB          00000000 09c30f 000125 00      0   0  1
    es.sh_name = sh_name(str, ".shstrtab");
    es.sh_type = SHT_STRTAB;
    es.sh_addr = 0;
    es.sh_offset = shstrtab();
    es.sh_size = this.pshdr - str;
    es.sh_entsize = 0;

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (14)
雪    币: 5308
活跃值: (5634)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
mark
2021-4-14 17:25
0
雪    币: 5201
活跃值: (4902)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
D-t
3
mark
2021-4-14 21:35
0
雪    币: 2118
活跃值: (1404)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
mark
2021-4-15 12:52
0
雪    币: 783
活跃值: (212)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
“很好逆”
2021-4-15 13:22
0
雪    币: 236
活跃值: (391)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
支持一下
2021-4-15 18:08
0
雪    币: 2189
活跃值: (576)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
康康
2021-4-16 12:10
0
雪    币: 334
活跃值: (392)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
康康
2021-4-17 00:40
0
雪    币: 104
活跃值: (73)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
Mark
2021-4-29 19:59
0
雪    币: 402
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
大佬就是大佬
2021-4-29 21:40
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
了解下
2021-5-8 09:40
0
雪    币: 343
活跃值: (906)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
12
好像不能用了
2021-7-6 16:28
1
雪    币: 794
活跃值: (663)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
看不懂
2021-8-6 14:35
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
mark
2021-8-26 19:47
0
雪    币: 2415
活跃值: (1246)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
大佬厉害哟哟哟
2022-2-9 14:07
0
游客
登录 | 注册 方可回帖
返回