diff --git a/.gitignore b/.gitignore index ac5dac8f..8a488186 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ bin/ gen/ obj/ -libs/*/*.so + diff --git a/README.md b/README.md index 3360c1f7..4514b61e 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,8 @@ Use Android studio. - Changed to Android Studio structure. # TODO - - Optimization \ No newline at end of file + - Optimization(Done) + - Support x86 files. + - fix bugs + - add menus on clicking disassemblies. + - add coloring. \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5536a2d7..b33613db 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,12 +6,14 @@ tools:remove="android:maxSdkVersion" /> + + android:resizeableActivity = "true" + android:largeHeap="true"> diff --git a/app/src/main/java/capstone/Arm_const.java b/app/src/main/java/capstone/Arm_const.java index 2596ed80..ce13cc34 100644 --- a/app/src/main/java/capstone/Arm_const.java +++ b/app/src/main/java/capstone/Arm_const.java @@ -3,6 +3,7 @@ import android.util.*; import java.lang.reflect.*; +import java.util.*; public class Arm_const { @@ -39,8 +40,44 @@ public class Arm_const public static final int ARM_CC_GT = 13; public static final int ARM_CC_LE = 14; public static final int ARM_CC_AL = 15; + private static final Map _int2string; + + static + { + final Map int2string = new HashMap<>(); + + try + { + for (Field field: Arm_const.class.getFields()) + { + final int mod = field.getModifiers(); + + if (!int.class.equals(field.getType())) + continue; + + if (!Modifier.isStatic(mod) || !Modifier.isPublic(mod)) + continue; + + if (!field.getName().startsWith("ARM_CC_")) + continue; + + int2string.put(field.getInt(null), + field.getName().substring("ARM_CC_".length())); + } + } + catch (IllegalAccessException l_e) + { + throw new RuntimeException(l_e); // should not occur + } + + _int2string = Collections.unmodifiableMap(int2string); + } public static String getCCName(int cc) + { + return _int2string.get(cc); + } + public static String getCCName2(int cc) { Class clazz=Arm_const.class; Field[] fields=clazz.getFields(); diff --git a/app/src/main/java/capstone/Capstone.java b/app/src/main/java/capstone/Capstone.java index fe11ae82..759abb60 100644 --- a/app/src/main/java/capstone/Capstone.java +++ b/app/src/main/java/capstone/Capstone.java @@ -221,7 +221,11 @@ private OpInfo getOptInfo(_cs_detail detail) return op_info; } - + int opCount; + int opIndex; + int regRead; + int regWrite; + byte[] bytes; public int opCount(int type) { return cs.cs_op_count(csh, raw.getPointer(), type); @@ -276,8 +280,7 @@ protected void finalize() throws Throwable // TODO: Implement this method super.finalize(); cs.cs_free(raw.getPointer(),new NativeLong(1)); - } - + } } private CsInsn[] fromArrayRaw(_cs_insn[] arr_raw) @@ -564,11 +567,11 @@ public CsInsn[] disasm(byte[] code, long address, long count) return allInsn; } - public CsInsn[] disasm(byte[] code,long offset, long address, long count) + public CsInsn[] disasm(byte[] code,long offset, long length,long address, long count) { PointerByReference insnRef = new PointerByReference(); - NativeLong c = cs.cs_disasm2(ns.csh, code,new NativeLong(offset), new NativeLong(code.length), address, new NativeLong(count), insnRef); + NativeLong c = cs.cs_disasm2(ns.csh, code,new NativeLong(offset), new NativeLong(length), address, new NativeLong(count), insnRef); if (0 == c.intValue()) { diff --git a/app/src/main/java/com/kyhsgeekcode/disassembler/DisasmResult.java b/app/src/main/java/com/kyhsgeekcode/disassembler/DisasmResult.java index 27baf137..f89027b2 100644 --- a/app/src/main/java/com/kyhsgeekcode/disassembler/DisasmResult.java +++ b/app/src/main/java/com/kyhsgeekcode/disassembler/DisasmResult.java @@ -10,8 +10,8 @@ public DisasmResult() address=0L; size=0; bytes=new byte[16]; - mnemonic=new String("undefined"); - op_str=new String("undefined"); + mnemonic="undefined"; + op_str="undefined"; regs_read=new byte[12]; regs_read_count=0; regs_write=new byte[20]; diff --git a/app/src/main/java/com/kyhsgeekcode/disassembler/ListViewAdapter.java b/app/src/main/java/com/kyhsgeekcode/disassembler/ListViewAdapter.java index a0e82638..77dd96ee 100644 --- a/app/src/main/java/com/kyhsgeekcode/disassembler/ListViewAdapter.java +++ b/app/src/main/java/com/kyhsgeekcode/disassembler/ListViewAdapter.java @@ -17,6 +17,11 @@ public ListViewAdapter() { } + //You should not modify + public ArrayList itemList() + { + return listViewItemList; + } // Adapter에 사용되는 데이터의 개수를 리턴. : 필수 구현 @Override diff --git a/app/src/main/java/com/kyhsgeekcode/disassembler/ListViewItem.java b/app/src/main/java/com/kyhsgeekcode/disassembler/ListViewItem.java index 21ba2549..c780d290 100644 --- a/app/src/main/java/com/kyhsgeekcode/disassembler/ListViewItem.java +++ b/app/src/main/java/com/kyhsgeekcode/disassembler/ListViewItem.java @@ -24,6 +24,7 @@ public ListViewItem(DisasmResult disasmResult) this.disasmResult = disasmResult; this.address=Long.toHexString(disasmResult.address); byte[] bytestmp=new byte[disasmResult.size]; + //System.arraycopy(); for(int i=0;i disasmResults=new ArrayList<>(); + ArrayList disasmResults=new ArrayList<>(); private TableLayout tlDisasmTable; @@ -89,24 +93,17 @@ public void onClick(View p1) final List ListItems = new ArrayList<>(); ListItems.add("Instant mode"); ListItems.add("Persist mode"); - // ListItems.add(""); - final CharSequence[] items = ListItems.toArray(new String[ ListItems.size()]); - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("Disassemble as..."); - builder.setItems(items, new DialogInterface.OnClickListener() { + ShowSelDialog(ListItems,"Disassemble as...",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int pos) { //String selectedText = items[pos].toString(); - dialog.dismiss(); if (pos == 0) { instantMode = true; - final List ListItems2 = new ArrayList<>(); - ListItems2.add("Entry point"); - ListItems2.add("Custom address"); - AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); - builder.setTitle("Start from..."); - builder.setItems(items, new DialogInterface.OnClickListener() { + ListItems.clear(); + ListItems.add("Entry point"); + ListItems.add("Custom address"); + ShowSelDialog(ListItems,"Start from...",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog2, int pos) { if (pos == 0) @@ -116,33 +113,23 @@ public void onClick(DialogInterface dialog2, int pos) } else if (pos == 1) { - final EditText edittext = new EditText(MainActivity.this); - - AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); - builder.setTitle("Start from..."); - builder.setMessage("Enter address to start analyzing."); - builder.setView(edittext); - builder.setPositiveButton("OK", - new DialogInterface.OnClickListener() { + final EditText edittext=new EditText(MainActivity.this); + ShowEditDialog("Start from...","Enter address to start analyzing.",edittext,"OK",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog3, int which) { instantEntry = parseAddress(edittext.getText().toString()); DisassembleInstant(); } - }); - builder.setNegativeButton("cancel", - new DialogInterface.OnClickListener() { + },"cancel",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog4, int which) { dialog4.dismiss(); } }); - dialog2.dismiss(); - builder.show(); + //dialog2.dismiss(); } } }); - builder.show(); } else if (pos == 1) { @@ -150,7 +137,6 @@ else if (pos == 1) } } }); - builder.show(); break; case R.id.btnShowdetail: if (elfUtil == null) @@ -169,12 +155,50 @@ else if (pos == 1) default: break; } - + + } + + private void ShowEditDialog(String title,String message,final EditText edittext, + String positive,DialogInterface.OnClickListener pos, + String negative,DialogInterface.OnClickListener neg) + { + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setTitle(title); + builder.setMessage(message); + builder.setView(edittext); + builder.setPositiveButton(positive,pos); + builder.setNegativeButton(negative,neg); + builder.show(); + return ; } + private void ShowSelDialog(final List ListItems,String title,DialogInterface.OnClickListener listener) + { + final CharSequence[] items = ListItems.toArray(new String[ ListItems.size()]); + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(title); + builder.setItems(items,listener); + builder.show(); + } + + private long parseAddress(String toString) { + if(toString==null) + { + return elfUtil.getEntryPoint(); + } + if(toString.equals("")) + { + return elfUtil.getEntryPoint(); + } // TODO: Implement this method - return Long.decode(toString); + try{ + long l= Long.decode(toString); + return l; + }catch(NumberFormatException e) + { + Toast.makeText(this,"Did you enter valid address?",3).show(); + } } private void AlertSelFile() @@ -184,6 +208,7 @@ private void AlertSelFile() private void SaveDisasm() { + requestAppPermissions(this); if (fpath == null || "".compareToIgnoreCase(fpath) == 0) { AlertSelFile(); @@ -232,7 +257,8 @@ private void SaveDisasmSub(int mode) try { StringBuilder sb=new StringBuilder(); - for (ListViewItem lvi:disasmResults) + ArrayList items=adapter.itemList(); + for (ListViewItem lvi:items) { switch (mode) { @@ -277,6 +303,7 @@ private void SaveDisasmSub(int mode) private void SaveDetail() { + requestAppPermissions(this); if (fpath == null || "".compareToIgnoreCase(fpath) == 0) { AlertSelFile(); @@ -333,6 +360,10 @@ private void DisassembleInstant() long index=startaddress; long addr=elfUtil.getCodeSectionVirtAddr(); long limit=startaddress + 400; + if(limit>=filecontent.length) + { + Toast.makeText(this,"Odd address :(",3).show(); + } for (;;) { DisasmResult dar=new DisasmResult(filecontent, index, addr); @@ -346,7 +377,7 @@ private void DisassembleInstant() //break; } final ListViewItem lvi=new ListViewItem(dar); - disasmResults.add(lvi); + //disasmResults.add(lvi); adapter.addItem(lvi); adapter.notifyDataSetChanged(); Log.v(TAG, "i=" + index + "lvi=" + lvi.toString()); @@ -368,6 +399,25 @@ private void DisassembleInstant() } } + public final Runnable runnableRequestLayout=new Runnable(){ + @Override + public void run() + { + //adapter.notifyDataSetChanged(); + listview.requestLayout(); + } + }; + +// final Runnable runnableAddItem=new Runnable(){ +// @Override +// public void run() +// { +// adapter.addItem(lvi); +// adapter.notifyDataSetChanged(); +// return ; +// } +// }; + ListViewItem lvi; //TODO: DisassembleFile(long address, int amt); private void DisassembleFile() { @@ -376,8 +426,7 @@ private void DisassembleFile() //final ProgressDialog dialog= showProgressDialog("Disassembling..."); disasmResults.clear(); - mNotifyManager = - (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + mNotifyManager =(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mBuilder = new Notification.Builder(this); mBuilder.setContentTitle("Disassembler") .setContentText("Disassembling in progress") @@ -393,68 +442,53 @@ public void run() long limit=elfUtil.getCodeSectionLimit(); long addr=elfUtil.getCodeSectionVirtAddr(); Log.v(TAG, "code section point :" + Long.toHexString(index)); + //ListViewItem lvi; // getFunctionNames(); - HashMap xrefComments=new HashMap(); - for (;;) + long size=limit - start; + long leftbytes=size; + DisasmIterator dai=new DisasmIterator(MainActivity.this,mNotifyManager,mBuilder,adapter,size); + dai.getAll(filecontent,start,size,addr, disasmResults); + /* do { - Capstone.CsInsn[] insns=cs.disasm(filecontent,index,addr,1); - Capstone.CsInsn insn=insns[0]; - final ListViewItem lvi=new ListViewItem(insn/*filecontent, index, addr*/); - if (insn.size == 0) + Capstone.CsInsn[] insns=cs.disasm(filecontent,index,Math.min(leftbytes,2048),addr,256); + if(insns==null) { - insn.size = 4; - insn.mnemonic = "db"; - //insn.bytes = new byte[]{filecontent[(int)index],filecontent[(int)index + 1],filecontent[(int)index + 2],filecontent[(int)index + 3]}; - insn.opStr = ""; - Log.e(TAG, "Dar.size==0, breaking?"); - //break; + Log.i(TAG,"INSN null, breaking!"); + break; } - //final ListViewItem lvi=new ListViewItem(dar); - if(lvi.isBranch()) + int bytes=0; + for(Capstone.CsInsn insn:insns) { - //xrefComments.put(lvi.getTargetAddress(),lvi.address); + if(insn.size==0) + { + Log.i(TAG,"INSN siz 0"); + insn.size=4;//ignore and skip + //blahblah + } + Log.v(TAG,index+"bytes="+bytes+"left="+leftbytes+"addr="+insn.address+insn.mnemonic); + index+=insn.size; + bytes+=insn.size; + addr+=insn.size; } - runOnUiThread(new Runnable(){ - @Override - public void run() - { - adapter.addItem(lvi); - adapter.notifyDataSetChanged(); - return ; - } - }); - //Log.v(TAG, "i=" + index + "lvi=" + lvi.toString()); - if (index >= limit) + if(insns.length==0) { - Log.i(TAG, "index is " + index + ", breaking"); - break; + index+=4; + bytes+=4; + addr+=4; } - //Log.v(TAG, "dar.size is =" + dar.size); - Log.i(TAG, "" + index + " out of " + (limit - start)); - if ((index - start) % 320 == 0) + if(insns.length<256) { - mBuilder.setProgress((int)(limit - start), (int)(index - start), false); - // Displays the progress bar for the first time. - mNotifyManager.notify(0, mBuilder.build()); - runOnUiThread(new Runnable(){ - @Override - public void run() - { - //adapter.notifyDataSetChanged(); - listview.requestLayout(); - } - }); + Log.i(TAG,"len l 256,"+insns.length); + //break; } - index += insn.size; - addr += insn.size; - //dialog.setProgress((int)((float)(index-start) * 100 / (float)(limit-start))); - //dialog.setTitle("Disassembling.."+(index-start)+" out of "+(limit-start)); - } + leftbytes-=bytes; + Log.i(TAG,"left="+leftbytes+"bytes="+bytes); + }while(leftbytes>0); + */ mNotifyManager.cancel(0); final int len=disasmResults.size(); //add xrefs - - + runOnUiThread(new Runnable(){ @Override public void run() @@ -464,7 +498,7 @@ public void run() final ListViewItem lvi=disasmResults.get(i); adapter.addItem(lvi); //AddOneRow(lvi); - }*/ + }/*/ //adapter.notifyDataSetChanged(); listview.requestLayout(); tab2.invalidate(); @@ -474,6 +508,128 @@ public void run() }); Log.v(TAG, "disassembly done"); } + + private void method() + { + int c=3; + /*final int numLoop=(int)size / BULK_SIZE; + final int remain=(int)size % BULK_SIZE; + final long endloopaddr=numLoop * BULK_SIZE; + HashMap xrefComments=new HashMap(); + //Optimization: less JNA Calls by bulk processing + //index : base of foffset + //processedbytes : offset from index of foffset + Log.i(TAG,"size="+size+"numLoop"+numLoop+"remain"+remain+"endloop"+endloopaddr); + for (;index < endloopaddr;index += BULK_SIZE,addr += BULK_SIZE) + { + int processedbytes=0; + Capstone.CsInsn[] insns=cs.disasm(filecontent, index, BULK_SIZE, addr, 0); + Log.i(TAG,"index="+index+"insns len="+insns.length+"Processedbytes="+processedbytes); + for (Capstone.CsInsn insn:insns) + { + //Capstone.CsInsn insn=insns[0]; + int siz=DoOneItem(insn); + Log.v(TAG,"pb="+processedbytes+"siz="+siz); + if (siz == 0)//Broken Instruction + { + Log.i(TAG,"Siz 0"); + //disassemble remnants... + HandleBroken(processedbytes, index, limit, start, addr); + break; + } + processedbytes += siz; + //Log.i(TAG, "" + index+processedbytes + " out of " + (limit - start)); + } + //if ((index - start) % 3200 == 0) + { + mBuilder.setProgress((int)(size), (int)(index - start), false); + // Displays the progress bar for the first time. + mNotifyManager.notify(0, mBuilder.build()); + runOnUiThread(runnableRequestLayout); + } + //dialog.setProgress((int)((float)(index-start) * 100 / (float)(limit-start))); + //dialog.setTitle("Disassembling.."+(index-start)+" out of "+(limit-start)); + } + Capstone.CsInsn[] insns=cs.disasm(filecontent, index, remain, addr, 0); + int processedbytes=0; + for (Capstone.CsInsn insn:insns) + { + //Capstone.CsInsn insn=insns[0]; + int siz=DoOneItem(insn); + if (siz == 0)//Broken Instruction + { + //disassemble remnants... + HandleBroken(processedbytes, index, limit, start, addr); + break; + } + processedbytes += siz; + Log.v(TAG, "" + index+processedbytes + " out of " + (limit - start)); + } + */ + } + /* + ///@Desc skips an instruction and disassembles after it + ///@Note currebtly only skips 4 bytes for ARM. + ///////!!!!!! Now use skipdata mode!!!!!!!!!! + private void HandleBroken(int pb, long index, long limit, long start, long addr) + { + Log.i(TAG,"handleBroken("+pb+","+index+","+addr+")"); + Capstone.CsInsn[] insns=cs.disasm(filecontent, pb + index + 4, BULK_SIZE - 4 - pb, addr + pb + 4, 0); + int processedbytes=pb+4; + for (Capstone.CsInsn insn:insns) + { + int siz=DoOneItem(insn); + if (siz == 0)//Broken Instruction + { + Log.i(TAG,"size 0"); + //disassemble remnants... + HandleBroken(processedbytes, index, limit, start, addr+pb); + break; + } + processedbytes += siz; + } + return ; + } + */ + ///@Param index: file offset of insn + /// //addr: virtual address of insn + private int DoOneItem(Capstone.CsInsn insn) + { + lvi = new ListViewItem(insn); + if (insn.size == 0) + { + insn.size = 4; + insn.mnemonic = "db"; + //insn.bytes = new byte[]{filecontent[(int)index],filecontent[(int)index + 1],filecontent[(int)index + 2],filecontent[(int)index + 3]}; + insn.opStr = ""; + Log.e(TAG, "Dar.size==0, breaking?"); + return 0; + } + //final ListViewItem lvi=new ListViewItem(dar); + //if (lvi.isBranch()) + { + //xrefComments.put(lvi.getTargetAddress(),lvi.address); + } + runOnUiThread(new Runnable(){ + @Override + public void run() + { + adapter.addItem(lvi); + adapter.notifyDataSetChanged(); + return ; + } + }); + //Log.v(TAG, "i=" + index + "lvi=" + lvi.toString()); + //if (index >= limit) + //{ + // Log.i(TAG, "index is " + index + ", breaking"); + //break; + //} + //Log.v(TAG, "dar.size is =" + dar.size); + return insn.size; +// index += insn.size; +// addr += insn.size; + } }); workerThread.start(); } @@ -554,27 +710,39 @@ public void AdjustShow(TextView t1v, TextView t2v, TextView t3v, TextView t4v, T t6v.setVisibility(isShowOperands() ? View.VISIBLE: View.GONE); t7v.setVisibility(isShowComment() ? View.VISIBLE: View.GONE); } - + public static final int REQUEST_WRITE_STORAGE_REQUEST_CODE=1; - public static void requestAppPermissions(Activity a) { - if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + public static void requestAppPermissions(Activity a) + { + if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) + { return; } - if (hasReadPermissions(a) && hasWritePermissions(a)) { - Log.i(TAG,"Has permissions"); + if (hasReadPermissions(a) && hasWritePermissions(a)&&hasGetAccountPermissions(a)) + { + Log.i(TAG, "Has permissions"); return; } a.requestPermissions(new String[] { - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - }, REQUEST_WRITE_STORAGE_REQUEST_CODE); // your request code + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.GET_ACCOUNTS + }, REQUEST_WRITE_STORAGE_REQUEST_CODE); // your request code } - public static boolean hasReadPermissions(Context c) { - return c.checkSelfPermission( Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + private static boolean hasGetAccountPermissions(Context c) + { + // TODO: Implement this method + return c.checkSelfPermission(Manifest.permission.GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED; } - public static boolean hasWritePermissions(Context c) { + public static boolean hasReadPermissions(Context c) + { + return c.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + } + + public static boolean hasWritePermissions(Context c) + { return c.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; } /** Called when the activity is first created. */ @@ -582,13 +750,15 @@ public static boolean hasWritePermissions(Context c) { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final Thread.UncaughtExceptionHandler ori=Thread.getDefaultUncaughtExceptionHandler(); + //final Thread.UncaughtExceptionHandler ori=Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){ @Override public void uncaughtException(Thread p1, Throwable p2) { // TODO: Implement this method - final Intent emailIntent = new Intent( android.content.Intent.ACTION_SEND); + requestAppPermissions(MainActivity.this); + String [] accs=getAccounts(); + final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); emailIntent.setType("plain/text"); @@ -597,16 +767,41 @@ public void uncaughtException(Thread p1, Throwable p2) emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Crash report"); - + StringBuilder content=new StringBuilder(Log.getStackTraceString(p2)); + content.append("Emails:"); + content.append(System.lineSeparator()); + for(String s:accs) + { + content.append(s); + content.append(System.lineSeparator()); + } emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, - Log.getStackTraceString(p2)); + content.toString()); startActivity(Intent.createChooser(emailIntent, "Send crash report as an issue by email")); - ori.uncaughtException(p1,p2); + // ori.uncaughtException(p1, p2); + Log.wtf(TAG,"UncaughtException",p2); return ; } + private String[] getAccounts() { + Pattern emailPattern = Patterns.EMAIL_ADDRESS; + Account[] accounts = AccountManager.get(MainActivity.this).getAccounts(); + if(accounts==null) + { + return new String[]{""}; + } + ArrayList accs=new ArrayList<>(); + for (Account account : accounts) { + if (emailPattern.matcher(account.name).matches()) { + String email = account.name; + accs.add(email); + //Log.d(TAG, "email : " + email); + } + } + return accs.toArray(new String[accs.size()]); + } }); - + /* Create a TextView and set its content. * the text is retrieved by calling a native * function. @@ -640,18 +835,23 @@ public void uncaughtException(Thread p1, Throwable p2) this.tab2 = (LinearLayout) findViewById(R.id.tab2); try { - cs = new Capstone(Capstone.CS_ARCH_ARM, Capstone.CS_MODE_ARM); - cs.setDetail(Capstone.CS_OPT_ON); - }catch(RuntimeException e) + if(Init()==-1) + { + throw new RuntimeException(); + } + //cs = new Capstone(Capstone.CS_ARCH_ARM, Capstone.CS_MODE_ARM); + //cs.setDetail(Capstone.CS_OPT_ON); + } + catch (RuntimeException e) { - Toast.makeText(this, "Failed to initialize the native engine: "+Log.getStackTraceString(e), 10).show(); + Toast.makeText(this, "Failed to initialize the native engine: " + Log.getStackTraceString(e), 10).show(); android.os.Process.killProcess(android.os.Process.getGidForName(null)); } - if (cs==null) + /*if (cs == null) { Toast.makeText(this, "Failed to initialize the native engine", 3).show(); android.os.Process.killProcess(android.os.Process.getGidForName(null)); - } + }*/ //tlDisasmTable = (TableLayout) findViewById(R.id.table_main); // TableRow tbrow0 = new TableRow(MainActivity.this); // CreateDisasmTopRow(tbrow0); @@ -666,13 +866,18 @@ public void onItemClick(AdapterView parent, View p2, int position, long id) ListViewItem lvi=(ListViewItem) parent.getItemAtPosition(position); if (lvi.isBranch()) { - + } // TODO: Implement this method return; } }); - + AlertDialog.Builder builder=new AlertDialog.Builder(this); + builder.setTitle("Permissions"); + builder.setCancelable(false); + builder.setMessage("- Read/Write storage(obvious)\r\n- GetAccounts: add email address info on crash report."); + builder.setPositiveButton("OK",(DialogInterface.OnClickListener)null); + builder.show(); requestAppPermissions(this); // ViewGroup.LayoutParams lp= listview.getLayoutParams(); //listview.setMinimumHeight(getScreenHeight()); @@ -740,9 +945,10 @@ protected void onDestroy() } catch (Exception e) {} - if(cs!=null) + Finalize(); + if (cs != null) cs.close(); - cs=(Capstone) null; + cs = (Capstone) null; //Finalize(); if (mNotifyManager != null) { @@ -827,6 +1033,7 @@ public void onClick(View v) private void showFileChooser() { + requestAppPermissions(this); Intent i=new Intent(this, FileSelectorActivity.class); startActivityForResult(i, REQUEST_SELECT_FILE); /* @@ -848,30 +1055,35 @@ private void showFileChooser() Toast.LENGTH_SHORT).show(); }*/ } -@Override -public void onRequestPermissionsResult(int requestCode, - String permissions[], int[] grantResults) { - switch (requestCode) { - case REQUEST_WRITE_STORAGE_REQUEST_CODE: { - // If request is cancelled, the result arrays are empty. - if (grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - - // permission was granted, yay! Do the - // contacts-related task you need to do. - - } else { - - // permission denied, boo! Disable the - // functionality that depends on this permission. - } - return; - } - - // other 'case' lines to check for other - // permissions this app might request - } -} + @Override + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) + { + switch (requestCode) + { + case REQUEST_WRITE_STORAGE_REQUEST_CODE: { + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) + { + + // permission was granted, yay! Do the + // contacts-related task you need to do. + + } + else + { + + // permission denied, boo! Disable the + // functionality that depends on this permission. + } + return; + } + + // other 'case' lines to check for other + // permissions this app might request + } + } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -954,14 +1166,14 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) } catch (IOException e) { - Log.e(TAG,"",e); - Toast.makeText(this,Log.getStackTraceString(e),30).show(); + Log.e(TAG, "", e); + Toast.makeText(this, Log.getStackTraceString(e), 30).show(); } } } super.onActivityResult(requestCode, resultCode, data); } - + private String getRealPathFromURI(Uri uri) { String filePath = ""; @@ -1013,11 +1225,11 @@ private ProgressDialog showProgressDialog(String s) public static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) + for (int p=0, j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + hexChars[p++] = hexArray[v >>> 4]; + hexChars[p++] = hexArray[v & 0x0F]; } return new String(hexChars); } @@ -1096,16 +1308,19 @@ public boolean isShowComment() * 'hello-jni' native library, which is packaged * with this application. */ - // public native String disassemble(byte [] bytes, long entry); - //public native int Init(); - //public native void Finalize(); + // public native String disassemble(byte [] bytes, long entry); + public native int Init(); + public native void Finalize(); /* this is used to load the 'hello-jni' library on application * startup. The library has already been unpacked into * /data/data/com.example.hellojni/lib/libhello-jni.so at * installation time by the package manager. */ - + static{ + System.loadLibrary("hello-jni"); + } + /* OnCreate() vp = (ViewPager)findViewById(R.id.pager); Button btn_first = (Button)findViewById(R.id.btn_first); diff --git a/app/src/main/res/layout/activity_made_by.xml b/app/src/main/res/layout/activity_made_by.xml index cebb9557..90f917f5 100644 --- a/app/src/main/res/layout/activity_made_by.xml +++ b/app/src/main/res/layout/activity_made_by.xml @@ -12,26 +12,25 @@ android:textAppearance="?android:attr/textAppearanceLarge" android:layout_width="wrap_content" android:typeface="serif" - android:textStyle="bold|italic" + android:textStyle="bold" android:textIsSelectable="true" android:textSize="40sp" - android:alpha="0.9" android:background="@drawable/cell_shape" - android:ellipsize="middle" android:gravity="right|center_vertical|fill|fill_vertical" - android:textColor="#99DF76" - android:shadowColor="#C4554E" - android:textColorHint="#AD413A" android:id="@+id/activitymadebyTextView1"/> + android:layout_width="wrap_content" + android:typeface="serif" + android:textStyle="bold" + android:textIsSelectable="true" + android:textSize="40sp" + android:background="@drawable/cell_shape" + android:gravity="right|center_vertical|fill|fill_vertical" + android:id="@+id/activitymadebyTextView2"/> diff --git a/app/src/main/res/xml/pref_settings.xml b/app/src/main/res/xml/pref_settings.xml index ddf735d1..bda2c88d 100644 --- a/app/src/main/res/xml/pref_settings.xml +++ b/app/src/main/res/xml/pref_settings.xml @@ -50,8 +50,8 @@ android:summary="@string/dev_info" android:title="@string/dev_info_detail" > + android:targetClass="com.kyhsgeekcode.disassembler.MadeByActivity" + android:targetPackage="com.kyhsgeekcode.disassembler" />