CTF 安卓逆向

MagicImageViewer——png结构+算法

很少做安卓逆向的题目,在此记录一下

先用模拟器看一下



嗯,没啥提示。

jeb打开

关键部分

  1. if(s.length() == 16) //输入的字符串长度为16
  2. String s1 = MainActivity.this.getKey(s); //该方法获得s1,getKey()在native层
  3. Bitmap bitmap0 = MagicImageUtils.readMagicImage(MainActivity.this, "png/encrypt_png.dat", s1);
  4. // MagicImageUtils.readMagicImage是Java层的方法

先看getKey()

关键部分

  1. strcpy(v5, "Welcome_to_sdnisc_2018_By.Zero");
  2. v13[i] = *(v7 + 2 * i) ^ v5[i - 30 * (v9 / 30)];

2*i比较怪,是什么呢?我们查一下JNI的GetStringChars方法,由参考链接1可知它返回的是Unicode格式的char*,所以2字节算一个字符**

v5[i - 30 * (v9 / 30)这个就是v5[i]

就是对输入的字符串进行异或(前16位)

接着看MagicImageUtils.readMagicImage



关键部分

  1. int v1 = inputStream0.read();//读取路径文件
  2. arrayList0.add(Byte.valueOf(((byte)MagicImageUtils.decrypt(v1, ((char)s1.charAt(v % 16))))));
  3. //decrypt() 在native层



也是个异或

接着往下看可以发现,后面生成了图片,也就是对于加密后的图片数据,解密为图片

输入s,s与v5异或得到s1,s1,路径文件异或生成内容转化,图片。

但是png图片的前16位是固定的,所以很容易解出来。

  1. goal = b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52' //png图片的前16 位
  2. key_s = 'Welcome_to_sdnisc_2018_By.Zero'
  3. ans = ''
  4. with open('encrypt_png.dat', 'rb') as f:
  5. dat = f.read(16)
  6. for i in range(16):
  7. v = (dat[i] - 1) ^ 0x61 ^ goal[i] ^ ord(key_s[i])
  8. ans += chr(v)
  9. print(ans)

输出 XaE3*2#@!qV^v+_.

验证:

得到flag。

此时可以更为有趣的写出png(刚开始没想到)

此时

没看懂getKey也能过这题。

作者贴心地提供了一个正常图片的处理函数MagicImageUtils.readImage。

此时会出现dat=0的情况,所以加了验证

  1. goal = b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52'
  2. def b(v):
  3. return v if v >= 0 else 0xff
  4. with open('encrypt_png.dat', 'rb') as f:
  5. dat = f.read()
  6. _key = b''
  7. for i in range(16):
  8. _key += (b(dat[i] - 1) ^ 0x61 ^ goal[i]).to_bytes(length=1, byteorder='big', signed=False)
  9. with open('flag.png', 'wb') as f:
  10. for i in range(len(dat)):
  11. f.write((b(dat[i] - 1) ^ 0x61 ^ _key[i & 0xf]).to_bytes(length=1, byteorder='big', signed=False))

flag{y0ur'r3_g00d_aT_4ndr01d}

参考链接:

https://www.cnblogs.com/lijunamneg/archive/2012/12/22/2828891.html

https://www.52pojie.cn//thread-1665541-1-1.html

随机推荐

  1. 手机号码归属地的自动查询.py(亲测有效)

    import requests url = "http://m.ip138.com/sj.asp?mobile=" kv = {'user-agent':'Mozilla/5.0' ...

  2. fork语句遇见for循环语句

    一.没有automatic的fork-join_none 通常小白会这么写: 代码如下: foreach(a[i]) begin fork repeat(a[i]) #1ns; $display(&q ...

  3. jQ的工具类方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 这年头,谁的好友列表还没有躺一个ChatGPT啊?

    你要是说这个,我可不困了 大家好,我最近开始使用一款非常有趣的AI机器人,它叫做ChatGPT.ChatGPT是一款独特的聊天机器人,它可以进行智能对话,回答你的问题,还可以学习你的语言习惯,使得对话 ...

  5. ASP.NET CORE开发 (三)

    1. 在使用singleton时出现 Cannot resolve scoped service 'AlgoTag.Models.AlgoContext' from root provider. ht ...

  6. 【开源免费】ChatGPT-Java版SDK重磅更新至1.0.10版,支持Tokens计算,快来一键接入。

    简介 ChatGPT Java版SDK开源地址:https://github.com/Grt1228/chatgpt-java ,目前收获将近1000个star. 有bug欢迎朋友们指出,互相学习,所 ...

  7. dfs实现

    1.思路:从图中的未访问的一个顶点开始,沿着一条路一直走到底,然后这条路尽头的节点,在从另外一条路走到底,不断递归此过程,直到所有遍历完成特点:不撞南墙不回头2.具体实现:当从一个未知的顶点出发,将这 ...

  8. MySQL 读书笔记(一)

    1 MySQL 表 1.1 索引组织表 在 InnoDB 存储引擎中,表都是根据主键顺序存放的,这种存储方式称为索引组织表. InnoDB存储引擎中,每张 MySQL表 都有一个唯一主键,如果创建表时 ...

  9. 基于【ESLint+JavaScript Standard Style】标准的VUE/JS/html风格指南

    小仙男前端代码风格规范指南v1.0 概述 本规范是适用于小仙男团队及前端团队所搭建的各种前端框架代码的通用风格规范指南: 使用时,请遵循指南细则进行代码风格约束,并在提交之前确保进行代码风格的修正操作 ...

  10. Vue2的组件中data为什么不能使用对象

    当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例. 如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数 ...