我們來分析apk的安裝檔案
我們試著拿解壓縮工具(e.x 7-zip)將apk,看看裡面有甚麼檔案,發現大概的架構如下
我們對配置文件下手,但似乎看不懂,裡面是binary
能夠把 apk 拆包,打包的工具
拆包
apktool d <file.apk> -o <dir>
打包
apktool b <dir> -o <*.apk>
# 生出一把key
keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
# 對apk簽名
jarsigner -verbose -keystore demo.keystore <your_apk> demo.keystore
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloworld">
<application android:allowBackup="true" android:debuggable="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name">
<activity android:label="@string/app_name" android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
MANIFEST.MF
CERT.SF
CERT.RSA
B --- byte
C --- char
D --- double
F --- float
I --- int
J --- long
S --- short
V --- void
Z --- boolean
[XXX --- array
Lxxx/yyy --- object
foo ()V
=> void foo()
foo (III)Z
=> boolean foo(int, int, int)
foo (Z[I[ILjava/lang/String;J)Ljava/lang/String
=> String foo (boolean, int[], int[], String, long)
private:invoke-direct
public, protected: invoke-virtual
static:invoke-static
parent: invoke-super
example: invoke-xxx {參數},Class;->function(type)
# eg.
public static native String fenugreek(String str);
---------------------------------------------------
invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->fenugreek(Ljava/lang/String;)Ljava/lang/String;
move-result-object v1
return-object v1
參考自:https://www.slideshare.net/EnPingHsieh/android-76769248
是個密碼輸入框,我們試著找找
hint:password的位置(res)?
用apktool逆出來的結果,我合理懷疑password放在java/lang/String
.line 12
.local v0, "password":Ljava/lang/String;
invoke-virtual {p0, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
strings.xml
找密碼,恩找到了apktool\one\res\values\strings.xml
public static String getFlag(String input, Context ctx) {
String[] witches = {"weatherwax", "ogg", "garlick", "nitt", "aching", "dismass"};
int second = 3 - 3;
int third = (3 / 3) + second;
int fourth = (third + third) - second;
int fifth = 3 + fourth;
int sixth = (fifth + second) - third;
String str = ".";
if (input.equals("".concat(witches[fifth]).concat(str).concat(witches[third]).concat(str).concat(witches[second]).concat(str).concat(witches[sixth]).concat(str).concat(witches[3]).concat(str).concat(witches[fourth]))) {
return sesame(input);
}
return "NOPE";
}
public class FlagstaffHill {
public static native String sesame(String str);
public static String getFlag(String input, Context ctx) {
// 0 1 2 3 4 5
String[] witches = {"weatherwax", "ogg", "garlick", "nitt", "aching", "dismass"};
int second = 0;
int third = 1;
int fourth = 2;
int fifth = 5;
int sixth = 4;
String str = ".";
if (input.equals("".concat(witches[fifth]).concat(str).concat(witches[third]).concat(str).concat(witches[second]).concat(str).concat(witches[sixth]).concat(str).concat(witches[3]).concat(str).concat(witches[fourth]))) {
return sesame(input);
}
return "NOPE";
}
}
dismass.ogg.weatherwax.aching.nitt.garlick
public class FlagstaffHill {
public static native String cilantro(String str);
public static String nope(String input) {
return "don't wanna";
}
public static String yep(String input) {
return cilantro(input);
}
public static String getFlag(String input, Context ctx) {
return nope(input);
}
}
public class FlagstaffHill {
public static native String cilantro(String str);
public static String getFlag(String input, Context ctx) {
return nope(input); - > yep(input);
}
}
.method public static getFlag(Ljava/lang/String;Landroid/content/Context;)Ljava/lang/String;
.locals 1
.param p0, "input" # Ljava/lang/String;
.param p1, "ctx" # Landroid/content/Context;
.line 19
invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->yep(Ljava/lang/String;)Ljava/lang/String;