- Name - Android App
- Category - Reverse Engineering
- Points - 100
- Description - Find the Flag!!
- Binary - Download here
This challenge is a good exercise for those of you who would like to start REing android apps. Once again the application accepts a serial number and validates it:
Extract the apk file and open classes.dex with Jadx. You can use dex2jar and jdgui for this but I found that Jadx gives better results. The part we're interested in resides in the button's listener, onClick() in class a:
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 26 27 28 29 | public void onClick(View view) { String str = new String( " " ); str = this .a.b.getText().toString(); Log.v( "EditText" , this .a.b.getText().toString()); String str2 = new String( "" ); int processObjectArrayFromNative = this .a.processObjectArrayFromNative(str); int IsCorrect = this .a.IsCorrect(str); str = new StringBuilder(String.valueOf( this .a.d + processObjectArrayFromNative)).append( " " ).toString(); try { MessageDigest instance = MessageDigest.getInstance( "MD5" ); instance.update(str.getBytes()); byte [] digest = instance.digest(); StringBuffer stringBuffer = new StringBuffer(); for ( byte b : digest) { stringBuffer.append(Integer.toString((b & 255 ) + 256 , 16 ).substring( 1 )); } if (IsCorrect == 1 && this .a.e != "unknown" ) { this .a.c.setText( "Sharif_CTF(" + stringBuffer.toString() + ")" ); } if (IsCorrect == 1 && this .a.e == "unknown" ) { this .a.c.setText( "Just keep Trying :-)" ); } if (IsCorrect == 0 ) { this .a.c.setText( "Just keep Trying :-)" ); } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } |
Our input is read from the textfield (line 3) and passed to the IsCorrect() function (line 7). Unfortunately this function is part of the adnjni library (\lib\armeabi folder); it would've been too easy if it was written in Java. Load the library in IDA and locate the function Java_com_example_ctf2_MainActivity_IsCorrect(). The first section looks like this:
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 26 27 28 29 30 31 32 33 34 35 36 37 | v9 = ( char *)(*( int (**)( void ))(*(_DWORD *)a1 + 676))(); v12 = 101; v13 = 102; v14 = 53; v15 = 55; v16 = 102; v17 = 51; v18 = 102; v19 = 101; v20 = 51; v21 = 99; v22 = 102; v23 = 54; v24 = 48; v25 = 51; v26 = 99; v27 = 48; v28 = 51; v29 = 56; v30 = 57; v31 = 48; v32 = 101; v33 = 101; v34 = 53; v35 = 56; v36 = 56; v37 = 56; v38 = 55; v39 = 56; v40 = 99; v41 = 48; v42 = 101; v43 = 99; v44 = 0; v4 = 0; v45 = 53; v10 = j_j_strcmp(v9, &v12); |
Notice that at the bottom (line 37), 2 strings are being compared. Variable v9 contains our input string and variable v12 contains the string shown on lines 2 to 34. Once again, converting from decimal to ASCII we get ef57f3fe3cf603c03890ee588878c0ec.
And hence: