攻防世界 安卓题目刷题记录

先把 攻防世界的安卓题目刷刷,,,再去刷一些pwn题目。,

发现自己刷的也不多

攻防世界 安卓题目刷题记录_第1张图片

 攻防世界 安卓题目刷题记录_第2张图片

估计剩下的都比较难 >=<

 

app3

 

这个题目算是比较好看的

就一个坑点,

题目中给的文件是 .ab   .ab 可以简单的理解成apk 的dump 文件 那么需要我们用 abe.jar的工具  可以分离出 文件,

D:\gugexiazai\android-backup-extractor-master\android-backup-extractor-master>java -jar abe-all.jar unpack app3.ab  app.apk
0% 1% 2% 3% 4% 5% 6% 7% 8% 9% 10% 11% 12% 13% 14% 15% 16% 17% 18% 19% 20% 21% 22% 23% 24% 25% 26% 27% 28% 29% 30% 31% 32% 33% 34% 35% 36% 37% 38% 39% 40% 41% 42% 43% 44% 45% 46% 47% 48% 49% 50% 51% 52% 53% 54% 55% 56% 57% 58% 59% 60% 61% 62% 63% 64% 65% 66% 67% 68% 69% 70% 71% 72% 73% 74% 75% 76% 77% 78% 79% 80% 81% 82% 83% 84% 85% 86% 87% 88% 89% 90% 91% 92% 93% 94% 95% 96% 97% 98% 99% 100%
9097216 bytes written to app.apk.

其实分离出的就是一个压缩包 打开发现了两个db 文件 还有 一个apk

试着用工具SQLiteDatabaseBrowserPortable 看db的时候。。 发现要密码

那么我们开始分析apk

攻防世界 安卓题目刷题记录_第3张图片

 

发现并没有什么东西,,

攻防世界 安卓题目刷题记录_第4张图片

这里就发现了 很多的函数逻辑,

不过发现了很多 以前没有见过的 东西

 

 ContentValues   可以简单的理解成一个 存储键值对的数据结构

那么就会发现程序逻辑很清楚了

     v0.put("name", "Stranger");
     v0.put("password", Integer.valueOf(0x0001e240));
     a v1 = new a();
     String v2 = v1.a(v0.getAsString("name"), v0.getAsString("password"));

Stranger=v0.getAsString("name")

”123456“= Integer.valueOf(0x0001e240)

那么函数运算 直接用java 粘贴复制就ok

import java.security.MessageDigest;

public class CTF {
	

	public static void main(String[] args){
		
		String v2=c("Stranger","123456");
		System.out.println(v2);
		String strs=b(new StringBuilder()+v2+a(v2)+"yaphetshan").substring(0, 7);
		System.out.println(strs);
	}
	 public static final String a(String arg9) {
	        String v0_2;
	        int v0 = 0;
	        char[] v2 = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
	        try {
	            byte[] v1 = arg9.getBytes();
	            MessageDigest v3 = MessageDigest.getInstance("MD5");
	            v3.update(v1);
	            byte[] v3_1 = v3.digest();
	            int v4 = v3_1.length;
	            char[] v5 = new char[v4 * 2];
	            int v1_1 = 0;
	            while(v0 < v4) {
	                int v6 = v3_1[v0];
	                int v7 = v1_1 + 1;
	                v5[v1_1] = v2[v6 >>> 4 & 15];
	                v1_1 = v7 + 1;
	                v5[v7] = v2[v6 & 15];
	                ++v0;
	            }

	            v0_2 = new String(v5);
	        }
	        catch(Exception v0_1) {
	            v0_2 = null;
	        }

	        return v0_2;
	    }
	 public static final String b(String arg9) {
	        String v0_2;
	        int v0 = 0;
	        char[] v2 = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
	        try {
	            byte[] v1 = arg9.getBytes();
	            MessageDigest v3 = MessageDigest.getInstance("SHA-1");
	            v3.update(v1);
	            byte[] v3_1 = v3.digest();
	            int v4 = v3_1.length;
	            char[] v5 = new char[v4 * 2];
	            int v1_1 = 0;
	            while(v0 < v4) {
	                int v6 = v3_1[v0];
	                int v7 = v1_1 + 1;
	                v5[v1_1] = v2[v6 >>> 4 & 15];
	                v1_1 = v7 + 1;
	                v5[v7] = v2[v6 & 15];
	                ++v0;
	            }

	            v0_2 = new String(v5);
	        }
	        catch(Exception v0_1) {
	            v0_2 = null;
	        }

	        return v0_2;
	    }
	 public static String c(String p0,String p1)
	 {
	      String v1 = null;
	      return new StringBuilder()+p0.substring(0, 4)+p1.substring(0, 4);
	 }

}

攻防世界 安卓题目刷题记录_第5张图片

成功解出数据库

攻防世界 安卓题目刷题记录_第6张图片

 base64解码一下

easy java

 这个题目也不难,,

重点是分析这个题目是想干啥的,

程序前面也就是让 把 flag{} 给分开 

然后把中间的字符串 做一下处理 然后和 wigwrkaugala 作比较

中间的字符串 主要是经历了

return p2.a(p1.a(input_cr)); 这个过程

这里两个函数 都是  在表中找到对应的值  然后返回下标

然后在 "abcdefghijklmnopqrstuvwxyz"; 中取出相应坐标的值就可以了

那两个表 也很好找

攻防世界 安卓题目刷题记录_第7张图片

 

直接模拟一下 就可以出来, = =  不过 有一个坑 我一开始没有看到 ,, 自闭了10分钟

攻防世界 安卓题目刷题记录_第8张图片

每次运行完都偏移1,,

 

下面是脚本程序

#!/user/bin/env python
# -*-coding:utf-8 -*-
from collections import deque

str_table="abcdefghijklmnopqrstuvwxyz"
table1=[8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13]
table2=[7, 14, 16, 21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8]
table3=[]
str_cmp = 'wigwrkaugala'
for i in range(2,len(table1)):
    table3.append(table1[i])
for i in range(0,2):
    table3.append(table1[i])

table1=table3
table3=[]
for i in range(3,len(table2)):
    table3.append(table2[i])
for i in range(0,3):
    table3.append(table2[i])
table2=table3
table3=[]
print(table1)
print(table2)
flag=""

for i in range(len(str_cmp)):
    index=ord(str_cmp[i])-ord('a')
    t1=table2[index]
    t2=table1[t1]
    flag+=str_table[t2]
    table3=[]
    for j in table1[1:]:
        table3.append(j)
    #table3.append(table1[1:])
    table3.append(table1[0])
    #table1=table1[1:].append(table1[0])
    table1=table3
    str_table=str_table[1:]+str_table[0]
    #print(str_table)
    #print(table1)
    
   

print(flag)
    


    

 

RememberOther 

这个题目其实不算难, 只是脑洞有点大,,,

 

攻防世界 安卓题目刷题记录_第9张图片

然后发现 分析了一波 发现没有看到什么有用的信息  去找了一下maketext 弹出的页面信息

 

攻防世界 安卓题目刷题记录_第10张图片

在 values  里面的strings.xml 里面找到的

然后md5 解密一下,

攻防世界 安卓题目刷题记录_第11张图片

 发现了解密成功 。

但是flag 交上去不对 。

后来看了一下题解  补上了 ANDROID然后提示 拿到了flag

easy so

这题目 其实看一下就知道怎么回事了,,,

 

就是分析so文件里面的函数 

攻防世界 安卓题目刷题记录_第12张图片

 

 就是 前16位和 后16位置换一下  然后在  两两换位    直接看脚本,,



strcmp="f72c5a36569418a20907b55be5bf95ad"


flags=""
for i in range(0,len(strcmp),2):
    flags+=strcmp[i+1]+strcmp[i]

print(flags[16:]+flags[:16])
    

 

黑客精神,,

 

这个题目 有点好玩 

java 层没有啥好说的 

主要看看so层的情况 

 

主要看n1  n2  n3 函数的情况

攻防世界 安卓题目刷题记录_第13张图片

 

然后去看看   n1这个函数

攻防世界 安卓题目刷题记录_第14张图片

然后发现是读取里面的数据 

我们看一下n2

攻防世界 安卓题目刷题记录_第15张图片 一堆的数据操作   其实不难猜出来   v19 是 input   v20 就是上面的字符串 直接写一个脚本就可以

#-*- coding=utf-8 -*-


strcmp="EoPAoY62@ElRD"
strtable="W3_arE_whO_we_ARE"

magic_number=2016
flag=""
for i in range(len(strcmp)):
    if i%3==1:
        magic_number=(magic_number+5)%16
        flag+=chr(ord(strcmp[i])^ord(strtable[magic_number+1]))
    if i%3==2:
        magic_number=(magic_number+7)%15
        flag+=chr(ord(strcmp[i])^ord(strtable[magic_number+2]))
    if i%3==0:
        magic_number=(magic_number+3)%13
        flag+=chr(ord(strcmp[i])^ord(strtable[magic_number+3]))
    
print(flag)
'''
    while ( v15 < v18 )
    {
      if ( v15 % 3 == 1 )
      {
        v13 = (v13 + 5) % 16;
        v19 = *(&v23 + v13 - 23);
      }
      else if ( v15 % 3 == 2 )
      {
        v13 = (v13 + 7) % 15;
        v19 = *(&v23 + v13 - 22);
      }
      else
      {
        v13 = (v13 + 3) % 13;
        v19 = *(&v23 + v13 - 21);
      }
      v20 = *v17;
      ++v15;
      *(++v17 - 1) = v20 ^ v19;
    }
    fputs(v16, v5);
  }

'''


easy-dex 

这个题目有点难度,,

不过这个题目感觉在哪做过,,,

 

这个题目 看了一些log 信息 应该是让 10s 然后做晃动手机100次,,,

因为我一直都是用夜神模拟 调试,,, 夜神模拟器我的没有晃动按钮 (我没有找到 或许有?)

然后 感觉直接改调转dump 肯定不行  然后打算硬干里面运算的算法

先把 里面的字符串给恢复了一下(没啥用)

#-*- coding=utf-8 -*-

lists=[0x9D888DC6,0x888DC688,0x8AC6889D,0x88C78486,0x84889AC7,0xC78C8599,
0x8D87808F,0x8C8D9084,0x808FC691,0xC69A8C85,0x9A88858A,0xC79A8C9A,0xE9918C8D]

flag=""
for i in lists:
    strs=(i).to_bytes(4, 'little')
    for j in strs:
        flag+=chr(j^0xe9)

print("**************")
print(flag)

lists=[0x9D888DC6,0x888DC688,0x8AC6889D,0x88C78486,0x84889AC7,
0xC78C8599,0x8D87808F,0x8C8D9084,0x808FC691,0xC69A8C85,0x918C8D86]

flag=""
for i in lists:     
    strs=(i).to_bytes(4, 'little')
    for j in strs:
        flag+=chr(j^0xe9)

print(flag)
print("**************")


 

然后就是逆向数据了

攻防世界 安卓题目刷题记录_第16张图片

然后写出脚本

# -*- coding:utf-8 -*- 
import os
import zlib
f=open("dump",'rb').read()
#f=open("dump.txt",'rb').read()
#print f

print(hex(len(f)))
os.system("pause")
length = 0x3CA10
#length = 0x41BE8
data = list(f)   
#print hex(len(data)) 
for j in range(0,90):
    if j%10 == 9:
        ls = (j/10)
        ls_ = (length/10)
        start = ls*ls_
        end = (ls+1)*ls_
        for i in range(start,end):
            data[i] = chr(ord(data[i])^j)
        if j == 89:
            for i in range(end,length):
                data[i] = chr(ord(data[i])^89)


result = ''.join(data)
ws=open('s.zip','wb')
ws.write(str(result))
ws.close()
c = zlib.decompress(result)
ff=open('class.dex','wb')
ff.write(c)
ff.close()

fss=open('real.dex','rb').read()
datas=fss

fs=open('ss.zip','wb')
cc = zlib.compress(datas)
fs.write(cc)
fs.close()

cc = zlib.decompress(cc)
with open('sss.dex','wb') as fws:

    fws.write(cc)

fws.close()


'''
import idaapi
start_address=0x7004
data_length=0x41BE8 #0x7005#0x41BE8
data=idaapi.get_bytes(start_address, data_length)
fp = open('dump', 'wb')
#print data
fp.write(data)
fp.close()

print "[*]  ok"

'''

然后搞出了 dex

然后在ide 里面搜索 发现了这个

攻防世界 安卓题目刷题记录_第17张图片

 I have a male fish and a female fish

分析了一下 这个就是key

 

twofish  当时我做过一道题目

是关于这个算法的  当时那个题目是有解密函数  但是因为这个算法 让我感觉到很好玩  

然后就记得了   试了一下 解密一下

攻防世界 安卓题目刷题记录_第18张图片

 

# -*- coding:utf-8 -*- 
import base64
import binascii
from twofish import Twofish
T = Twofish(b'I have a male fish and a female ')


s= [-120, 77, -14, -38, 17, 5, -42, 44, -32, 109, 85, 31, 24, -91, -112, -83, 64, -83, 
-128, 84, 5, -94, -98, -30, 18, 70, -26, 71, 5, -99, -62, -58, 117, 29, -44, 6, 112, -4,
 81, 84, 9, 22, -51, 95, -34, 12, 47, 77]
  
ss=[3, -91, 61, -29, -87, -21, 101, -57, 27, -19, -27, -10, -61, 15, 
-85, 12, -32, -102, 106, 92, -39, 100, -122, 112, 18, -100, -55, 44, 60, 
-118, -97, 127, 76, 113, -35, 68, -17, -33, -93, -62, -57, -84, 36, -96, 97, -15, 20, 69]
flag=""
sst= [chr(i&0xff) for i in s]



#flags=binascii.b2a_hex(flag)
#print flags
#print binascii.a2b_hex(flags).decode('hex')
#print flag
#'''
flag=""
sss=""
for i in range(0,16):
    sss+=sst[i]

flag+=T.decrypt(sss)
sss=""
for i in range(16,32):
    sss+=sst[i]
flag+=T.decrypt(sss)
sss=""
for i in range(32,48):
    sss+=sst[i]
flag+=T.decrypt(sss)

#flag+=T.decrypt(x[0:16])
print flag
#print base64.b64encode(flag)
#'''

strs='Ncg`esdvLkLgk$mL=Lgk$mL=Lgk$mL=Lgk$mL=Lgk$mLm'

lsl=""
for i in strs:
    lsl+=chr(ord(i)^0x10)

print lsl

交上题目并不对, ,

不知道怎么回事

 

Illusion

这个题目。。

算是感觉比较好玩的一道题目了  首先看一下java层

攻防世界 安卓题目刷题记录_第19张图片

就是读取flag 文件里面的数据 和做比较

攻防世界 安卓题目刷题记录_第20张图片

然后去分析so文件,,,

我有一个好习惯 就是 看so层的时候我一般会先看看load这个函数的代码,。。 我发现了这个

攻防世界 安卓题目刷题记录_第21张图片

 

攻防世界 安卓题目刷题记录_第22张图片

 

重头戏来了。。。 接下来怎么分析 

这里 恐怕就要 撸一下arm 指令了

攻防世界 安卓题目刷题记录_第23张图片

攻防世界 安卓题目刷题记录_第24张图片

可以看出 r1 就是我们最后要比较的点,,,

而我写了一个demo 观察了一波1028这个函数

然后发现,

#include

int  sub_1028(unsigned int a1, unsigned int a2)
{
  signed int v2; // r12
  unsigned int v3; // r3
  int v4; // r2
  int result; // r0

  v2 = a1 ^ a2;
  v3 = 1;
  v4 = 0;
  if ( (a2 & 0x80000000) != 0 )
    a2 = -a2;
  if ( (a1 & 0x80000000) != 0 )
    a1 = -a1;
  if ( a1 >= a2 )
  {
    while ( a2 < 0x10000000 && a2 < a1 )
    {
      a2 *= 16;
      v3 *= 16;
    }
    while ( a2 < 0x80000000 && a2 < a1 )
    {
      a2 *= 2;
      v3 *= 2;
    }
    while ( 1 )
    {
      if ( a1 >= a2 )
      {
        a1 -= a2;
        v4 |= v3;
      }
      if ( a1 >= a2 >> 1 )
      {
        a1 -= a2 >> 1;
        v4 |= v3 >> 1;
      }
      if ( a1 >= a2 >> 2 )
      {
        a1 -= a2 >> 2;
        v4 |= v3 >> 2;
      }
      if ( a1 >= a2 >> 3 )
      {
        a1 -= a2 >> 3;
        v4 |= v3 >> 3;
      }
      if ( !a1 )
        break;
      v3 >>= 4;
      if ( !v3 )
        break;
      a2 >>= 4;
    }
  }
  result = v4;
  if ( v2 < 0 )
    result = -v4;
  return result;
}
int main()
{

    for(int i=0;i<100;i++)
    {
        printf("[# %d]: %d\n",i,sub_1028(i,93));
    }
    return 0;
}

攻防世界 安卓题目刷题记录_第25张图片

 

也就是说,,, 这个函数只要大于等于93 就是1 其余是0

那么在结合arm  就可以得出结论。。。

如果大于93 就是  减去 93  否则就直接返回参数一 

那么就可以写出脚本 拿到flag。

 

import string
strcmp="Ku@'G_V9v(yGS"
strtable="(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"
flag=""
strs=string.printable
if __name__ =="__main__":
    for i in range(0,len(strcmp)):
        for j in strs:
            tmp=ord(j)-0x40+ord(strtable[i])
            if tmp>=0x5d:
                tmp=tmp-0x5d
            tmp+=0x20
            if tmp==ord(strcmp[i]):
                flag+=j
                break

    print(flag)

 

人民的名义-抓捕赵德汉1-200

这个题目。。

就是一道水题   只需要解一下 md5 就可以了

Android2.0 

swpu 的题目 记得做了  就是简单的so库 函数分析

str1="LN^dl"
str2=[32, 53, 45, 22, 97]
str3="AFBo}"

flag=""
for i in range(4):
	flag+=chr(int((ord(str1[i])^0x80)/2))
	flag+=chr(ord(str1[i])^str2[i])
	flag+=chr(ord(str3[i])^str2[i])

flag+=str1[4]
flag+=chr(str2[4])
flag+=str3[4]
print(flag)

 

参考链接

https://blog.pwnhub.cn/2017/06/12/%E6%8E%8F%E5%87%BA%E4%BD%A0%E7%9A%84%E5%B0%8F%E6%89%8B%E6%9C%BAWriteup/

Flag_system

首先把这个文件给一下版本和压缩标志位

攻防世界 安卓题目刷题记录_第26张图片

 

发现出来了两个文件夹

其中一个还有db文件 

在jeb 里面发现了他们都是在读取db文件

感觉函数逻辑还是挺复杂的,,,,  直接得到db文件 用sql语句查就可以

frida 一把梭

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# @Author  : pipixia
import frida
import sys
import gmpy2


#select book_author,book_name from books_table
 
jscode = """
Java.perform(function () {
    send("Hook start..");
    
    var test = Java.use('com.example.mybackup.Test');
    var k;
    test.getSign.implementation = function () {
        send("getSign Function implementated");
        k = test.getSign.apply(this,arguments);
        send("Password is : " + k);

        return k;
    }

    var demo = Java.use('com.example.mybackup.BooksDB');
    var db;
    demo.getReadableDatabase.implementation = function (k) {
        send("getReadableDatabase Function implementated");
        db = this.getReadableDatabase(k);
        if(db != null)
            send('DB got');
        var S = Java.use("java.lang.String");
        var sql = S.$new("select book_author,book_name from books_table");
        var cursor = db.rawQuery(sql,null);
        if(cursor!=null)
            send('cursor got');
        send(cursor);
        /*cursor.getString(0);
        while(cursor.moveToNext()) {
            send("Result : " + cursor.getString(0));
        }
        Java.choose("net.sqlcipher.Cursor" , {
            onMatch : function(instance){
                console.log("Found instance: "+instance);
            },
            onComplete:function(){}
        });*/
        var class_cursor = Java.use("android.database.Cursor");
        cursor = Java.cast(cursor,class_cursor);
        send(cursor);
        while(cursor.moveToNext()) {
            send("Result : " + cursor.getString(0));
        }

        return db;
    }

    demo.$init.implementation = function (a) {
        send("$init Function implementated");
        return this.$init(a);
    }



});
"""
def on_message(message, data):
    if message['type']=='send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)

device = frida.get_remote_device()
pid = device.spawn(['com.example.mybackup'])
process = device.attach(pid)
 
script = process.create_script(jscode)
 
script.on("message", on_message)
script.load()
device.resume(pid)
sys.stdin.read()

 

你可能感兴趣的:(逆向之旅)