先把 攻防世界的安卓题目刷刷,,,再去刷一些pwn题目。,
发现自己刷的也不多
估计剩下的都比较难 >=<
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
发现并没有什么东西,,
这里就发现了 很多的函数逻辑,
不过发现了很多 以前没有见过的 东西
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);
}
}
成功解出数据库
base64解码一下
easy java
这个题目也不难,,
重点是分析这个题目是想干啥的,
程序前面也就是让 把 flag{} 给分开
然后把中间的字符串 做一下处理 然后和 wigwrkaugala 作比较
中间的字符串 主要是经历了
return p2.a(p1.a(input_cr)); 这个过程
这里两个函数 都是 在表中找到对应的值 然后返回下标
然后在 "abcdefghijklmnopqrstuvwxyz"; 中取出相应坐标的值就可以了
那两个表 也很好找
直接模拟一下 就可以出来, = = 不过 有一个坑 我一开始没有看到 ,, 自闭了10分钟
每次运行完都偏移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
这个题目其实不算难, 只是脑洞有点大,,,
然后发现 分析了一波 发现没有看到什么有用的信息 去找了一下maketext 弹出的页面信息
在 values 里面的strings.xml 里面找到的
然后md5 解密一下,
发现了解密成功 。
但是flag 交上去不对 。
后来看了一下题解 补上了 ANDROID然后提示 拿到了flag
easy so
这题目 其实看一下就知道怎么回事了,,,
就是分析so文件里面的函数
就是 前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 函数的情况
然后去看看 n1这个函数
然后发现是读取里面的数据
我们看一下n2
一堆的数据操作 其实不难猜出来 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("**************")
然后就是逆向数据了
然后写出脚本
# -*- 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 里面搜索 发现了这个
I have a male fish and a female fish
分析了一下 这个就是key
twofish 当时我做过一道题目
是关于这个算法的 当时那个题目是有解密函数 但是因为这个算法 让我感觉到很好玩
然后就记得了 试了一下 解密一下
# -*- 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层
就是读取flag 文件里面的数据 和做比较
然后去分析so文件,,,
我有一个好习惯 就是 看so层的时候我一般会先看看load这个函数的代码,。。 我发现了这个
重头戏来了。。。 接下来怎么分析
这里 恐怕就要 撸一下arm 指令了
可以看出 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;
}
也就是说,,, 这个函数只要大于等于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
首先把这个文件给一下版本和压缩标志位
发现出来了两个文件夹
其中一个还有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()