https://github.com/0xArab/diva-apk-file
1. Insecure Logging
입력한 데이터가 어디에 기록되는지 확인하고 취약한 코드를 찾아내는 것이 목표이다.
package jakhar.aseem.diva;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/* loaded from: classes.dex */
public class LogActivity extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_log);
}
public void checkout(View view) {
EditText cctxt = (EditText) findViewById(R.id.ccText);
try {
processCC(cctxt.getText().toString());
} catch (RuntimeException e) {
Log.e("diva-log", "Error while processing transaction with credit card: " + cctxt.getText().toString());
Toast.makeText(this, "An error occured. Please try again later", 0).show();
}
}
private void processCC(String ccstr) {
RuntimeException e = new RuntimeException();
throw e;
}
}
코드를 확인해보면 onCreate로 activity_log를 불러온다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:textColor="@color/material_grey_600" android:gravity="fill" android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/log_intro" android:layout_alignParentLeft="true" android:layout_alignParentTop="true"/>
<EditText android:id="@+id/ccText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/log_enter" android:ems="10" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:inputType="number"/>
<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/log_checkout" android:layout_below="@+id/ccText" android:layout_alignParentLeft="false" android:layout_centerHorizontal="true" android:onClick="checkout"/>
</RelativeLayout>
CHECK OUT 버튼을 누르면 checkout 함수를 호출한다.
checkout 함수에서는 card 넘버를 EditText 클래스의 cctxt로 저장하고
processCC 함수에 cctxt를 인자로 넣어 호출한다. processCC 에서는 일부러 에러를 던져주고
checkout 함수에서는 catch 로 넘어가 cctxt 데이터를 Log로 띄운다.
Log 내용에는 입력한 card number을 포함하고 있다.
Log를 확인하면 card number 값을 확인할 수 있다.
adb logcat
2. Hardcoding Issues - Part 1
하드코딩 되어 있는 부분을 찾는 것이 목표이다.
package jakhar.aseem.diva;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/* loaded from: classes.dex */
public class HardcodeActivity extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hardcode);
}
public void access(View view) {
EditText hckey = (EditText) findViewById(R.id.hcKey);
if (hckey.getText().toString().equals("vendorsecretkey")) {
Toast.makeText(this, "Access granted! See you on the other side :)", 0).show();
} else {
Toast.makeText(this, "Access denied! See you in hell :D", 0).show();
}
}
}
access함수를 보면 입력받은 값을 EditText 클래스 hckey에 저장한다.
hckey값과 "vendorsecretkey" 문자열과 비교해서 같다면 access granted 출력한다.
이 부분이 하드코딩 된 부분이고 "vendorsecretkey"를 입력하면
access granted 출력된다.
3. Insecure Data Storage - Part 1
name, password가 저장되는 위치/방법을 찾고 취약한 코드를 찾는것이 목표이다.
package jakhar.aseem.diva;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/* loaded from: classes.dex */
public class InsecureDataStorage1Activity extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_insecure_data_storage1);
}
public void saveCredentials(View view) {
SharedPreferences spref = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor spedit = spref.edit();
EditText usr = (EditText) findViewById(R.id.ids1Usr);
EditText pwd = (EditText) findViewById(R.id.ids1Pwd);
spedit.putString("user", usr.getText().toString());
spedit.putString("password", pwd.getText().toString());
spedit.commit();
Toast.makeText(this, "3rd party credentials saved successfully!", 0).show();
}
}
saveCredentials함수를 보면
SharedPreferences API로 spref 변수를 선언하는 것을 볼 수 있다.
SharedPreferences란 작고 단순한 데이터를 저장하기 위한 API로 xml 파일 형식으로 저장된다는 특징이 있다.
파일은 /data/data/(package_name)/shared_prefs/SharedPreference 경로에 저장된다.
Save하고 SharedPreference 경로로 이동한다.
jakhar.aseem.diva_preferences.xml 파일이 있고
mypassword, myname이 저장된 것을 확인할 수 있다.
4. Insecure Data Storage - Part 2
3번 문제와 비슷하게 username, password가 저장되는 위치/방법을 찾고 취약한 코드를 찾는 것이 목표이다.
package jakhar.aseem.diva;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/* loaded from: classes.dex */
public class InsecureDataStorage2Activity extends AppCompatActivity {
private SQLiteDatabase mDB;
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
this.mDB = openOrCreateDatabase("ids2", 0, null);
this.mDB.execSQL("CREATE TABLE IF NOT EXISTS myuser(user VARCHAR, password VARCHAR);");
} catch (Exception e) {
Log.d("Diva", "Error occurred while creating database: " + e.getMessage());
}
setContentView(R.layout.activity_insecure_data_storage2);
}
public void saveCredentials(View view) {
EditText usr = (EditText) findViewById(R.id.ids2Usr);
EditText pwd = (EditText) findViewById(R.id.ids2Pwd);
try {
this.mDB.execSQL("INSERT INTO myuser VALUES ('" + usr.getText().toString() + "', '" + pwd.getText().toString() + "');");
this.mDB.close();
} catch (Exception e) {
Log.d("Diva", "Error occurred while inserting into database: " + e.getMessage());
}
Toast.makeText(this, "3rd party credentials saved successfully!", 0).show();
}
}
private로 mDB 이름의 SQLiteDatabase를 만든다.
onCreate에서 ids2 이름의 DB를 만들고 table을 생성한다.
saveCredentials 함수에는 입력한 데이터를 INSERT하는 쿼리가 있다.
db 정보는 /data/data/(package_name)/databases 경로에 위치하고 있다.
db 파일이기 때문에 중간중간 깨진 문자들이 보인다. 평문으로 저장되어서 데이터 정보가 다 보인다.
내장되어 있는 sqlite를 이용해서 select 쿼리로 데이터를 확인할 수도 있다.
이전에 넣었던 데이터들과 방금 입력한 데이터들이 평문으로 저장되어 있는 것을 확인할 수 있다.
5. Insecure Data Storage - Part 3
package jakhar.aseem.diva;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import java.io.File;
import java.io.FileWriter;
/* loaded from: classes.dex */
public class InsecureDataStorage3Activity extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_insecure_data_storage3);
}
public void saveCredentials(View view) {
EditText usr = (EditText) findViewById(R.id.ids3Usr);
EditText pwd = (EditText) findViewById(R.id.ids3Pwd);
File ddir = new File(getApplicationInfo().dataDir);
try {
File uinfo = File.createTempFile("uinfo", "tmp", ddir);
uinfo.setReadable(true);
uinfo.setWritable(true);
FileWriter fw = new FileWriter(uinfo);
fw.write(usr.getText().toString() + ":" + pwd.getText().toString() + "\n");
fw.close();
Toast.makeText(this, "3rd party credentials saved successfully!", 0).show();
} catch (Exception e) {
Toast.makeText(this, "File error occurred", 0).show();
Log.d("Diva", "File error: " + e.getMessage());
}
}
}
saveCredentials 함수에서
usr, pwd에 입력한 데이터를 저장하고
File ddir = new File(getApplicationInfo().dataDir);
이 애플리케이션의 데이터 디렉토리 경로의 File 타입 ddir객체를 생성한다.
이후 try문으로 진입하고 uinfo 임시 파일을 만든다. 뒤에 오는 인자는 순서대로
접두사, 접미사, 파일 경로를 의미한다.
/data/data/(package_name) 경로로 가보면 uinfo.tmp 파일이 있는 것을 확인할 수 있고 입력한 데이터를 담고 있다.
6. Insecure Data Storage - Part 4
package jakhar.aseem.diva;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import java.io.File;
import java.io.FileWriter;
/* loaded from: classes.dex */
public class InsecureDataStorage4Activity extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_insecure_data_storage4);
}
public void saveCredentials(View view) {
EditText usr = (EditText) findViewById(R.id.ids4Usr);
EditText pwd = (EditText) findViewById(R.id.ids4Pwd);
File sdir = Environment.getExternalStorageDirectory();
try {
File uinfo = new File(sdir.getAbsolutePath() + "/.uinfo.txt");
uinfo.setReadable(true);
uinfo.setWritable(true);
FileWriter fw = new FileWriter(uinfo);
fw.write(usr.getText().toString() + ":" + pwd.getText().toString() + "\n");
fw.close();
Toast.makeText(this, "3rd party credentials saved successfully!", 0).show();
} catch (Exception e) {
Toast.makeText(this, "File error occurred", 0).show();
Log.d("Diva", "File error: " + e.getMessage());
}
}
}
File sdir = Environment.getExternalStorageDirectory();
외부저장소 최상위 경로 sdir 객체를 생성한다.
외부 저장소 경로는 /storage/emulated/0/ 이다.
try에서 ./uinfo.txt 파일을 생성하고 파일에 입력한 값을 저장한다.
Save를 누르면
에러가 뜬다.
log를 확인해보면 저장 권한이 없는 것으로 보인다.
저장공간을 허용 해주고 하면 될 것 같다.
외부저장소 최상위 경로에 가면 .uinfo.txt 파일이 존재하고
파일 내용을 확인할 수 있다.
7. Input Validation Issues - Part 1
이번 문제는 3명의 사용자 정보가 있고 단일 검색을 통해 3명의 정보를 모두 출력 시키는 것이 목표이다.
package jakhar.aseem.diva;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/* loaded from: classes.dex */
public class SQLInjectionActivity extends AppCompatActivity {
private SQLiteDatabase mDB;
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
this.mDB = openOrCreateDatabase("sqli", 0, null);
this.mDB.execSQL("DROP TABLE IF EXISTS sqliuser;");
this.mDB.execSQL("CREATE TABLE IF NOT EXISTS sqliuser(user VARCHAR, password VARCHAR, credit_card VARCHAR);");
this.mDB.execSQL("INSERT INTO sqliuser VALUES ('admin', 'passwd123', '1234567812345678');");
this.mDB.execSQL("INSERT INTO sqliuser VALUES ('diva', 'p@ssword', '1111222233334444');");
this.mDB.execSQL("INSERT INTO sqliuser VALUES ('john', 'password123', '5555666677778888');");
} catch (Exception e) {
Log.d("Diva-sqli", "Error occurred while creating database for SQLI: " + e.getMessage());
}
setContentView(R.layout.activity_sqlinjection);
}
public void search(View view) {
EditText srchtxt = (EditText) findViewById(R.id.ivi1search);
try {
Cursor cr = this.mDB.rawQuery("SELECT * FROM sqliuser WHERE user = '" + srchtxt.getText().toString() + "'", null);
StringBuilder strb = new StringBuilder("");
if (cr != null && cr.getCount() > 0) {
cr.moveToFirst();
do {
strb.append("User: (" + cr.getString(0) + ") pass: (" + cr.getString(1) + ") Credit card: (" + cr.getString(2) + ")\n");
} while (cr.moveToNext());
} else {
strb.append("User: (" + srchtxt.getText().toString() + ") not found");
}
Toast.makeText(this, strb.toString(), 0).show();
} catch (Exception e) {
Log.d("Diva-sqli", "Error occurred while searching in database: " + e.getMessage());
}
}
}
onCreate에는 db에 유저 정보를 삽입하는 코드가 있고
Cursor cr = this.mDB.rawQuery("SELECT * FROM sqliuser WHERE user = '" + srchtxt.getText().toString() + "'", null);
search 함수에서 입력 받은 데이터를 그대로 쿼리에 넣는다.
이 부분에서 sqli 공격이 가능하다.
3명의 유저 정보를 동시에 띄워야 하기 때문에 WHERE user 문을 무시하고 모두 SELECT하도록 쿼리를 짠다.
8. Input Validation Issues - Part 2
URL 외 민감한 정보를 엑세스 하는 것이 목표이다.
package jakhar.aseem.diva;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.EditText;
/* loaded from: classes.dex */
public class InputValidation2URISchemeActivity extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_input_validation2_urischeme);
WebView wview = (WebView) findViewById(R.id.ivi2wview);
WebSettings wset = wview.getSettings();
wset.setJavaScriptEnabled(true);
}
public void get(View view) {
EditText uriText = (EditText) findViewById(R.id.ivi2uri);
WebView wview = (WebView) findViewById(R.id.ivi2wview);
wview.loadUrl(uriText.getText().toString());
}
}
검증 없이 입력한 문자열을 웹 URL로 로드하기 때문에
file URL 사용해서 localhost의 파일에 접근이 가능하다.
9. Access Control Issues - Part 1
외부에서 API 증명에 엑세스 하라고 한다.
package jakhar.aseem.diva;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
/* loaded from: classes.dex */
public class AccessControl1Activity extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_access_control1);
}
public void viewAPICredentials(View view) {
Intent i = new Intent();
i.setAction("jakhar.aseem.diva.action.VIEW_CREDS");
if (i.resolveActivity(getPackageManager()) != null) {
startActivity(i);
return;
}
Toast.makeText(this, "Error while getting API details", 0).show();
Log.e("Diva-aci1", "Couldn't resolve the Intent VIEW_CREDS to our activity");
}
}
i.setAction("jakhar.aseem.diva.action.VIEW_CREDS");
위 액션 지정해주면 지정된 액션의 Activity가 실행된다.
<activity android:label="@string/apic_label" android:name="jakhar.aseem.diva.APICredsActivity">
<intent-filter>
<action android:name="jakhar.aseem.diva.action.VIEW_CREDS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
Manifest.xml을 확인해보면 위에서 본 action이 있다.
exported가 설정 되어있지 않은 경우 기본으로 true값을 가진다.
am start jakhar.aseem.diva/.APICredsActivity
adb shell에서 Activity에 바로 접근하여 엑세스 할 수 있다.
10. Access Control Issues - Part 2
package jakhar.aseem.diva;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.RadioButton;
import android.widget.Toast;
/* loaded from: classes.dex */
public class AccessControl2Activity extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_access_control2);
}
public void viewAPICredentials(View view) {
RadioButton rbregnow = (RadioButton) findViewById(R.id.aci2rbregnow);
Intent i = new Intent();
boolean chk_pin = rbregnow.isChecked();
i.setAction("jakhar.aseem.diva.action.VIEW_CREDS2");
i.putExtra(getString(R.string.chk_pin), chk_pin);
if (i.resolveActivity(getPackageManager()) != null) {
startActivity(i);
return;
}
Toast.makeText(this, "Error while getting Tveeter API details", 0).show();
Log.e("Diva-aci1", "Couldn't resolve the Intent VIEW_CREDS2 to our activity");
}
}
Action을 VIEW_CREDS2로 지정하고 그의 activity를 불러온다.
<activity android:label="@string/apic2_label" android:name="jakhar.aseem.diva.APICreds2Activity">
<intent-filter>
<action android:name="jakhar.aseem.diva.action.VIEW_CREDS2"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
package jakhar.aseem.diva;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
/* loaded from: classes.dex */
public class APICreds2Activity extends AppCompatActivity {
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_apicreds2);
TextView apicview = (TextView) findViewById(R.id.apic2TextView);
EditText pintext = (EditText) findViewById(R.id.aci2pinText);
Button vbutton = (Button) findViewById(R.id.aci2button);
Intent i = getIntent();
boolean bcheck = i.getBooleanExtra(getString(R.string.chk_pin), true);
if (!bcheck) {
apicview.setText("TVEETER API Key: secrettveeterapikey\nAPI User name: diva2\nAPI Password: p@ssword2");
return;
}
apicview.setText("Register yourself at http://payatu.com to get your PIN and then login with that PIN!");
pintext.setVisibility(0);
vbutton.setVisibility(0);
}
public void viewCreds(View view) {
Toast.makeText(this, "Invalid PIN. Please try again", 0).show();
}
}
APICreds2Activity에서 엑세스 하기 위해서는
boolean bcheck = i.getBooleanExtra(getString(R.string.chk_pin), true);
R.string.chk_pin의 값을 불러와서 bcheck에 저장하고 bchack가 false일 경우 엑세스에 성공한다.
그렇다면 chk_pin값이 false여야 한다.
getString(R.string.chk_pin)
여기서 R.string.chk_pin은 /res/values/strings.xml에 등록된 string의 id를 불러오고
getString()을 사용하면 id의 값을 가져올 수 있다.
chk_pin의 값은 check_pin임을 알 수 있다.
adb shell am start -n jakhar.aseem.diva/.APICreds2Activity --ez check_pin false
n옵션으로 Intent를 실행할 수 있도록 해주고 --ez 옵션으로 Extra_key 값을 false 로 지정할 수 있다.
11. Access Control Issues - Part 3(?)
12. Hardcoding Issues - Part 2
package jakhar.aseem.diva;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/* loaded from: classes.dex */
public class Hardcode2Activity extends AppCompatActivity {
private DivaJni djni;
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hardcode2);
this.djni = new DivaJni();
}
public void access(View view) {
EditText hckey = (EditText) findViewById(R.id.hc2Key);
if (this.djni.access(hckey.getText().toString()) != 0) {
Toast.makeText(this, "Access granted! See you on the other side :)", 0).show();
} else {
Toast.makeText(this, "Access denied! See you in hell :D", 0).show();
}
}
}
DivaJni 클래스의 반환 값에 따라 결과가 달라지는 것 같다.
package jakhar.aseem.diva;
/* loaded from: classes.dex */
public class DivaJni {
private static final String soName = "divajni";
public native int access(String str);
public native int initiateLaunchSequence(String str);
static {
System.loadLibrary(soName);
}
}
divajni라는 라이브러리를 로드하는 코드가 담겨있다.
라이브러리 경로는 data/app/(package_name)/lib/x86_64 에 있다.
위 경로에 가면 라이브러리 하나가 있다.
adb pull /data/app/jakhar.aseem.diva-DolXagkFPcattkE7AjwXAg==/lib/x86_64/libdivajni.so ./
위 명령어로 파일을 다운로드 해주고
strings libdivajni.so
strings 명령어로 문자열만 출력해보았다.
여러 문자열이 있어서 뭐가 access 인지 알 수가 없다.
ida에서 문자열을 참조한 주소를 하나씩 올라가다보면 access 부분을 찾을 수 있다.
access가 olsdfgad;lh임을 알 수 있다.
13. Input Validation Issues - Part 3(?)
package jakhar.aseem.diva;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
/* loaded from: classes.dex */
public class InputValidation3Activity extends AppCompatActivity {
private DivaJni djni;
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_input_validation3);
this.djni = new DivaJni();
}
public void push(View view) {
EditText cTxt = (EditText) findViewById(R.id.ivi3CodeText);
if (this.djni.initiateLaunchSequence(cTxt.getText().toString()) != 0) {
Toast.makeText(this, "Launching in T - 10 ...", 0).show();
} else {
Toast.makeText(this, "Access denied!", 0).show();
}
}
}
12번 문제에서 처럼 DivaJni 클래스에서 라이브러리를 불러오는 것임을 알고 있다.
initiateLaunchSequence 값만 알아내면 될 것 같다.
여기서 initiateLaunchSequence로 들어가보면
.dotdot 문자열을 확인할 수 있다.
.dotdot을 넣으면 Launching 메시지로 바뀌는데
목표는 애플리케이션을 충돌 시키는 것이었다.
.dotdo.d.dot.do.d.dotdototdottdotdototdott
여러 시도 하던 도중 .dotdot 사이에 .dotdot을 약 5번 넣으면 충돌이 일어나는 것을 확인했다.