攻防世界 reverse pingpong
pingpong XCTF 3rd-BCTF-2017
java层代码很简单:
1 package com.geekerchina.pingpongmachine; 2 3 import android.os.Bundle; 4 import android.support.v7.app.AppCompatActivity; 5 import android.view.Menu; 6 import android.view.MenuItem; 7 import android.view.View$OnClickListener; 8 import android.view.View; 9 import android.widget.TextView; 10 11 public class MainActivity extends AppCompatActivity { 12 class com.geekerchina.pingpongmachine.MainActivity$1 implements View$OnClickListener { 13 com.geekerchina.pingpongmachine.MainActivity$1(MainActivity arg1) { 14 MainActivity.this = arg1; 15 super(); 16 } 17 18 public void onClick(View arg7) { 19 if(MainActivity.this.tt % 2 == 1) { 20 MainActivity.this.p = 0; 21 MainActivity.this.num = 0; 22 MainActivity.this.tt = MainActivity.this.ttt; 23 } 24 25 --MainActivity.this.tt; 26 MainActivity.this.p = MainActivity.this.ping(MainActivity.this.p, MainActivity.this.num); 27 ++MainActivity.this.num; 28 if(MainActivity.this.num >= 7) { 29 MainActivity.this.num = 0; 30 } 31 32 View v0 = MainActivity.this.findViewById(0x7F0B0056); 33 ((TextView)v0).setText("PING"); 34 if(MainActivity.this.tt == 0) { 35 ((TextView)v0).setText("FLAG: BCTF{MagicNum" + Integer.toString(MainActivity.this.p) + "}"); 36 } 37 } 38 } 39 40 class com.geekerchina.pingpongmachine.MainActivity$2 implements View$OnClickListener { 41 com.geekerchina.pingpongmachine.MainActivity$2(MainActivity arg1) { 42 MainActivity.this = arg1; 43 super(); 44 } 45 46 public void onClick(View arg7) { 47 if(MainActivity.this.tt % 2 == 0) { 48 MainActivity.this.p = 0; 49 MainActivity.this.num = 0; 50 MainActivity.this.tt = MainActivity.this.ttt; 51 } 52 53 --MainActivity.this.tt; 54 MainActivity.this.p = MainActivity.this.pong(MainActivity.this.p, MainActivity.this.num); 55 ++MainActivity.this.num; 56 if(MainActivity.this.num >= 7) { 57 MainActivity.this.num = 0; 58 } 59 60 View v0 = MainActivity.this.findViewById(0x7F0B0056); 61 ((TextView)v0).setText("PONG"); 62 if(MainActivity.this.tt == 0) { 63 ((TextView)v0).setText("FLAG: BCTF{MagicNum" + Integer.toString(MainActivity.this.p) + "}"); 64 } 65 } 66 } 67 68 View$OnClickListener jping; 69 View$OnClickListener jpong; 70 public int num; 71 public int p; 72 public int tt; 73 public int ttt; 74 75 static { 76 System.loadLibrary("pp"); 77 } 78 79 public MainActivity() { 80 super(); 81 this.p = 0; 82 this.num = 0; 83 this.ttt = 1000000; 84 this.tt = this.ttt; 85 this.jping = new com.geekerchina.pingpongmachine.MainActivity$1(this); 86 this.jpong = new com.geekerchina.pingpongmachine.MainActivity$2(this); 87 } 88 89 protected void onCreate(Bundle arg4) { 90 super.onCreate(arg4); 91 this.setContentView(0x7F04001B); 92 this.findViewById(0x7F0B0057).setOnClickListener(this.jping); 93 this.findViewById(0x7F0B0058).setOnClickListener(this.jpong); 94 } 95 96 public boolean onCreateOptionsMenu(Menu arg3) { 97 this.getMenuInflater().inflate(0x7F0D0000, arg3); 98 return 1; 99 } 100 101 public boolean onOptionsItemSelected(MenuItem arg3) { 102 boolean v1 = arg3.getItemId() == 0x7F0B0070 ? true : super.onOptionsItemSelected(arg3); 103 return v1; 104 } 105 106 public native int ping(int arg1, int arg2) { 107 } 108 109 public native int pong(int arg1, int arg2) { 110 } 111 }
有两个按钮,分别调用natice层 ping方法、pong方法
先随便点一个,然后先ping 后pong,总共点击1000000次后输出flag
libpp.so 中的方法ping、pong中都有调用sleep(1) ,我们需要修改so文件,将其参数设为0
网上的一些wp都是新建个工程,然后调用so中方法。
那我们直接使用frida调用不就好了。
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 jscode = """ 11 setImmediate(function () { 12 Java.perform(function () { 13 console.log("start"); 14 //so层hook 15 //导出函数 16 //var exports = Module.enumerateExportsSync("libpp.so"); 17 //for(var i=0;i<exports.length;i++){ 18 // send("name:"+exports[i].name+" address:"+exports[i].address); 19 // } 20 21 //遍历模块找基址 22 Process.enumerateModules({ 23 onMatch: function (exp) { 24 if (exp.name == 'libpp.so') { 25 send('enumerateModules find'); 26 send(exp.name + "|" + exp.base + "|" + exp.size + "|" + exp.path); 27 send(exp); 28 return 'stop'; 29 } 30 }, 31 onComplete: function () { 32 send('enumerateModules stop'); 33 } 34 }); 35 36 //通过模块名直接查找基址 37 var soAddr = Module.findBaseAddress("libpp.so"); 38 send("soAddr:" + soAddr); 39 40 var aping=0x1308+1 41 var apong=0x1564+1 42 // hook导出函数 通过函数名 43 44 var fping=Module.findExportByName("libpp.so", "Java_com_geekerchina_pingpongmachine_MainActivity_ping") 45 send("findExportByName ping():" +fping ); 46 fping=new NativePointer(soAddr).add(aping); 47 //NativePointer 简写ptr 48 send("findExportByName ping():" +fping ); 49 var ping=new NativeFunction(fping, "int", ['pointer','pointer','int', 'int']); 50 51 52 //send("findExportByName edit():"+Module.findExportByName("libpp.so", "_ZL4editP7_JNIEnvP8_jobjecti")) 53 // Interceptor.attach(fping, { 54 // onEnter: function (args) { 55 // send("ping() began p:" + args[2] + ", num:" + args[3] ); 56 // }, 57 // onLeave: function (retval) { 58 // send("ping() return:" + retval); 59 // } 60 // }); 61 62 // hook导出函数 通过函数名 63 var fpong=Module.findExportByName("libpp.so", "Java_com_geekerchina_pingpongmachine_MainActivity_pong") 64 send("findExportByName pong():" +fpong ); 65 fpong=new NativePointer(soAddr).add(apong); 66 send("findExportByName pong():" +fpong ); 67 var pong=new NativeFunction(fpong, "int", ['pointer','pointer','int', 'int']); 68 //send("findExportByName edit():"+Module.findExportByName("libpp.so", "_ZL4editP7_JNIEnvP8_jobjecti")) 69 // Interceptor.attach(fpong, { 70 // onEnter: function (args) { 71 // send("pong() began p:" + args[2] + ", num:" + args[3] ); 72 // }, 73 // onLeave: function (retval) { 74 // send("pong() return:" + retval); 75 // } 76 // }); 77 var env = Java.vm.getEnv(); 78 var obj=ptr(0); 79 var check = 1000000; 80 var beFlag = 0; 81 var num = 0; 82 while (true) { //下面这部分代码参考 https://blog.csdn.net/jasalee/article/details/70242837 83 if (check % 2 == 1) { 84 --check; 85 beFlag = pong(env,obj,beFlag,num); 86 ++num; 87 if(num >= 7) { 88 num = 0; 89 } 90 } else { 91 --check; 92 beFlag = ping(env,obj,beFlag,num); 93 ++num; 94 if(num >= 7){ 95 num = 0; 96 } 97 } 98 if (check == 0) { 99 send("check:"+check+" num:"+num) 100 send("FLAG : "+"BCTF{MagicNum" + beFlag+ "}"); 101 break; 102 } 103 } 104 105 }); 106 }); 107 """ 108 109 110 # 运行中hook 111 process = frida.get_usb_device().attach('com.geekerchina.pingpongmachine') 112 script = process.create_script(jscode) 113 script.on('message', on_message) 114 print('[*] Running test') 115 script.load() 116 sys.stdin.read() 117 118 119 ''' 120 [*] Running test 121 start 122 [*] enumerateModules find 123 [*] libpp.so|0xd4c48000|24576|/data/app/com.geekerchina.pingpongmachine-6gshbHpfeBmTBFRYBxQpNg==/lib/arm/libpp.so 124 [*] {'name': 'libpp.so', 'base': '0xd4c48000', 'size': 24576, 'path': '/data/app/com.geekerchina.pingpongmachine-6gshbHpfeBmTBFRYBxQpNg==/lib/arm/libpp.so'} 125 [*] enumerateModules stop 126 [*] soAddr:0xd4c48000 127 [*] findExportByName ping():0xd34c9309 128 [*] findExportByName ping():0xd4c49309 129 [*] findExportByName pong():0xd34c9565 130 [*] findExportByName pong():0xd4c49565 131 [*] check:0 num:1 132 [*] FLAG : BCTF{MagicNum4500009} 133 '''
大约要跑4、5分钟的样子,没去分析ping、pong方法,大佬们可以分析一波 0.0
BCTF{MagicNum4500009}
脚本编写中也发现了一个问题:
Module.findExportByName 得到的地址不正确。
应该使用 基地址+函数偏移地址(thumb指令下偏移地址+1)