Confused about the `move-result-wide` smali instruction - android

The following smali codes, trying to move a 64-bit result to the register v4. But the size of the v4 is 32-bit. So how does the v4 store the value?
invoke-virtual {v0}, Landroid/location/Location;->getTime()J
move-result-wide v4

The move-result-wide vx instruction will move the long/double result value of the previous method invocation into vx,vx+1.
See Dalvik opcodes.

Related

Google Play Warning: SSL Error Handler Vulnerability have a False Positive for WebViewClient.onReceivedSslErrorHandler SSL

I am contributor for a shared library project that just received notice one of our customers received this warning from the Google Play Store,
Hello Google Play Developer, In July, the app submissions listed at
the end of this email were rejected due to an unsafe implementation of
the WebViewClient.onReceivedSslErrorHandler. This implementation
ignores all SSL certificate validation errors, making your app
vulnerable to man-in-the-middle attacks. An attacker could change the
affected WebView's content, read transmitted data (such as login
credentials), and execute code inside the app using JavaScript.
When looking into our AuthorizationWebViewClient which extends WebViewClient, we do not implement onReceivedSslErrorHandler, meaning we fall under the default implementation putting this library in the clear.
Can we get confirmation if this is a false positive or if there are changes that have to be made to this library?
UPDATE:
This was due to the version of the SDK used being much older when this vulnerability was present, the current codebase does not have this issue hence the disconnect.
I'm not sure what the specific app in question is, but there are apps which have a vulnerable com.microsoft.services.msa.AuthorizationRequest$OAuthDialog$AuthorizationWebViewClient.
For example, disassembling the code of one app shows that it does in fact have an onReceivedSslErrorHandler implementation.
.method public onReceivedSslError(Landroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V
.registers 4
.param p1, "view" # Landroid/webkit/WebView;
.param p2, "handler" # Landroid/webkit/SslErrorHandler;
.param p3, "error" # Landroid/net/http/SslError;
.prologue
.line 143
invoke-virtual {p2}, Landroid/webkit/SslErrorHandler;->proceed()V
.line 144
return-void
.end method

Smali - Undeclared static method

After compiling a certain apk and going through the smali code I stumbled upon this line in file com/name/name/r.smali:
invoke-static {v1, v0, v2}, Lcom/name/name/p;->a(Ljava/lang/String;Ljava/util/List;Lcom/name/name/CallbackI;)V
name is a placeholder in this situation
Unfortunately both of the classes p and CallbackI don't exist in com/name/name, how is this possible?
There are a few possibilities:
The code referencing those missing classes is dead code that never gets executed.
The app crashes when it tries to run that code.
The classes are defined elsewhere. Is the app using multi-dex? Or maybe the app uses a DexClassLoader to load another dex file?

Redundant opcodes in Android dex

I'm looking into some Android performance issues at the moment and noticing some sub-optimal patterns in the dex code. I'm just wondering if anyone knows if this is to be expected, and what the rationale behind it might be.
For example, consider the following Java code:
m_testField += i;
doSomething(m_testField);
When this is built and then run through baksmali it looks like the following:
iget v1, p0, Lcom/example/MainActivity$FieldTest;->m_testField:I
add-int/2addr v1, v0
iput v1, p0, Lcom/example/MainActivity$FieldTest;->m_testField:I
iget v1, p0, Lcom/example/MainActivity$FieldTest;->m_testField:I
invoke-direct {p0, v1}, Lcom/example/MainActivity$FieldTest;->doSomething(I)V
The part that's concerning me is the iget opcode to read the value of the instance field into register v1. The same field was written from the very same v1 register in the preceding opcode, so the opcode would appear to be completely redundant.
The only thing I can think of is that this is done to make this more thread-safe. But surely that should be the programmer's responsibility (by using sync blocks) instead of the compiler's responsibility. Although I'm not 100% certain, I think the above behaviour is quite different to what most C/C++ compilers would do.
I should say that essentially the same dex is produced when ProGuard is used. I should also probably mention that I'm using the very latest Android tools and a late model JDK.
Every access to a field is independent. To get the behavior you describe, you need to add an extra local variable:
int local = m_testField; // iget
local = local + i;
m_testField = local; // iput
doSomething(local);
That said, some combination of the interpreter, just-in-time compiler and ahead-of-time compiler may end up making these optimizations for you at runtime anyway.
On a hunch, I've done some further research and I think I'm in a position to answer my own question...
The sub-optimal dex seems to be a by-product of the fact that it is generated from standard Java bytecode which is stack-based rather than register-based. I disassembled the .class file corresponding to the sample code in my question. The relevant section looks like this:
5: aload_0
6: dup
7: getfield #22 // Field m_testField:I
10: iload_1
11: iadd
12: putfield #22 // Field m_testField:I
15: aload_0
16: aload_0
17: getfield #22 // Field m_testField:I
20: invokespecial #33 // Method doSomething:(I)V
After the iadd opcode on line 11 is executed, the value of m_testField is at the top of the stack and the 'this' reference is second from the top. The problem is that the putfield opcode on line 12 removes these from the stack. This means that the field value has to be re-pushed to the stack on line 17.
I must say I'm pretty surprised by this inefficiency. I'd have thought that the dx tool that converts bytecode to dex would be clever enough to remove this redundancy. I'm just hoping that ART is clever enough to do this at runtime instead.

what is meaning of .prologue in a smali file?

I diassembled a simple android app using apktool and it generated some smali codes.other things are understandable but i am not getting the meaning of .prologue in the smali code.please help me
Here other variables are self understanding linke invoke and locals but what does this .prologue do??
# direct methods
.method public constructor <init>()V
.locals 0
.prologue # What does this do?
.line 17
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
return-void
.end method
This is equivalent to the DBG_SET_PROLOGUE_END debug opcode in the dex file, as documented here.
sets the prologue_end state machine register, indicating that the next
position entry that is added should be considered the end of a method
prologue (an appropriate place for a method breakpoint). The
prologue_end register is cleared by any special (>= 0x0a) opcode.

smali: String Constants

Is there anything else that must be done to load a String constant into a register, and then using it in a method invocation, besides doing:
const-string v6, "TEST CONSTANT"
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
?
the following block of instructions
iget-object v4, p0, Lcom/mypackage/MyClass;->myList:Ljava/util/List;
invoke-interface {v4, p1}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_0
const-string v6, "TEST CONSTANT"
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_0
invoke-interface {v4, p2}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_1
invoke-static {v6, p2}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_1
gave me the following logcat error messages:
10-29 23:37:37.191: W/dalvikvm(515): VFY: register1 v6 type 2, wanted ref
10-29 23:37:37.241: W/dalvikvm(515): VFY: bad arg 0 (into Ljava/lang/String;)
10-29 23:37:37.241: W/dalvikvm(515): VFY: rejecting call to Landroid/util/Log;.wtf (Ljava/lang/String;Ljava/lang/String;)I
10-29 23:37:37.241: W/dalvikvm(515): VFY: rejecting opcode 0x71 at 0x0028
Your suspicions in this case are correct. The problem is because at the second Log->wtf instance, v6 was not necessarily set.
As to why this happens, it's important to note that very little verification is done when re-assembling the bytecode. In many cases, the assembler simply does not have enough information to do this level of verification - this would require the assembler have knowledge of the full set of classes that will be present when the application runs, similar to the case of deodexing (-o) or generating register info (-r).
These types of problems are caught by dalvik when verifies the bytecode, which is exactly what the error you mentioned is from.
Additionally, you mention "the values i used for p1 and p2 would have failed both if-eqz tests". This does not matter to dalvik's bytecode verifier. The verifier makes sure that all code paths are valid. It can't know or assume any particular value for the parameters that are passed in to the method.
If you want to see some additional information related to how the register types are propagated throughout the method, you can try the -r option for baksmali.
# grab the full framework directory from your device
adb pull /system/framework framework
# run baksmali with the -r command
baksmali -r ARGS,DEST,FULLMERGE -d framework <apk_or_dex_file>
This will add comments before/after every instruction with detailed information about the types of registers at that position.
i changed some things around and got it to work, but i'm not sure why...
the change i did was to move the constant loading (const-string v6, "TEST CONSTANT") outside of the "if-block", resulting in
const-string v6, "TEST CONSTANT"
iget-object v4, p0, Lcom/mypackage/MyClass;->myList:Ljava/util/List;
invoke-interface {v4, p1}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_0
invoke-static {v6, p1}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_0
invoke-interface {v4, p2}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :cond_not_met_1
invoke-static {v6, p2}, Landroid/util/Log;->wtf(Ljava/lang/String;Ljava/lang/String;)I
:cond_not_met_1
i suspect the reason for the initial problem is that if the flow bypassed the first "if-block" but entered the second "if-block", then the register v6 would not yet have been loaded before it was used.
the reason why i'm not so sure is because, when i ran the reassembled programme, the values i used for p1 and p2 would have failed both if-eqz tests (i.e. the flow would enter both "if-blocks").
so it seemed that,
1. the check for register v6 to be loaded before it was used was done preemptively before the actual control flow?
2. i thought such checking is only done at compile time?
i'm posting this as an answer as i needed more space to explain what i did. however, i'm still curious as to why such a change got it to work, so if anyone could give an explanation i'll mark that as the answer, thanks!

Categories

Resources