Play商店
奇怪的store
APK
程式碼
編譯
執行檔
一般流程
逆向
(被壓縮的檔案)
bytecode
資源
(原生的檔案)
apktool d <file.apk> -o <dir>
apktool d helloworld.apk -o ./helloworld
<?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>
是應用程式中最優先被執行的Activity
B---byte
C---char
D---double
F---float
I---int
J---long
S---short
V---void
Z---boolean
[XXX---array
Lxxx/yyy---object
disassemble
assemble
Smali
foo ()V
void foo()
foo (III)Z
foo (Z[I[ILjava/lang/String;J)Ljava/lang/String
boolean foo(int, int, int)
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
他就是Flag
ctrl + shift + p
Open
Sublime
smali
打包完的apk會放在dist底下
apktool b <dir> -o <*.apk>
apktool b ./Helloworld -o ./NISRA.apk
keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
jarsigner -verbose -keystore demo.keystore Helloworld.apk demo.keystore
keytool
-genkey 產生key
-alias 別名
-keystore 指定keystroe名字
-keyalg 密鑰算法
-validity 有效天數
jarsigner
- verbose 詳細輸出
- keystore 證書儲存路徑
.line 12
.local v0, "password":Ljava/lang/String;
invoke-virtual {p0, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
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);
//dismass.ogg.weatherwax.aching.nitt.garlick
}
return "NOPE";
}
}
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;
move-result-object v0
.line 20
.local v0, "flag":Ljava/lang/String;
return-object v0
.end method
public static String getFlag(String input, Context ctx) {
String str = "aaa";
StringBuilder ace = new StringBuilder(str);
StringBuilder jack = new StringBuilder(str);
StringBuilder queen = new StringBuilder(str);
StringBuilder king = new StringBuilder(str);
ace.setCharAt(0, (char) (ace.charAt(0) + 4));
ace.setCharAt(1, (char) (ace.charAt(1) + 19));
ace.setCharAt(2, (char) (ace.charAt(2) + 18));
jack.setCharAt(0, (char) (jack.charAt(0) + 7));
jack.setCharAt(1, (char) (jack.charAt(1) + 0));
jack.setCharAt(2, (char) (jack.charAt(2) + 1));
queen.setCharAt(0, (char) (queen.charAt(0) + 0));
queen.setCharAt(1, (char) (queen.charAt(1) + 11));
queen.setCharAt(2, (char) (queen.charAt(2) + 15));
king.setCharAt(0, (char) (king.charAt(0) + 14));
king.setCharAt(1, (char) (king.charAt(1) + 20));
king.setCharAt(2, (char) (king.charAt(2) + 15));
if (input.equals("".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString()))) {
return "call it";
}
return "NOPE";
}
Text
public static String getFlag(String input, Context ctx) {
String str = "aaa";
StringBuilder ace = new StringBuilder(str);
StringBuilder jack = new StringBuilder(str);
StringBuilder queen = new StringBuilder(str);
StringBuilder king = new StringBuilder(str);
ace.setCharAt(0, (char) (a + 4));
ace.setCharAt(1, (char) (a + 19));
ace.setCharAt(2, (char) (a + 18));
jack.setCharAt(0, (char) (a + 7));
jack.setCharAt(1, (char) (a + 0));
jack.setCharAt(2, (char) (a + 1));
queen.setCharAt(0, (char) (a + 0));
queen.setCharAt(1, (char) (a + 11));
queen.setCharAt(2, (char) (a + 15));
king.setCharAt(0, (char) (a + 14));
king.setCharAt(1, (char) (a + 20));
king.setCharAt(2, (char) (a + 15));
if (input.equals("".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString()))) {
return "call it";
}
return "NOPE";
}
print(chr(ord('a') + 0), end='')
print(chr(ord('a') + 11), end='')
print(chr(ord('a') + 15), end='')
print(chr(ord('a') + 7), end='')
print(chr(ord('a') + 0), end='')
print(chr(ord('a') + 1), end='')
print(chr(ord('a') + 4), end='')
print(chr(ord('a') + 19), end='')
print(chr(ord('a') + 18), end='')
print(chr(ord('a') + 14), end='')
print(chr(ord('a') + 20), end='')
print(chr(ord('a') + 15), end='')
# string
alphabetsoup
Text
public static String getFlag(String input, Context ctx) {
String str = "aaa";
StringBuilder ace = new StringBuilder(str);
StringBuilder jack = new StringBuilder(str);
StringBuilder queen = new StringBuilder(str);
StringBuilder king = new StringBuilder(str);
ace.setCharAt(0, (char) (a + 4));
ace.setCharAt(1, (char) (a + 19));
ace.setCharAt(2, (char) (a + 18));
jack.setCharAt(0, (char) (a + 7));
jack.setCharAt(1, (char) (a + 0));
jack.setCharAt(2, (char) (a + 1));
queen.setCharAt(0, (char) (a + 0));
queen.setCharAt(1, (char) (a + 11));
queen.setCharAt(2, (char) (a + 15));
king.setCharAt(0, (char) (a + 14));
king.setCharAt(1, (char) (a + 20));
king.setCharAt(2, (char) (a + 15));
if (input.equals("".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString()))) {
return "call it";
}
return "NOPE";
}
Text
public static String getFlag(String input, Context ctx) {
String str = "aaa";
StringBuilder ace = new StringBuilder(str);
StringBuilder jack = new StringBuilder(str);
StringBuilder queen = new StringBuilder(str);
StringBuilder king = new StringBuilder(str);
ace.setCharAt(0, (char) (a + 4));
ace.setCharAt(1, (char) (a + 19));
ace.setCharAt(2, (char) (a + 18));
jack.setCharAt(0, (char) (a + 7));
jack.setCharAt(1, (char) (a + 0));
jack.setCharAt(2, (char) (a + 1));
queen.setCharAt(0, (char) (a + 0));
queen.setCharAt(1, (char) (a + 11));
queen.setCharAt(2, (char) (a + 15));
king.setCharAt(0, (char) (a + 14));
king.setCharAt(1, (char) (a + 20));
king.setCharAt(2, (char) (a + 15));
if (input.equals("".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString()))) {
return "call it";
}
return "NOPE";
}
invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->cardamom(Ljava/lang/String;)Ljava/lang/String;
move-result-object p0
return-object p0
jarsigner -verbose -keystore demo.keystore Helloworld.apk demo.keystore
jarsigner
- verbose 詳細輸出
- keystore 證書儲存路徑
Dalvik opcodes
Android 反編譯與防止反編譯