Crack a foreign paid rtmp client and successfully call it on Android and Java

Source: Internet
Author: User

Adboe's red5 Streaming Media Server is free and open-source. It can be used with flash, but the use of Java and Android as client calls is a trigger.

Adobe's red5 Source Code contains an rtmpclient class, which is not complex in use, but cannot be called successfully. Observe the log and find that the connection is closed when the stream is created after the connection is successful. What I can think of is that the current version of the red5 server used by the company may be incompatible with the rtmpclient.

Some domestic users have simplified the rtmpclient of red5 and put it on Google's SVN as an open-source class library. The URL is http://code.google.com/p/android-rtmp-client /. This class library cannot connect to the server.

There is also a paid rtmpclient in foreign countries, with a value of 395 knives. I will not point out the specific website and product name, and you will surely find it. This client library is very powerful and easy to use. I registered a trial key and found that it can be successfully connected to the red5 server and communicate well.

Because I could not find any other method, and I tried to implement the rtmp protocol of red5 myself, this is basically not realistic. So I decomcompiled this class library and found that apart from several portal classes, other classes are all obfuscated.

Among them, the most important classes are netconnection, netstream, and license. Among them, netconnection and netstream are the two classes responsible for creating connections and Callback Server data. The license, as its name implies, is responsible for verifying whether there is any authorization. According to the official instructions, you must call the license. setkey () method to pass in the key obtained for registration before use.

According to the habit of cracking, it is always the first attempt of brute force cracking, that is, bypassing verification. Therefore, comment out the call to the license. setkey () method and throw an exception after running:

Exception inthread "Main" Java. Lang. illegalargumentexception: Your license key isinvalid!

Atcom. smaxe. UV. Client. netconnection. A (unknown source)

Atcom. smaxe. UV. Client. netconnection. B (unknown source)

Atcom. smaxe. UV. Client. netconnection. Connect (unknown source)

Open JD and locate the cononect method of the netconnect class. The Code obtained by decompilation is as follows:

Public void connect (string paramstring, object [] paramarrayofobject)

{

B (k );

Urlinfo localurlinfo = urlinfo. parseurl (paramstring );

Com. smaxe. UV. client. A. E locale = new COM. smaxe. UV. client. A. E ();

Locale. A (this. D );

Locale. A (ilogger) configuration (). Get ("logger "));

This. B = locale;

This. c = new ();

This. b. A (this, this. a. A (localurlinfo. protocol, localurlinfo. host, localurlinfo. port, configuration (), paramstring, localurlinfo. getapp (), this. c, paramarrayofobject );

Super. Connect (paramstring, paramarrayofobject );

}

You will find that the method B (k) is called a little odd. Open the license class. The setkey code is as follows:

Public static void setkey (string paramstring)

{

Netconnection. A (paramstring ));

}

Let's look at the (byte []) method of netconnection as follows:

Static voidA (Byte[] Paramarrayofbyte)

{

If(Paramarrayofbyte =Null) | (Paramarrayofbyte. length! = 25 ))

Return;

K= Paramarrayofbyte;

}

Sure enough, netconnection B () has been used to verify whether it has been authorized. Set "your license key is invalid !" As a pattern, a search is performed once in all files, but the search results cannot be found. After an analysis, I found that the author was very smart. In advance, I encoded this sentence into an ascii code. When I used it, I converted it into a string for output, in this way, the verification cannot be easily located by searching for the signature.

However, it is a pity that the Java compilation feature is that it is too easy to locate the verification code in the brute-force process. The next step is to copy the decompilation code of the entire netconnection to a new file. After finishing the references, I found a bunch of errors. I analyzed that most of them are slightly flawed in JD decompilation, it is easy to modify. However, the Code is as follows: This. a. A (localurlinfo. protocol, localurlinfo. host, localurlinfo. port, configuration (), the error message for eclipse is thetype
Com. smaxe. UV. a. C cannot be resolved. It is indirectly referenced fromrequired. class files. Com. smaxe. UV. a. C is a package name, but there is also COM. smaxe. UV. a. C Class, which is illegal in the Java compilation mechanism, but the Java VM allows such an existing form. The obfuscator uses this feature to modify the compiled bytecode file into such an odd form as "audio-visual ".

The method to bypass this mechanism is very simple, that is, reflection and specific code will be posted, but the process of thinking almost broke the head. For details about the call method, refer to the official example. You only need to replace netconnection and netstream with the following two.

Download the complete code here: http://download.csdn.net/detail/visualcatsharp/4294733

If you have no resource score, please leave your email.

Modified netconnection:
import java.io.File;import java.lang.reflect.Method;import java.util.Calendar;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import com.smaxe.logger.ILogger;import com.smaxe.uv.ProtocolLayerInfo;import com.smaxe.uv.Responder;import com.smaxe.uv.UrlInfo;import com.smaxe.uv.client.INetConnection;import com.smaxe.uv.client.a.d;import com.smaxe.uv.client.a.h;import com.smaxe.uv.client.a.i;import com.smaxe.uv.client.a.k;public final class UltraNetConnection extends i  implements INetConnection{  private final h a;  private d b = null;  private a c = null;  private ExecutorService d = null;  private ScheduledExecutorService e = null;  private boolean f = false;  private boolean g = false;  private static final int h = 19;  private static final int i = 9;  private static final int[] j = { 5, 2, 7, 1, 0, 3, 6, 4 };  private static byte[] k = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };  public static void setSwfFileSizeAndHash(Map<String, Object> paramMap, File paramFile)    throws Exception  {    a(paramMap, paramFile);  }  public UltraNetConnection()  {    this(null);  }  public UltraNetConnection(Map<String, Object> paramMap)  {    this(paramMap, null, null);  }  public UltraNetConnection(Map<String, Object> paramMap, ExecutorService paramExecutorService, ScheduledExecutorService paramScheduledExecutorService)  {    super(paramMap);    this.d = (paramExecutorService == null ? Executors.newCachedThreadPool() : paramExecutorService);    this.e = (paramScheduledExecutorService == null ? Executors.newSingleThreadScheduledExecutor() : paramScheduledExecutorService);    this.f = (paramExecutorService == null);    this.g = (paramScheduledExecutorService == null);    this.a = new k(this.e);  }  public void addHeader(String paramString, boolean paramBoolean, Object paramObject)  {    this.b.a(paramString, paramBoolean, paramObject);  }  public void call(String paramString, Responder paramResponder, Object[] paramArrayOfObject)  {    if (!connected())      return;    this.b.a(paramString, paramResponder, paramArrayOfObject);  }  public void close()  {    b(com.smaxe.uv.a.e.b("NetConnection.Connect.Closed", "Connection is closed."));  }  public void connect(String paramString, Object... paramArrayOfObject)  {//    b(k);    UrlInfo localUrlInfo = UrlInfo.parseUrl(paramString);    com.smaxe.uv.client.a.e locale = new com.smaxe.uv.client.a.e();    locale.a(this.d);    locale.a((ILogger)configuration().get("logger"));    this.b = locale;    this.c = new a();    try {    Method bitchMethod = com.smaxe.uv.client.a.h.class.getMethod("a", String.class, String.class, int.class, Map.class);        Object btichResult = bitchMethod.invoke(this.a, localUrlInfo.protocol, localUrlInfo.host, localUrlInfo.port, configuration());        Method[] aryMethod = com.smaxe.uv.client.a.d.class.getMethods();        for(Method method : aryMethod) {        if(method.getName().equals("a") && method.getParameterTypes().length == 6) {        method.invoke(this.b, this, btichResult, paramString, localUrlInfo.getApp(), this.c, paramArrayOfObject);        break;        }        }    } catch(Exception ex) {    ex.printStackTrace();    }        super.connect(paramString, paramArrayOfObject);  }  public boolean connected()  {    if (this.b == null)      return false;    return this.b.a() == 3;  }  public String connectedProxyType()  {    return connected() ? this.b.b() : null;  }  public boolean usingTLS()  {    return connected() ? this.b.c() : false;  }  public ProtocolLayerInfo getInfo()  {    return this.b.d();  }  public int getUploadBufferSize()  {    return this.b.e();  }  public void setMaxUploadBandwidth(int paramInt)  {    if (paramInt < 0)      throw new IllegalArgumentException("Parameter 'bandwidth' is negative: " + paramInt);    this.b.a(paramInt);  }  public void onBWDone()  {  }  public void onBWDone(Object[] paramArrayOfObject)  {  }  private void b(Map<String, Object> paramMap)  {    if (this.b == null)      return;    this.b.a(paramMap);    if ((this.f) && (this.d != null))      this.d.shutdown();    if ((this.g) && (this.e != null))      this.e.shutdown();    this.d = null;    this.e = null;  }  static void a(byte[] paramArrayOfByte)  {    if ((paramArrayOfByte == null) || (paramArrayOfByte.length != 25))      return;    k = paramArrayOfByte;  }  d a()  {    return this.b;  }  private static void b(byte abyte0[])  throws IllegalArgumentException{  int l = 0;  for(int i1 = 1; i1 < abyte0.length - 1; i1++)      l += abyte0[i1] & 0xff;  l &= 0xff;  int j1 = abyte0[1] & 0xf;  if((abyte0[0] & 0xff) != (byte)(l >> 0 & 0xf) || (abyte0[abyte0.length - 1] & 0xff) != (byte)(l >> 4 & 0xf) || abyte0[1] + abyte0[abyte0.length - 2] != 15)      a(16);  boolean aflag[] = new boolean[21];  byte abyte1[] = new byte[8];  int k1 = 1;  int l1 = j1;  for(int i2 = 0; i2 < abyte1.length; i2++)  {      for(; aflag[l1 % aflag.length]; l1++);      aflag[l1 % aflag.length] = true;      abyte1[i2] = abyte0[2 + l1 % aflag.length];      k1 += 2;      l1 += k1;  }  if((abyte1[1] & 0xf) != 3)      a(32);  boolean flag = (abyte1[3] & 0xf) >= 8;  int j2 = (flag ? abyte1[3] - 8 : abyte1[3]) & 0xf;  if(j2 < 1)      a(1);  if(flag)  {      Calendar calendar = Calendar.getInstance();      calendar.set(1, 2000 + (abyte1[4] & 0xf));      calendar.set(2, (abyte1[5] & 0xf) - 1);      calendar.set(5, ((abyte1[6] & 0xf) << 4) + (abyte1[7] & 0xf));      if(System.currentTimeMillis() - calendar.getTimeInMillis() > 0L)          a(18);  }}  private static void a(int paramInt)  {    switch (paramInt & 0xF)    {    case 0:      throw new IllegalArgumentException(a(new long[] { 8460391658548064800L, 8315163859177334048L, 8319872964449869929L, 7205878151055483136L }));    case 1:      throw new IllegalArgumentException(a(new long[] { 8460391658548064800L, 8315163859177334048L, 8319309735340351598L, 7811060823377406308L, 7162256601089340786L, 8532478991051810162L, 120946281218048L }));    case 2:      throw new IllegalArgumentException(a(new long[] { 8462924959242482208L, 2314957309810076517L, 2335505025909089656L, 2378011653932580864L }));    }  }  private static String a(long[] paramArrayOfLong)  {    byte[] arrayOfByte = new byte[paramArrayOfLong.length * 8];    int m = 0;    for (int n = 0; n < paramArrayOfLong.length; n++)      for (int i1 = 0; i1 < 8; i1++)      {        byte i2 = (byte)(int)(paramArrayOfLong[n] >> j[i1] * 8 & 0xFF);        if (i2 == 0)          break;        arrayOfByte[(n * 8 + i1)] = i2;        m++;      }    return new String(arrayOfByte, 0, m);  }  static void a(UltraNetConnection netconnection, String s, Exception exception)  {      netconnection.a(s, exception);  }  static void a(UltraNetConnection netconnection, String s)  {      netconnection.a(s);  }  static void a(UltraNetConnection netconnection, Map map)  {      netconnection.b(map);  }  static void b(UltraNetConnection netconnection, Map map)  {      netconnection.a(map);  }  static void c(UltraNetConnection netconnection, Map map)  {      netconnection.a(map);  }    private class a extends d.a  {    public a()    {    }    public void a(String paramString, Exception paramException)    {      UltraNetConnection.a(UltraNetConnection.this, paramString, paramException);    }    public void a(String paramString)    {      UltraNetConnection.a(UltraNetConnection.this, paramString);    }    public void a(Map<String, Object> paramMap)    {      String str = (String)paramMap.get("code");      if ((!"NetConnection.Connect.Success".equals(str)) && (!"NetConnection.Connect.Bandwidth".equals(str)) && (!"NetConnection.Call.Failed".equals(str)))        UltraNetConnection.a(UltraNetConnection.this, paramMap);      UltraNetConnection.b(UltraNetConnection.this, paramMap);    }    public void a(long paramLong1, long paramLong2)    {      if (!((Boolean)UltraNetConnection.this.configuration().get("enableAcknowledgementEventNotification")).booleanValue())        return;      Map localMap = com.smaxe.uv.a.e.b("NetConnection.Connect.Bandwidth", "'Acknowledgement' event notification.");      localMap.put("acknowledgement", Long.valueOf(paramLong1));      localMap.put("info", new ProtocolLayerInfo(UltraNetConnection.this.getInfo()));      localMap.put("uploadBufferSize", Long.valueOf(paramLong2));      UltraNetConnection.c(UltraNetConnection.this, localMap);    }  }}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.