返回列表 发新帖

ApkPecker上线DEX-VMP自动化脱壳服务

  [复制链接]

65

主题

2339

帖子

1万

积分

管理员

Hasky

Rank: 9Rank: 9Rank: 9

金币
4404
好评
573
贡献
30

小明星MT论坛优秀版主MT论坛侠客2018MT论坛优秀成员MT论坛最佳新人MT论坛帅哥MT论坛活跃会员2019-5.1节快乐考神

QQ
发表于 2021-7-19 18:50:22 | 显示全部楼层 | 阅读模式

近日,腾讯安全科恩实验室ApkPecker上线了自动化脱壳服务,帮助安全人员更好地进行安全审计。经过大规模测试结果显示, ApkPecker的脱壳成功率超过了85%。


移动应用脱壳是移动应用逆向及恶意应用分析最基本的操作,主要为在移动应用安全审计和病毒分析的过程中,帮助安全人员脱掉应用的壳代码,从而去分析其关键代码。移动应用脱壳有助于开发者及时发现应用开发代码本身存在的安全问题以及审查发现恶意行为。企业尤其是规模较大的企业经常需要采用第三方供应链提供的应用安全开发及加固服务,安全人员需要对其安全性进行校验,移动应用脱壳就是其中的必经步骤。






常规而言,安全人员一般采用手动方式进行脱壳,一是受制于安全研究人员本身水平的高低,二是其中有大量重复性工作,耗费企业安全人力。而市面上现有的自动脱壳工具不能解决DEX虚拟化的加固方案,并且厂商自定义的解释器会定期更换Opcode映射表,导致很多自动脱壳服务无法完整有效的还原DEX代码。




基于这个洞察,腾讯安全科恩实验室根据多年安全攻防研究经验,推出先进的自动化脱壳方案,支持恢复常见的DEX加密和指令抽取等类型的加固。同时,针对厂商的DEX虚拟化保护(DEX-VMP), ApkPecker也进行了针对性脱壳和恢复。




ApkPecker在确定厂商字节码格式的基础上,通过AI学习厂商解释器二进制中opcode handler的运行时行为,从而自动化恢复出厂商解释器的opcode语义,还原出原始Dalvik字节码,并重写DEX文件。ApkPekcer的脱壳方案解决了opcode handler识别的难点,自动化还原被DEX-VMP保护的代码,提高了脱壳的完整度和自动化程度。经过大规模测试结果显示,ApkPecker的脱壳成功率超过了85%。



ApkPecker是腾讯安全科恩实验室研发的一款全自动的Android 应用漏洞扫描工具,该系统通过Android应用生命周期建模和应用攻击面建模,采用静态数据流分析和污点分析的技术,提高漏洞发现的准确率。ApkPecker能够输出高质量漏洞扫描报告,提供高品质漏洞信息以及漏洞触发完整路径,精准定位漏洞并提供修复建议,帮助移动安全人员解决现有痛点,提升应用安全性。

此次上线的自动化APK脱壳服务,也是其整体能力的又一次升级。Apkpecke致力于成为安全研究人员的数字助手,广大移动应用开发商可以借助ApkPecker对各种移动应用风险进行有力的防御,建立从APP开发到用户交互的产品全生命周期的安全管理,开展安全风险检测与控制,为用户的手机信息、财产安全保驾护航。



ApkPecker脱壳服务FAQ如何使用脱壳服务API 概述
  • 协议:https
  • 功能:提供APK脱壳服务,支持还原主流加壳厂商的DEX VMP加固

使用说明
先使用上传 APK 的 API 接口上传目标 APK,根据壳类型不同几分钟之后可以使用查询结果接口访问脱壳结果和下载接口下载脱壳后的APK。
API身份认证
apkpecker.qq.com可以使用微信注册,登录后可以查看自己的Authorization值, Bearer开头。

Header键名
描述
Header键值
必填
Authorization
身份认证
Bearer XXX




上传APK进行脱壳
  • 方法:POST
  • URI:  /api/unpack/upload_apk
  • 参数:

参数
描述
类型
必填
uploadfile
文件字段
文件

正常返回结果:
  1. {
  2.     "success": true,
  3.     "body":{
  4.         "upload_apk_md5": "<MD5>",
  5.         "unpack_task_id": integer
  6.      }
  7. }
复制代码
  • 重复上传md5相同的apk会失败,请使用“重新处理已上传apk进行脱壳”接口

重新处理已上传apk进行脱壳
  • 方法: POST
  • URI: /api/unpack/process_uploaded_apk
  • 参数:
  • 参数
    描述
    类型
    必填
    upload_apk_md5
    已上传apk的md5
    string
  • 正常返回结果:
    1. {
    2.     "success": true,
    3.     "body":{
    4.         "unpack_task_id": integer
    5.      }
    6. }
    复制代码
    获取脱壳结果
    • 方法:  POST
    • URI: /api/unpack_result
    • 参数:

    参数名
    描述
    类型
    必填
    task_id
    任务id
    integer
    • 正常返回结果:
      1. {
      2.     "success": true,
      3.     "body": {
      4.     "unpack_result": "string",
      5.     "msg": "string"
      6.     }   
      7. }
      复制代码
      unpack_result取值如下:

      • "UNFINISHED": 未开始或进行中
      • "SUCCESS": 成功脱壳
      • "NO_PACK": 无壳
      • "FAILURE": 脱壳失败
      • "TIMEOUT": 脱壳机器长时间未返回


      下载已脱壳的Apk
      • 方法:  POST
      • URI:  /api/dl_unpacked
      • 参数:

      参数名
      描述
      类型
      必填
      task_id
      任务id
      integer

      • 正常返回的content为脱壳后的APK
      • 正常返回的header中Filemd5给出了脱壳apk的md5

      error code
      • "INVALID_PARAMETER"
      • "NOT_LOGIN"
      • "EXPIRED"
      • "INVALID_TOKEN"
      • "TASK_NOT_FOUND" # 任务未找到
      • "TASK_FAILURE" # 任务已失败
      • "WAIT_TASK_FINISH" # 任务未完成



    • 示例脚本
      Python 实现的API使用示例代码,需要替换认证信息和本地APK路径


      1. import os
      2. import requests
      3. import json
      4. import traceback
      5. import time


      6. HOST = "https://apkpecker.qq.com"
      7. AUTH_KEY = "Authorization"
      8. AUTH_VALUE = "Bearer <REPLACE_ME>"  # use cookie in apkpecker.qq.com
      9. HEADERS = {AUTH_KEY: AUTH_VALUE}


      10. def upload_apk(apk_path: str) -> int:
      11.     api = "/api/unpack/upload_apk"
      12.     if not os.path.exists(apk_path):
      13.         raise Exception("apk %s not exist" % apk_path)
      14.     file_obj = None

      15.     task_id = 0
      16.     try:
      17.         file_obj = open(apk_path, "rb")
      18.         files = {"uploadfile": (os.path.basename(apk_path), file_obj)}
      19.         data = {"apk_analysis_tools": '["unpack"]'}
      20.         response = requests.post(
      21.             HOST+api, files=files, data=data, headers=HEADERS, timeout=60 * 5)
      22.         result = json.loads(response.content.decode())

      23.         if result["success"] == True:
      24.             body = result["body"]
      25.             apk_md5 = body["upload_apk_md5"]
      26.             task_id = body["unpack_task_id"]
      27.             print("upload success, md5 %s, task id %d" % (apk_md5, task_id))
      28.         else:
      29.             print("upload apk failed")
      30.             print(response.text)
      31.     except Exception as ex:
      32.         print("Exception: %s" % ex)
      33.         print(traceback.format_exc())
      34.     finally:
      35.         if file_obj:
      36.             file_obj.close()
      37.         return task_id


      38. def get_unpack_result(task_id: int) -> bool:
      39.     api = "/api/unpack_result"
      40.     result = False
      41.     try:
      42.         data = {"task_id": task_id}
      43.         response = requests.post(
      44.             HOST+api, data=data, headers=HEADERS, timeout=60 * 5)
      45.         result = json.loads(response.content.decode())

      46.         if result["success"] == True:
      47.             body = result["body"]
      48.             unpack_result = body["unpack_result"]
      49.             print("get result success, task id %d, result %s" %
      50.                   (task_id, unpack_result))

      51.             if unpack_result == "SUCCESS":
      52.                 result = True
      53.             else:
      54.                 result = False
      55.         else:
      56.             print("get unpack result failed")
      57.             print(response.text)
      58.     except Exception as ex:
      59.         print("Exception: %s" % ex)
      60.         print(traceback.format_exc())
      61.     finally:
      62.         return result


      63. def download_unpacked(task_id: int,  apk_path: str):
      64.     api = "/api/dl_unpacked"
      65.     try:
      66.         data = {"task_id": task_id}
      67.         response = requests.post(
      68.             HOST+api, data=data, headers=HEADERS, timeout=60 * 5)
      69.         print(response.headers)
      70.         with open(apk_path, "wb") as f:
      71.             f.write(response.content)
      72.     except Exception as ex:
      73.         print("download unpacked apk failed")
      74.         print("Exception: %s" % ex)
      75.         print(traceback.format_exc())


      76. def process_uploaded_apk(apk_md5: str):
      77.     api = "/api/unpack/process_uploaded_apk"
      78.     task_id = 0
      79.     try:
      80.         data = {"upload_apk_md5": apk_md5}
      81.         response = requests.post(
      82.             HOST+api, json=data, headers=HEADERS, timeout=60 * 5)

      83.         result = json.loads(response.content.decode())
      84.         if result["success"] == True:
      85.             body = result["body"]
      86.             task_id = body["unpack_task_id"]
      87.             print("process uploaded apk success, task id %d" %
      88.                   (task_id))
      89.         else:
      90.             print("process uploaded apk failed")
      91.             print(result)
      92.     except Exception as ex:
      93.         print("Exception: %s" % ex)
      94.         print(traceback.format_exc())
      95.     finally:
      96.         return task_id


      97. if __name__ == "__main__":

      98.     apk_path = "<REPLACE_ME> "  # APK file path

      99.     task_id = upload_apk(apk_path)

      100.     # uploading apk with same md5 is not allowed by apkpecker,
      101.     # but we can re-analysis uploaded apk

      102.     # task_id = process_uploaded_apk("2bbcbfbb17a64d16a4891e832c7d0f37") # apk md5sum

      103.     if task_id != 0:
      104.         while True:
      105.             result = get_unpack_result(task_id)
      106.             if result:
      107.                 download_unpacked(task_id, "./unpacked.apk")
      108.                 break
      109.             else:
      110.                 time.sleep(30)
      复制代码
      为什么有时脱壳会失败
      我们主要针对目前市场上主流的最新版本DEX-VMP和绝大多数的动态加载、指令抽取类壳进行适配。如果提交的APK使用的壳的版本过于老旧,则可能无法正确脱壳。其次,少部分APK因为兼容性等问题,无法在我们的环境上执行,也会导致脱壳失败。
      此外,ApkPecker的自动脱壳系统目前属于测试阶段,虽然经过测试,但是难免存在bug,如果确信APK和壳没有上述兼容性问题








[size=14.6667px]

体验地址:
游客,如果您要查看本帖隐藏内容请回复



游客,如果您要查看本帖隐藏内容请回复








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
已有1人评分好评 金币 理由
言欢 + 1 + 1

查看全部评分 总评分:好评 +1  金币 +1 

本帖被以下淘专辑推荐:

回复

使用道具 举报

86

主题

4382

帖子

1万

积分

博士生

Rank: 7Rank: 7Rank: 7

金币
4926
好评
227
贡献
1

MT论坛最佳新人MT论坛帅哥考神MT论坛活跃会员MT论坛侠客MT论坛新人

发表于 2021-7-19 18:52:35 来自手机  | 显示全部楼层
沙发
回复

使用道具 举报

58

主题

4554

帖子

1万

积分

博士生

滑稽

Rank: 7Rank: 7Rank: 7

金币
2769
好评
59
贡献
0
QQ
发表于 2021-7-19 18:53:13 来自手机  | 显示全部楼层
看看     
回复

使用道具 举报

15

主题

102

帖子

642

积分

初中生

Rank: 3Rank: 3

金币
119
好评
2
贡献
0
发表于 2021-7-19 18:53:55 来自手机  | 显示全部楼层
回复

使用道具 举报

3

主题

1387

帖子

5444

积分

硕士生

Rank: 6Rank: 6

金币
166
好评
2
贡献
0

考神MT论坛帅哥MT论坛新人

发表于 2021-7-19 18:54:51 来自手机  | 显示全部楼层
回复

使用道具 举报

11

主题

442

帖子

1457

积分

高中生

Rank: 4

金币
585
好评
6
贡献
1

考神MT论坛帅哥MT论坛最佳新人

QQ
发表于 2021-7-19 18:55:18 来自手机  | 显示全部楼层
好期待啊
回复

使用道具 举报

0

主题

74

帖子

319

积分

初中生

Rank: 3Rank: 3

金币
176
好评
0
贡献
0
发表于 2021-7-19 18:55:22 来自手机  | 显示全部楼层
回帖是一种美德
回复

使用道具 举报

0

主题

161

帖子

469

积分

初中生

Rank: 3Rank: 3

金币
215
好评
0
贡献
0
发表于 2021-7-19 18:56:35 来自手机  | 显示全部楼层
看看。。。
回复

使用道具 举报

11

主题

535

帖子

1292

积分

高中生

Rank: 4

金币
483
好评
2
贡献
0

MT论坛新人MT论坛最佳新人

QQ
发表于 2021-7-19 18:59:07 来自手机  | 显示全部楼层
回复看看
回复

使用道具 举报

0

主题

331

帖子

1231

积分

高中生

Rank: 4

金币
423
好评
0
贡献
0
发表于 2021-7-19 18:59:39 来自手机  | 显示全部楼层
牛逼牛逼
回复

使用道具 举报

0

主题

290

帖子

1292

积分

高中生

Rank: 4

金币
110
好评
0
贡献
0
发表于 2021-7-19 19:00:53 来自手机  | 显示全部楼层
这么厉害
回复

使用道具 举报

1

主题

453

帖子

1239

积分

高中生

Rank: 4

金币
351
好评
0
贡献
0
发表于 2021-7-19 19:01:03 来自手机  | 显示全部楼层
牛啊这个
回复

使用道具 举报

87

主题

3457

帖子

1万

积分

博士生

Rank: 7Rank: 7Rank: 7

金币
3078
好评
44
贡献
19

MT论坛最佳新人MT论坛帅哥考神MT论坛活跃会员

QQ
发表于 2021-7-19 19:01:30 来自手机  | 显示全部楼层
回复

使用道具 举报

149

主题

2398

帖子

5882

积分

硕士生

安争(潜水,偶尔回复。)

Rank: 6Rank: 6

金币
667
好评
74
贡献
0

考神MT论坛最佳新人MT论坛帅哥MT论坛新人MT论坛活跃会员MT论坛侠客

QQ
发表于 2021-7-19 19:02:31 来自手机  | 显示全部楼层
突然感觉被圈钱。。。。
回复

使用道具 举报

7

主题

427

帖子

1427

积分

高中生

小菜鸟

Rank: 4

金币
968
好评
0
贡献
0
发表于 2021-7-19 19:02:52 | 显示全部楼层
谢谢分享
没有耕耘,没有收获!
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表