攻防世界 reverse android-app-100

 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 ‘‘‘

原文地址:https://www.cnblogs.com/DirWang/p/11579448.html

时间: 2024-11-09 10:07:04

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

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

8.The_Maya_Society Hack.lu-2017 在linux下将时间调整为2012-12-21,运行即可得到flag. 下面进行分析 1 signed __int64 __fastcall main(__int64 a1, char **a2, char **a3) 2 { 3 size_t v3; // rbx 4 size_t v4; // rax 5 unsigned __int64 size; // rax 6 unsigned __int64 size_1; // ra

攻防世界 reverse 进阶 10 Reverse Box

攻防世界中此题信息未给全,题目来源为[TWCTF-2016:Reverse] Reverse Box 网上有很多wp是使用gdb脚本,这里找到一个本地还原关键算法,然后再爆破的 https://www.megabeets.net/twctf-2016-reverse-reverse-box/ [TWCTF-2016:Reverse] Reverse Box Writeup 标准 Shak的客座文章. 挑战描述$ ./reverse_box $ {FLAG} 95eeaf95ef942349995

攻防世界 reverse BabyXor

BabyXor     2019_UNCTF 查壳 脱壳 dump 脱壳后 IDA静态分析 int main_0() { void *v0; // eax int v1; // ST5C_4 char *v2; // ST6C_4 const char *v3; // ST68_4 void *v4; // ST64_4 size_t v5; // eax char *v6; // ST60_4 v0 = (void *)sub_4010B4((int)&unk_4395F0, "世界上

攻防世界 reverse 新手练习区

1.re1 DUTCTF IDA shift+F12 查看字符串 DUTCTF{We1c0met0DUTCTF} 2.game ZSCTF zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t} 3.Hello, CTF  Pediy CTF 2018 CrackMeJustForFun 将16进制字符串转ascii字符串得到flag 4.open-source HackYou CTF 参数 51966 25 h4cky0u flag为:

攻防世界 reverse 流浪者

流浪者 int __thiscall sub_401890(CWnd *this) { struct CString *v1; // ST08_4 CWnd *v2; // eax int v3; // eax int v5[26]; // [esp+4Ch] [ebp-74h] int i; // [esp+B4h] [ebp-Ch] char *Str; // [esp+B8h] [ebp-8h] CWnd *v8; // [esp+BCh] [ebp-4h] v8 = this; v1 =

攻防世界 reverse 进阶5-7

5.re-for-50-plz-50  tu-ctf-2016 流程很简单,异或比较 1 x=list('cbtcqLUBChERV[[[email protected]_X^D]X_YPV[CJ') 2 y=0x37 3 z='' 4 for t in x: 5 z+=chr(ord(t)^y) 6 print(z) TUCTF{but_really_whoisjohngalt} 6.key csaw-ctf-2016-quals 运行后打印完?W?h?a?t h?a?p?p?e?n? 便结束

攻防世界 reverse 进阶 16-zorropub

16.zorropub  nullcon-hackim-2016 (linux平台以后整理) https://github.com/ctfs/write-ups-2016/tree/master/nullcon-hackim-2016/re/zorropub-100 nullcon{nu11c0n_s4yz_x0r1n6_1s_4m4z1ng} 原文地址:https://www.cnblogs.com/DirWang/p/11448008.html

攻防世界 reverse 进阶 15-Reversing-x64Elf-100

15.Reversing-x64Elf-100 这题非常简单, 1 signed __int64 __fastcall sub_4006FD(__int64 a1) 2 { 3 signed int i; // [rsp+14h] [rbp-24h] 4 const char *v3; // [rsp+18h] [rbp-20h] 5 const char *v4; // [rsp+20h] [rbp-18h] 6 const char *v5; // [rsp+28h] [rbp-10h] 7

攻防世界 reverse 2ex1

2ex1 CISCN-2018-Quals mark 1 import base64 2 3 std_base= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 4 mg_base='@,.1fgvw#`/2ehux$~\"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD' 5 6 en_trantab=str.maketrans(std_b