android-app-100  suctf-2016

jeb启动,找到点击事件:

验证流程:

输入作为参数 --> processObjectArrayFromNative 得到一返回值(ret_a) --> IsCorrect 返回0,失败;返回1,成功 --> 输出"Sharif_CTF("+md5(str(d+ret_a)+” “+”)“      (.d = 0x1BEBE)

可以发现flag的获取关键在于processObjectArrayFromNative 的返回值。

 1 public void onClick(View arg8) {
2 new String(" ");
3 String v0 = this.a.b.getText().toString();
4 Log.v("EditText", this.a.b.getText().toString());
5 new String("");
6 int v1 = this.a.processObjectArrayFromNative(v0);
7 int v2 = this.a.IsCorrect(v0);
8 v0 = String.valueOf(this.a.d + v1) + " ";
9 try {
10 MessageDigest v1_1 = MessageDigest.getInstance("MD5");
11 v1_1.update(v0.getBytes());
12 byte[] v1_2 = v1_1.digest();
13 StringBuffer v3 = new StringBuffer();
14 int v0_2;
15 for(v0_2 = 0; v0_2 < v1_2.length; ++v0_2) {
16 v3.append(Integer.toString((v1_2[v0_2] & 0xFF) + 0x100, 16).substring(1));
17 }
18
19 if(v2 == 1 && this.a.e != "unknown") {
20 this.a.c.setText("Sharif_CTF(" + v3.toString() + ")");
21 }
22
23 if(v2 == 1 && this.a.e == "unknown") {
24 this.a.c.setText("Just keep Trying :-)");
25 }
26
27 if(v2 == 0) {
28 this.a.c.setText("Just keep Trying :-)");
29 }
30
31 return;
32 }
33 catch(NoSuchAlgorithmException v0_1) {
34 v0_1.printStackTrace();
35 return;
36 }
37 }

程序有两个native方法:

public native int IsCorrect(String arg1)

public native int processObjectArrayFromNative(String arg1)

IDA启动,

发现有混淆,但我们还是能发现这两个native方法中调用了strcmp方法

Java_com_example_ctf2_MainActivity_processObjectArrayFromNative:

 1 ptr_chars = (env_2->functions->GetStringUTFChars)(env_2, jstring_2, 0);
2 *p_chars = ptr_chars;
3 temp_chars_ptr = *p_chars;
4 v46 = &v8;
5 v51 = 101;
6 v8 = 926246501;
7 v52 = 53;
8 v45 = 55;
9 v9 = 102;
10 v10 = 51;
11 v11 = 102;
12 v12 = 101;
13 v13 = 51;
14 v44 = 99;
15 v14 = 99;
16 v15 = 102;
17 v16 = 54;
18 v17 = 48;
19 v18 = 51;
20 v19 = 99;
21 v20 = 48;
22 v21 = 51;
23 v22 = 56;
24 v23 = 57;
25 v24 = 48;
26 v25 = 101;
27 v26 = 101;
28 v27 = 53;
29 v28 = 56;
30 v29 = 56;
31 v30 = 56;
32 v31 = 55;
33 v32 = 56;
34 v33 = 99;
35 v34 = 48;
36 v35 = 101;
37 v36 = 99;
38 v50_2 = v50;
39 v38 = 53;
40 v5 = j_strcmp(temp_chars_ptr, &v8);

processObjectArrayFromNative方法返回值:0或者0x57cbbd2

Java_com_example_ctf2_MainActivity_IsCorrect方法内也进行了字符串比较,

通过脚本我们可以获取到进行比较的字符串:

 1 v51 = 'e';
2 v8 = '75fe'[::-1];
3 v52 = '5';
4 v45 = '7';
5 v9 = 'f';
6 v10 = '3';
7 v11 = 'f';
8 v12 = 'e';
9 v13 = '3';
10 v44 = 'c';
11 v14 = 'c';
12 v15 = 'f';
13 v16 = '6';
14 v17 = '0';
15 v18 = '3';
16 v19 = 'c';
17 v20 = '0';
18 v21 = '3';
19 v22 = '8';
20 v23 = '9';
21 v24 = '0';
22 v25 = 'e';
23 v26 = 'e';
24 v27 = '5';
25 v28 = '8';
26 v29 = '8';
27 v30 = '8';
28 v31 = '7';
29 v32 = '8';
30 v33 = 'c';
31 v34 = '0';
32 v35 = 'e';
33 v36 = 'c';
34 x=''
35 for i in range(8,37):
36 x+=locals()['v'+str(i)]
37 print(x)
38 print(len(x))
39
40 v12 = 101;
41 v13 = 102;
42 v14 = 53;
43 v15 = 55;
44 v16 = 102;
45 v17 = 51;
46 v18 = 102;
47 v19 = 101;
48 v20 = 51;
49 v21 = 99;
50 v22 = 102;
51 v23 = 54;
52 v24 = 48;
53 v25 = 51;
54 v26 = 99;
55 v27 = 48;
56 v28 = 51;
57 v29 = 56;
58 v30 = 57;
59 v31 = 48;
60 v32 = 101;
61 v33 = 101;
62 v34 = 53;
63 v35 = 56;
64 v36 = 56;
65 v37 = 56;
66 v38 = 55;
67 v39 = 56;
68 v40 = 99;
69 v41 = 48;
70 v42 = 101;
71 v43 = 99;
72
73 y=''
74 for i in range(12,44):
75 y+=chr(locals()['v'+str(i)])
76 print(y)
77 print(len(y))
78
79
80 '''
81 ef57f3fe3cf603c03890ee588878c0ec
82 32
83 ef57f3fe3cf603c03890ee588878c0ec
84 32
85 '''

ef57f3fe3cf603c03890ee588878c0ec

运行adb命令输入到编辑框

adb shell input text ef57f3fe3cf603c03890ee588878c0ec

当然也可以静态获取:

1 ret_a=0x57CBBD2
2 d=0x1BEBE
3 d=str(d+ret_a)+' '
4 print(d)
5 import hashlib
6 m=hashlib.md5(d.encode()).hexdigest()
7 print('Sharif_CTF('+m+')')

Sharif_CTF(833489ef285e6fa80690099efc5d9c9d)

(一开始还原算法时得到的结果不对,又写了个frida脚本验证,返回值没问题,后来才发现要md5的字符串忘了加空格 0.0)

frida脚本:

  1 import frida, sys
2
3
4 def on_message(message, data):
5 if message['type'] == 'send':
6 print("[*] {0}".format(message['payload']))
7 else:
8 print(message)
9
10
11 jscode = """
12 setImmediate(function () {
13 Java.perform(function () {
14 console.log("start");
15 //so层hook
16 //导出函数
17 //var exports = Module.enumerateExportsSync("libadnjni.so");
18 //for(var i=0;i<exports.length;i++){
19 // send("name:"+exports[i].name+" address:"+exports[i].address);
20 // }
21 var str = Java.use("java.lang.String");
22 //遍历模块找基址
23 // Process.enumerateModules({
24 // onMatch: function (exp) {
25 // if (exp.name == 'libadnjni.so') {
26 // send('enumerateModules find');
27 // send(exp.name + "|" + exp.base + "|" + exp.size + "|" + exp.path);
28 // send(exp);
29 // return 'stop';
30 // }
31 // },
32 // onComplete: function () {
33 // send('enumerateModules stop');
34 // }
35 // });
36
37 //通过模块名直接查找基址
38 var soAddr = Module.findBaseAddress("libadnjni.so");
39 send("soAddr:" + soAddr);
40
41 var parray=0x48c+1;
42 var pcorrect=0x74c+1;
43 // hook导出函数 通过函数名
44
45 //Module.findExportByName 找到的函数地址无效
46 // var farray=Module.findExportByName("libadnjni.so", "Java_com_example_ctf2_MainActivity_processObjectArrayFromNative")
47 // send("findExportByName farray() by Module.findExportByName:" +farray);
48 var farray=new NativePointer(soAddr).add(parray);
49 //NativePointer 简写ptr
50 send("findExportByName farray() by ptr:" +farray );
51
52 Interceptor.attach(farray, {
53 onEnter: function (args) {
54 var s = Java.cast(args[2], str);
55 send("array() jstring:" + s );
56 },
57 onLeave: function (retval) {
58 send("array() return:" + retval);
59 }
60 });
61
62 // hook导出函数 通过函数名
63 // var fcorrect=Module.findExportByName("libadnjni.so", "Java_com_example_ctf2_MainActivity_IsCorrect");
64 // send("findExportByName correct() by Module.findExportByName:" +fcorrect );
65 var fcorrect=new NativePointer(soAddr).add(pcorrect);
66 send("findExportByName correct() by ptr:" +fcorrect );
67 Interceptor.attach(fcorrect, {
68 onEnter: function (args) {
69 var s = Java.cast(args[2], str);
70 send("fcorrect() jstring:" + s );
71 },
72 onLeave: function (retval) {
73 send("fcorrect() return:" + retval);
74 }
75 });
76
77 });
78 });
79 """
80 # print(jscode)
81
82 # 启动时hook
83 # devices=frida.get_usb_device()
84 # pid=devices.spawn(['com.example.goal'])
85 # session=devices.attach(pid)
86 # devices.resume(pid) #创建完脚本, 恢复进程运行
87 # script=session.create_script(jscode)
88
89 # 命令行frida -U -f com.example.goal --no-pause -l <hook.js>
90
91 # 运行中hook
92 process = frida.get_usb_device().attach('com.example.ctf2')
93 script = process.create_script(jscode)
94 script.on('message', on_message)
95 print('[*] Running test')
96 script.load()
97 sys.stdin.read()
98
99 # ef57f3fe3cf603c03890ee588878c0ec
100
101 '''
102 [*] Running test
103 start
104 [*] soAddr:0xcd562000
105 [*] findExportByName farray() by ptr:0xcd56248d
106 [*] findExportByName correct() by ptr:0xcd56274d
107 [*] array() jstring:Serial Number
108 [*] array() return:0x0
109 [*] fcorrect() jstring:Serial Number
110 [*] fcorrect() return:0x0
111
112
113 [*] array() jstring:ef57f3fe3cf603c03890ee588878c0ec
114 [*] array() return:0x57cbbd2
115 [*] fcorrect() jstring:ef57f3fe3cf603c03890ee588878c0ec
116 [*] fcorrect() return:0x1
117 '''

攻防世界 reverse android-app-100的更多相关文章

  1. 攻防世界 reverse 进阶 10 Reverse Box

    攻防世界中此题信息未给全,题目来源为[TWCTF-2016:Reverse] Reverse Box 网上有很多wp是使用gdb脚本,这里找到一个本地还原关键算法,然后再爆破的 https://www ...

  2. 攻防世界 reverse evil

    这是2017 ddctf的一道逆向题, 挑战:<恶意软件分析> 赛题背景: 员工小A收到了一封邮件,带一个文档附件,小A随手打开了附件.随后IT部门发现小A的电脑发出了异常网络访问请求,进 ...

  3. 攻防世界 reverse tt3441810

    tt3441810 tinyctf-2014 附件给了一堆数据,将十六进制数据部分提取出来, flag应该隐藏在里面,(这算啥子re,) 保留可显示字符,然后去除填充字符(找规律 0.0) 处理脚本: ...

  4. 攻防世界 reverse 进阶 APK-逆向2

    APK-逆向2 Hack-you-2014 (看名以为是安卓逆向呢0.0,搞错了吧) 程序是.net写的,直接祭出神器dnSpy 1 using System; 2 using System.Diag ...

  5. 攻防世界 reverse pingpong

    pingpong  XCTF 3rd-BCTF-2017 java层代码很简单: 1 package com.geekerchina.pingpongmachine; 2 3 import andro ...

  6. 攻防世界 reverse BabyXor

    BabyXor     2019_UNCTF 查壳 脱壳 dump 脱壳后 IDA静态分析 int main_0() { void *v0; // eax int v1; // ST5C_4 char ...

  7. 攻防世界 reverse 进阶 8-The_Maya_Society Hack.lu-2017

    8.The_Maya_Society Hack.lu-2017 在linux下将时间调整为2012-12-21,运行即可得到flag. 下面进行分析 1 signed __int64 __fastca ...

  8. 攻防世界 reverse Windows_Reverse2

    Windows_Reverse2   2019_DDCTF 查壳: 寻找oep-->dump-->iat修复   便可成功脱壳 int __cdecl main(int argc, con ...

  9. 攻防世界 reverse Replace

    Replace 湖湘杯2018 查壳upx,手动脱壳,修复IAT,去掉重定向便可以运行. ida查看,流程清晰.关键函数check_E51090. int __cdecl main(int argc, ...

  10. 攻防世界 reverse 流浪者

    流浪者 int __thiscall sub_401890(CWnd *this) { struct CString *v1; // ST08_4 CWnd *v2; // eax int v3; / ...

随机推荐

  1. openssl的用法

    Openssl详细用法: OpenSSL 是一个开源项目,其组成主要包括一下三个组件: openssl:多用途的命令行工具 libcrypto:加密算法库 libssl:加密模块应用库,实现了ssl及 ...

  2. Apple Watch Series 6 字母图案 (图解教程)

    Apple Watch Series 6 字母图案 (图解教程) Apple Watch Series 6 自定义文字 如何开启 字母图案 solution 1 选择 彩色 表盘️ PS: 该复杂功能 ...

  3. Django : Security in Django

    Security in Django https://docs.djangoproject.com/en/1.10/topics/security/ 1 Cross site scripting (X ...

  4. ES6 Arrow Function All In One

    ES6 Arrow Function All In One this const log = console.log; const arrow_func = (args) => log(`arg ...

  5. Python Lambda & Functional Programming

    Python Lambda & Functional Programming 函数式编程 匿名函数 纯函数 高阶函数 # higher-order functions def apply_tw ...

  6. Microsoft Solitaire Collection

    Microsoft Solitaire Collection game https://zone.msn.com/gameplayer/gameplayerHTML.aspx?game=mssolit ...

  7. Ethical Hacking Tutorials

    Ethical Hacking Tutorials Free Ethical Hacking Tutorials https://www.guru99.com/ethical-hacking-tuto ...

  8. web hack & web security

    web hack & web security https://www.hacksplaining.com/lessons https://www.hacksplaining.com/ OK ...

  9. Flutter: AnimatedList 一个滚动容器,可在插入或移除项目时为其设置动画

    Flutter Widget of the Week import 'dart:math'; import 'package:flutter/material.dart'; void main() = ...

  10. redis源码之SDS

    1:SDS介绍 我们在redis中执行命令 set key name 的时候,key和name都是字符串类型,而且字符串(string)在redis中是会经常用到的类型,那redis是如何保存字符串的 ...