目录:

0x00APK加固简介与静态脱壳机的编写思路

1.大家都知道Android中的程序反编译比较简单,辛苦开发出一个APK轻易被人反编译了,所以现在就有很多APK加固的第三方平台,比如爱加密和梆梆加固等。

2.一般的加固保护通常能够提供如下保护:加密、防逆向、防篡改、反调试、反窃取等功能,编写静态脱壳机须要信息有加密后的原始DEX数据、解密算法、解密密钥、要想获得这些信息我们首先要解决的问题是过反调试、动态分析解密流程、获取密钥,获得原始DEX数据存放位置、分析解密算法。

0x01壳简单分析

1.整体来看一下加固前APK包和加固后的APK包结构相关变化,如图1所示。

      图1

图1所示加固后的APK增加了librsprotect.so、librsprotect_x86.so、rsprotect.dat文件,发生变化的有AndroidManifest.xml、classes.dex文件。

2.反编译加固后APK,APK中的AndroidManifest.xml文件的入口被修改,如图2所示。

      图2

3.入口类中主要会调用librsprotect.so中的3个函数,如图3所示。

private native void initialize(Context paramContext);

private native Application makeApplication(String paramString);

private native void applicationOnCreate();

      图3

0x02 SO文件脱壳

1.既然主要是调用librsprotect.so中的函数,我们将librsprotect.so放到IDA Pro中分析,发现代码都是乱码 图4所示,说明被加密了。

      图4

2.一般加壳的SO的壳代码都在INIT段或INIT_ARRAY段,我们先看下被加壳以后的SO信息,用readelf -a命令查看,图5所示

      图5

可以看到INIT值为0x2ea91,到 IDA中看看该地址的内容,就是壳的入口了,明显是UPX的加壳,图6所示,有人会问你为什么会知道是UPX的壳,“只是因为在人群中多看了你一眼,再也没能忘掉你容颜!(^_^)”。

      图6

3.尝试用upx -d脱壳,因为这样脱方便、干净、省事、提示图7所示的信息。

      图7

查看UPX源码后发现可能是没有找到UPX!的标志,用16进制工具打开librsprotect.so发现标志被改成了RSP!,将其改成UPX!后再将尝试,出现 图8所示的信息。

      图8

出现这种错误可能是做变形处理了或者是版本不对,通过分析librsprotect.so的壳代码好像没有变形处理,所以决定重新编一个3.92版本的来试试,编译好后脱壳成功,如图9所示。

      图9

将脱壳后的so放到IDA Pro中分析,代码正常,图10所示,SO脱壳完成。

      图10

0x03 反调试分析

1.如何使用IDA调试android的SO模块,网上教程也太多太多了,这里不多说,将脱壳后的librsprotect.so替换掉原始有壳的SO后(也可不用替换没影响,这里只是为了测试)签名安装进行动态分析。

2.通过动态调试该加壳程序,它用到的反调试方法是首先试探性读取/proc/pid/status获取进程状态去判断是否有调试器,如果发现被调试就kill掉本进程,如图11所示

      图11

3.通过读取/proc/net/tcp查看正在运行应用的本地端口号是否有android_server端口,如果有就创建一个反调试线程,如图12所示,每隔几秒检查一次,过反调试就很简单了直接把返回值改成假就成了。

      图12 android_server运行后端口

      图13

0x04解密流程分析

1. 根据算法中的常量值猜测该算法为MD5,如图14所示

      图14

2.获取包名并计算MD5值 图15所示,将该值做为密钥。

com.droider.crackme0201

F2 E8 F0 62 85 17 9C 3C 99 F5 67 9F A6 27 FC 55

      图15

2.打开并读取/data/data/com.droider.crackme0201/files/.rsdata/rsprotect.dat数据,该文件是从APK包中的assets文件夹中拷贝过来的,判断前4字节是"RSFL"是否与so中的相同,不同则退出,rsprotect.dat前0x1000字节存放原始DEX大小与循环解密的次数,每次解密0x1000字节,根据密钥初始化流程发现解密算法为RC4,图16示(也可以看IDB)。

      图16

0x05脱壳机编写

1.通过分析,已经知道了壳的数据、密钥、算法、解密过程, 现在来写脱壳机。

必要步骤如下:

1。解包获得rsprotect.da数据。

2.XML解析获得包名。

3.MD5计算获得密钥。

4.RC4解密rsprotect.dat中的数据。

代码流程:

 #include"stdafx.h"
#include<afxwin.h>
#include<stdio.h>
#include<windows.h>
#include<process.h>
#include<assert.h>
#include<string>
#include<iostream>
#include"CMarkup.h"
#include"md5.h"
#include"rc4.h"
#include<string>
usingnamespacestd;
BOOLGetPackName(char* pathXml, charoutPackName[])
{
CMarkupxml;
boolflag;
CStringpackName;
CStringAppandroidname;
MCD_STRmyapkName;
MCD_STRattribName;
char* strXML = "\\AndroidManifest.xml";
strcat(pathXml,strXML);
flag = xml.Load((MCD_STR)pathXml);
if ( FALSE == flag)
{
printf("获得包名失败...\n");
returnFALSE;
}
flag = xml.FindElem((MCD_STR)"manifest");
//获取包名.........
for(intattribIndex=;;attribIndex++)
{
attribName=xml.GetAttribName(attribIndex);
if (attribName.GetLength()!=) //方法若返回empty string,即表示属性结束,结束循环
{
MCD_STRattribVal = xml.GetAttrib(attribName);//否则读取属性值,以子元素加入dxml
//------判断是否为包名...
packName = attribName.GetString();
if ( == strcmp(packName.GetString(), "package"))
{
myapkName = attribVal;
strcpy(outPackName, attribVal.GetString());
returnTRUE;
}
}
else
break;
}
returnFALSE;
}
voidStrToHex(BYTE *pbDest, BYTE *pbSrc, intnLen)
{
charh1,h2;
BYTEs1,s2;
inti;
for (i=; i<nLen; i++)
{
h1 = pbSrc[*i];
h2 = pbSrc[*i+];
s1 = toupper(h1) - 0x30;
if (s1> )
s1 -= ;
s2 = toupper(h2) - 0x30;
if (s2> )
s2 -= ;
pbDest[i] = s1* + s2;
}
}
int_tmain(intargc, _TCHAR* argv[])
{
charstrAPK[] = {};
charapkd[] = "";
charFileDirectory[] = {};
chardexDirectory[] = {};
charPackName[] = {};
BOOLret = FALSE;
structrc4_staterc4_test;
FILE *fp;
DWORDfileSize = ;
BYTE *ptr = NULL;
DWORDDecOffset = 0X1000;//文件偏移
DWORDDecSize = 0X0;//大小
DWORDindex = ;//循环解密的次数
stringkey;
printf("请输入要脱壳的apk包路径:\n");
scanf("%s",strAPK);
if (NULL == strAPK)
{
printf("路径不能为空!\n");
return -;
}
strcpy(apkd, "java -jar apktool.jar d ");
strcat(apkd, strAPK);
//--------bat解包
CFileapktool("apktool.bat", CFile::modeCreate | CFile::modeReadWrite);
apktool.Write(apkd, strlen(apkd));
apktool.Write("\r\n", strlen("\r\n"));
apktool.Close();
char* cmd1 = "apktool.bat";
STARTUPINFOsi1;
GetStartupInfo(&si1);
si1.dwFlags = STARTF_USESHOWWINDOW;
si1.wShowWindow = SW_HIDE;
PROCESS_INFORMATIONpi1;
CreateProcess(NULL,
(LPSTR)cmd1,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si1,
&pi1);
printf("正在解包apk...\n");
WaitForSingleObject(pi1.hProcess,INFINITE);
DeleteFile("apktool.bat");
printf("解包完成...\n");
//-----判断是否解包成功..........
strncpy(FileDirectory, strAPK, strlen(strAPK)-strlen(".apk"));
DWORDdwFileAtt;
dwFileAtt = GetFileAttributes(FileDirectory);
//判断是否为目录
if( dwFileAtt != FILE_ATTRIBUTE_DIRECTORY)
{
printf("apk解包失败!...\n");
return ;
}
printf("apk解包成功!...\n");
strcpy(dexDirectory, FileDirectory);
//得到包名
ret = GetPackName(FileDirectory,PackName);
if (FALSE == ret)
{
printf("获得包名失败...\n");
return -;
}
//计算MD5值
MD5md5(PackName);
key = md5.md5();
strcat(dexDirectory, "\\assets\\rsprotect.dat");
fp=fopen(dexDirectory, "rb");
if(fp==NULL)
printf("打开文件失败!...");
//求文件大小
fseek(fp, , SEEK_END);
fileSize = ftell(fp);
fseek(fp, , SEEK_SET);
ptr = (BYTE*)malloc(fileSize);
if (NULL == ptr)
{
puts("malloc error");
}
memset(ptr,fileSize,);
fread(ptr, sizeof(BYTE), fileSize, fp);
fclose(fp);
//--解密dex
DecSize = *(DWORD*)(ptr+);
index = *(DWORD*)(ptr+0x10);
ptr += DecOffset;
if ( == DecSize)
{
printf("要解密的dex大小出错\n");
return -;
}
memset(&rc4_test,,sizeof(rc4_test));
unsignedcharDecKey[] = {};
for (inti=; i<; i++)
{
DecKey[i] = key[i];
}
unsignedcharkey1[] ={};
StrToHex(key1, DecKey, 0x10);
//--生成解密后的dex文件
fp = fopen("classes.dex","wb");
if (NULL == fp)
{
printf("File open error\n");
}
for (inti=; i<index; i++)
{
//初始化Key
init_Key(&rc4_test, key1, 0x10);
//解密数据
rc4_crypt(&rc4_test, ptr, DecOffset); fwrite(ptr, sizeof(BYTE), DecOffset, fp);
ptr+=DecOffset;
}
fclose(fp);
if (NULL != ptr)
{
free(Temp);
ptr = NULL;
Temp = NULL;
} printf("解密完成!^_^\n");
return ;
}

0x06 测试与总结

1.运行UnPack.exe输入要解密的APK包路径,成功解密后重新打包并正常反编译,如图17 图18所示。

      图17

      图18

2.以上就是简单实现一般APK加固静态脱壳机的编写步骤,由于该加固核心so文件使用UPX默认加壳并未做变形处理,导致so被轻松的静态脱卓,而so模块中的反调试手段比较初级且模块化,可以非常简单的手工patch函数一处反回值就可完全过掉,总的来说无论是静态脱壳还是动态dump都是很容易的。

完。

样本及PDF IDB下载

http://yunpan.cn/cFzNPXB27awau (提取码:6937)

APK加固之静态脱壳机编写入门的更多相关文章

  1. Android FART脱壳机流程分析

    本文首发于安全客 链接:https://www.anquanke.com/post/id/219094 0x1 前言 在Android平台上,程序员编写的Java代码最终将被编译成字节码在Androi ...

  2. APK加固之类抽取分析与修复

    0x00 简单介绍   目前我己知的APK加固主要有以下两种方式(或有其它的方式有待发现) 隐藏dex文件:通过对目标DEX文件进行整体加密或压缩方式把整个dex转换为另外一个文件存放在assets文 ...

  3. Android Apk加固的初步实现思路(dex整体加固)

    一.前 言 Android Apk加固的发展已经有一段时间了,相对来说本篇博客要记录的Android加壳的实现思路是4年的东西了,已经被老鸟玩烂了,Android加固的安全厂商也不会采用这么粗犷的方式 ...

  4. 基于御安全APK加固的游戏反外挂方案

    一. 前言 随着移动互联网的兴起,移动游戏市场近几年突然爆发,收入规模快速增长.根据第三方数据统计,国内移动游戏2015年市场规模已达514.6亿.由于手游市场强势兴起,而且后续增长势头会愈加猛烈.火 ...

  5. linux库文件编写入门(笔记)

    linux库文件的编写 作者: laomai地址: http://blog.csdn.net/laomai 本文主要参考了如下资料⑴hcj写的"Linux静态/动态链接库的创建和使用&quo ...

  6. 国内apk加固的破解方法

    国内apk加固的破解方法 By Bob Pan 国内的apk加固技术都使用了将原有的dex隐藏, 在运行时解压, 并且通过修改app的类加载器的方式实现加固. 参考: AndoridAPK反逆向解决方 ...

  7. 010 Editor 8.0.1 之 逆向分析及注册机编写

    前言一.工具及软件介绍二.逆向分析2.1.找到提示错误注册弹窗2.2.分析跳转处代码2.3.=2D 函数分析2.3.1.获取注册码处分析2.3.2.3处分支分析2.3.2.1.9C情况2.3.2.2. ...

  8. Gulp:插件编写入门

    之前挖了个坑,准备写篇gulp插件编写入门的科普文,之后迟迟没有动笔,因为不知道该肿么讲清楚Stream这货,毕竟,gulp插件的实现不像grunt插件的实现那么直观. 好吧,于是决定单刀直入了.文中 ...

  9. [.NET] [.net 脱壳工具]Sixxpack 最新脱壳机 通杀Sixxpack全版本by -=Msdn5 君临=

    [.net 脱壳工具]Sixxpack 最新脱壳机 通杀Sixxpack全版本by -=Msdn5 君临=- 识别方法: 如果无法调戏,请上传附件艾特我.............发帖不易啊..身处大西 ...

随机推荐

  1. 模板【洛谷P3811】 【模板】乘法逆元

    P3811 [模板]乘法逆元 给定n,p求1~n中所有整数在模p意义下的乘法逆元. T两个点的费马小定理求法: code: #include <iostream> #include < ...

  2. springloud系列搭建注册中心

    首先搭建父工程: 点击next父工程就搭建完成; pom.xml文件: <?xml version="1.0" encoding="UTF-8"?> ...

  3. 解决浏览器location.href重定向失效问题

    在[location.href]赋值语句后,添加页面刷新代码[location.reload(true)],参数为[true]这样就等价于F5刷新页面了. 需要注意的是:不能把[location.re ...

  4. sharepoint_study_11

    描述:修改管理员密码和账户后,管理中心无法打开.(提示:HTTP Error 503. The service is unavailable.) 解决: 1.打开iis 2.右击“应用程序池”下的”S ...

  5. Luogu P1120 小木棍 [数据加强版] 来来来我们一起来剪枝,剪枝,剪枝、、、

    好啊...太棒了... dfs(拼到第几根木棍,这根木棍剩余长度,上一根木棍的位置) len是木棍的长度,cnt是木棍的个数 震撼人心的剪枝: 1.枚举长度从最大的木棍开始,直到sum/2,因为之后只 ...

  6. chrome插件 crap jsonview

    最近有用到几个非常好用的Chrome  记录一下: 1.Crap Api debug,直接在Chrome标签打开的,界面大概长这样,方便调试 2. adblock 比较大众 3. tampermonk ...

  7. Autel MaxiSys Pro MS908P

    Autel MaxiSys pro MS908P is an evolutionary smart solution for specialized automotive diagnosis and ...

  8. NETCORE 之 openSUSE docker 安装

    openSUSE docker 安装https://www.jianshu.com/p/c725a06447d5 http://www.importnew.com/24684.htmlSuse安装Do ...

  9. Java学习笔记day07_琐碎知识_水仙花数_ASCII码_冒泡排序_简单选择排序_折半查找

    琐碎知识: 水仙花数, ASCII码, 冒泡排序, 简单选择排序, 折半查找 1.水仙花数 每位数的平方的和等于本身. 如100到999之间的水仙花数满足: 个位的平方+十位的平方+百位的平方 = 本 ...

  10. maya2016无法安装卸载激活失败

    AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...