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

最新文章

  1. 【BZOJ】1606: [Usaco2008 Dec]Hay For Sale(背包)
  2. 总结Allegro元件封装(焊盘)制作方法[修整]
  3. 15_CXF和Spring开发手机号查询网站
  4. html中显示xml
  5. Java一些八卦集合类
  6. 使用async和wait进行异步编程
  7. 链接了dpdk的进程启动core在 Illegal instruction
  8. Java字节码浅析(二)
  9. 基于iscroll的better-scroll在vue中的使用
  10. java 彻底理解 byte char short int float long double
  11. AndroidManifest.xml文件安全探索
  12. es 配置文件
  13. 【SSH网上商城项目实战06】基于DataGrid的数据显示
  14. less使用总结
  15. NumPy常用函数总结
  16. 配置文件格式用哪个?文件夹+纯文本文件,XML,SQLite
  17. Servlet实现前后端交互的原理及过程解析
  18. iOS 常用工具库LFKit功能介绍
  19. HTML+JavaScript实现链式运动特效
  20. Linux主从同步监测和利用sendMail来发邮件

热门文章

  1. u-boot 移植 ---&gt;4、Tiny210核心板的DDR初始化下详解
  2. μC/OS-III---I笔记8---事件标志
  3. docker部署LNMP架构
  4. Get your site working on Google Search Console , 在 Google Search Console中运行您的网站, Google Search Console
  5. MongoDB 101
  6. auto open Chrome DevTools in the command line
  7. CSS animation &amp; CSS animation 101
  8. svg click event bug &amp; css pointer-events
  9. c++ string与wstring转换
  10. 1060 Are They Equal——PAT甲级真题