From 090e4447414d00c70a8d7b4be1fcabd08c6d4801 Mon Sep 17 00:00:00 2001 From: Pedro Diaz Date: Thu, 29 Sep 2016 08:32:04 -0400 Subject: [PATCH] Reworking Mitm --- .../snorlax/module/SnorlaxModule.java | 11 ++++++ .../snorlax/module/feature/mitm/Mitm.java | 14 ++++--- .../module/feature/mitm/MitmInputStream.java | 7 ++-- .../feature/mitm/MitmInputStreamFactory.java | 37 +++++++++++++++++++ .../module/feature/mitm/MitmOutputStream.java | 8 ++-- .../feature/mitm/MitmOutputStreamFactory.java | 37 +++++++++++++++++++ .../module/feature/mitm/MitmProvider.java | 33 +++++++++-------- 7 files changed, 119 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmInputStreamFactory.java create mode 100644 app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmOutputStreamFactory.java diff --git a/app/src/main/java/com/icecream/snorlax/module/SnorlaxModule.java b/app/src/main/java/com/icecream/snorlax/module/SnorlaxModule.java index 60225ac..19370da 100644 --- a/app/src/main/java/com/icecream/snorlax/module/SnorlaxModule.java +++ b/app/src/main/java/com/icecream/snorlax/module/SnorlaxModule.java @@ -16,9 +16,12 @@ package com.icecream.snorlax.module; +import java.util.List; + import javax.inject.Singleton; import android.app.Application; +import android.util.LongSparseArray; import com.icecream.snorlax.module.feature.mitm.MitmRelay; @@ -26,6 +29,8 @@ import dagger.Provides; import de.robv.android.xposed.XSharedPreferences; +import static POGOProtos.Networking.Requests.RequestOuterClass.Request; + @Module final class SnorlaxModule { @@ -59,4 +64,10 @@ Application provideAppliction() { MitmRelay provideMitmRelay() { return MitmRelay.getInstance(); } + + @Provides + @Singleton + LongSparseArray> provideLongSparseArray() { + return new LongSparseArray<>(); + } } diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/Mitm.java b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/Mitm.java index c893e7e..32d7229 100644 --- a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/Mitm.java +++ b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/Mitm.java @@ -34,36 +34,38 @@ public final class Mitm implements Feature { private final ClassLoader mClassLoader; + private final MitmInputStreamFactory mMitmInputStreamFactory; + private final MitmOutputStreamFactory mMitmOutputStreamFactory; private XC_MethodHook.Unhook mUnhookInputStream; private XC_MethodHook.Unhook mUnhookOutputStream; @Inject - Mitm(ClassLoader classLoader) { + Mitm(ClassLoader classLoader, MitmInputStreamFactory mitmInputStreamFactory, MitmOutputStreamFactory mitmOutputStreamFactory) { mClassLoader = classLoader; + mMitmInputStreamFactory = mitmInputStreamFactory; + mMitmOutputStreamFactory = mitmOutputStreamFactory; } @Override public void subscribe() throws Exception { final Class http = XposedHelpers.findClass(getHttpUrlConnection(), mClassLoader); if (http == null) { - Log.e("Cannot find HttpsURLConnection class"); + Log.e("Cannot find HttpURLConnection implementation class"); return; } mUnhookInputStream = XposedHelpers.findAndHookMethod(http, "getInputStream", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { - // TODO factory - param.setResult(new MitmInputStream((InputStream) param.getResult())); + param.setResult(mMitmInputStreamFactory.create((InputStream) param.getResult())); } }); mUnhookOutputStream = XposedHelpers.findAndHookMethod(http, "getOutputStream", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { - // TODO factory - param.setResult(new MitmOutputStream((OutputStream) param.getResult())); + param.setResult(mMitmOutputStreamFactory.create((OutputStream) param.getResult())); } }); } diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmInputStream.java b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmInputStream.java index d57972d..47ac1b9 100644 --- a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmInputStream.java +++ b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmInputStream.java @@ -26,11 +26,12 @@ final class MitmInputStream extends InputStream { private static final int sAverageSize = 4096; - + private final MitmProvider mMitmProvider; private boolean mMitmDone; private ByteBuffer mByteBuffer; - MitmInputStream(InputStream inputStream) { + MitmInputStream(InputStream inputStream, MitmProvider mitmProvider) { + mMitmProvider = mitmProvider; mMitmDone = false; if (inputStream == null) { @@ -95,7 +96,7 @@ private void mitmStream() { if (mMitmDone) return; - ByteBuffer fromMitm = MitmProvider.processInboundPackage( + ByteBuffer fromMitm = mMitmProvider.processInboundPackage( mByteBuffer.asReadOnlyBuffer(), mByteBuffer.hasRemaining() ); diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmInputStreamFactory.java b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmInputStreamFactory.java new file mode 100644 index 0000000..0595ab2 --- /dev/null +++ b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmInputStreamFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016. Pedro Diaz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.icecream.snorlax.module.feature.mitm; + +import java.io.InputStream; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +final class MitmInputStreamFactory { + + private final MitmProvider mMitmProvider; + + @Inject + MitmInputStreamFactory(MitmProvider mitmProvider) { + mMitmProvider = mitmProvider; + } + + MitmInputStream create(InputStream inputStream) { + return new MitmInputStream(inputStream, mMitmProvider); + } +} diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmOutputStream.java b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmOutputStream.java index ad0edba..a439127 100644 --- a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmOutputStream.java +++ b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmOutputStream.java @@ -23,11 +23,13 @@ final class MitmOutputStream extends ByteArrayOutputStream { - private final OutputStream mOutputStream; + private final MitmProvider mMitmProvider; + private OutputStream mOutputStream; - MitmOutputStream(OutputStream outputStream) { + MitmOutputStream(OutputStream outputStream, MitmProvider mitmProvider) { super(2048); mOutputStream = outputStream; + mMitmProvider = mitmProvider; } @Override @@ -43,7 +45,7 @@ public void close() throws IOException { @SuppressWarnings("unused") private void mitmStream() { - ByteBuffer fromMitm = MitmProvider.processOutboundPackage( + ByteBuffer fromMitm = mMitmProvider.processOutboundPackage( ByteBuffer.wrap(buf, 0, count).asReadOnlyBuffer(), mOutputStream != null ); diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmOutputStreamFactory.java b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmOutputStreamFactory.java new file mode 100644 index 0000000..fb565c1 --- /dev/null +++ b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmOutputStreamFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016. Pedro Diaz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.icecream.snorlax.module.feature.mitm; + +import java.io.OutputStream; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +final class MitmOutputStreamFactory { + + private final MitmProvider mMitmProvider; + + @Inject + MitmOutputStreamFactory(MitmProvider mitmProvider) { + mMitmProvider = mitmProvider; + } + + MitmOutputStream create(OutputStream outputStream) { + return new MitmOutputStream(outputStream, mMitmProvider); + } +} diff --git a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmProvider.java b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmProvider.java index acb3ec0..5fa1621 100644 --- a/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmProvider.java +++ b/app/src/main/java/com/icecream/snorlax/module/feature/mitm/MitmProvider.java @@ -19,6 +19,9 @@ import java.nio.ByteBuffer; import java.util.List; +import javax.inject.Inject; +import javax.inject.Singleton; + import android.util.LongSparseArray; import com.google.protobuf.ByteString; @@ -38,15 +41,17 @@ import static POGOProtos.Networking.Responses.GetInventoryResponseOuterClass.GetInventoryResponse; import static android.R.attr.id; +@Singleton final class MitmProvider { - static { - sRequests = new LongSparseArray<>(); - } + private final LongSparseArray> mRequests; - private static LongSparseArray> sRequests; + @Inject + MitmProvider(LongSparseArray> requests) { + mRequests = requests; + } - static ByteBuffer processOutboundPackage(ByteBuffer roData, boolean connectionOk) { + ByteBuffer processOutboundPackage(ByteBuffer roData, boolean connectionOk) { if (!connectionOk) return null; @@ -72,14 +77,14 @@ static ByteBuffer processOutboundPackage(ByteBuffer roData, boolean connectionOk return null; } - private static void processOutBuffer(RequestEnvelope envelope) { - sRequests.put( + private void processOutBuffer(RequestEnvelope envelope) { + mRequests.put( envelope.getRequestId(), envelope.getRequestsList() ); } - static ByteBuffer processInboundPackage(ByteBuffer roData, boolean connectionOk) { + ByteBuffer processInboundPackage(ByteBuffer roData, boolean connectionOk) { if (!connectionOk) return null; @@ -109,8 +114,8 @@ static ByteBuffer processInboundPackage(ByteBuffer roData, boolean connectionOk) return null; } - private static ByteBuffer processInBuffer(ResponseEnvelope envelope) throws InvalidProtocolBufferException { - List requests = sRequests.get(envelope.getRequestId()); + private ByteBuffer processInBuffer(ResponseEnvelope envelope) throws InvalidProtocolBufferException { + List requests = mRequests.get(envelope.getRequestId()); if (requests == null) { return null; @@ -129,7 +134,7 @@ private static ByteBuffer processInBuffer(ResponseEnvelope envelope) throws Inva } } } - sRequests.remove(id); + mRequests.remove(id); if (!isDone) { return null; @@ -138,7 +143,7 @@ private static ByteBuffer processInBuffer(ResponseEnvelope envelope) throws Inva return ByteBuffer.wrap(envelope.toByteArray()); } - private static ByteString processInventoryResponse(GetInventoryResponse response) { + private ByteString processInventoryResponse(GetInventoryResponse response) { if (!response.getSuccess() || !response.hasInventoryDelta()) { return null; } @@ -177,8 +182,4 @@ private static ByteString processInventoryResponse(GetInventoryResponse response return null; } - - private MitmProvider() { - throw new AssertionError("No instances"); - } }