How to get references of variables in APK? - android

I'm doing the static analysis on Android APK file. Given the following source code:
protected void OkHttpClientCheck() throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://www.vogella.com/index.html")
.build();
Response response = client.newCall(request).execute();
}
So I can extract this source code uses OkHttpClient to open a connection and the target URL by using pattern matching (likes grep with regex). My question is, how do we map the OkHttpClient API with the corresponding url? In other words, I would like to output: "https://www.vogella.com/index.html" is called by OkHttpClient.
Can androguard do it or I need to perform static analysis with Soot or Flowdroid?
I have tried androguard but it could not extract the detail inside a method. Is it true or did I miss something?

Related

How to pass files to WEB API from Android

I have Web API service and Android Client to consume that service. Data parsing is working as expected. But now I have to transfer some documents/files to the web API. I have tried to pass in query parameter as string (after converting document to base64 string), which is working fine only for document having length of 2-3KB. But for large files (1-4MB) I get Socket timeout exception at android side I have tried with increasing the socket timeout for both android (okhttp client) and the web API from the C# code in controller.
please you can suggest me any other way that make it better. I know this is not the right way to pass files. I have max file size of 4-5 MB.
I am adding the code snippet of both Android and Web API. thanks in advance
C#:
[System.Web.Http.HttpPost]
public JsonResultModel SaveClaimDocument(string cd)
{
HttpContext.Current.Server.ScriptTimeout = 300;
.....
}
Android Code:
new Thread() {
#Override
public void run() {
super.run();
OkHttpClient client = SingleConnectionManager.getInstance().getConnectionWithHighTimeOut();
String url = "http://" + Constants.IP + "/api/ClaimDocuments/SaveClaimDocument?cd=" + file_base;
try {
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("test", cd)
.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
//Set Before New Connection Request
System.setProperty("http.keepAlive", "false");
client.newCall(request).enqueue(new Callback() {
Edit:
Android Exception

OkHttp MockWebServer with dynamic URLs using Retrofit

My app uses dynamic URLs to make web-service calls (on Android). baseUrl is set as empty and we pass Retrofit2 #Url parameters in the service interface:
public interface UserService {
#GET
public Call<ResponseBody> profilePicture(#Url String url);
}
We don't know the host/domain in advance, so MockWebServer is not able to intercept the requests. The call to fetch the initial list of dynamic URLs is made in different screens. One idea is to create a new flavor providing a local data source for URLs to be used, which is my fallback plan.
I am curious if MockWebServer has any other methods to help test such cases and can be limited to test code.
You could use an OkHttp interceptor to rewrite the hostname and port?
I was also facing the same kind of issue. When I use MockWebserver in testing I have to change base URL to target mock web server localhost and port. I tried this it is working fine.
private static final Interceptor mRequestInterceptor = new Interceptor() {
#Override
public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
final InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 8080);
HttpUrl httpUrl = request.url().newBuilder().scheme("http://").host(address.getHostName()).port(8080)
.build();
request = request.newBuilder()
.url(httpUrl)
.build();
return chain.proceed(request);
}
};
After this base url changes to "http://localhost:8080/"

How to access cookie and check if it has expired using okhttp3 and PersistentCookieStore?

I am working on an Android app in which a log in post request is made to a webservice. The request returns a cookie which expires in 20 minutes.
Using okhttp3 and this PersistentCookieStore library, I got the cookie to be stored and subsequently added it as request header to access authentication-required get requests (e.g. personal information that are non-public).
The code goes this way,
CookieJar myCookieJar = new PersistentCookieJar(new SetCookieCache(),
new SharedPrefsCookiePersistor(this));
OkHttpClient client = new OkHttpClient.Builder().cookieJar(HttpRequests.cookieJar).build();
I then call a method like this inside an (after I have gone through another log in Async task to get the cookie) Async task to perform a get request that requires authentication,
public static String PostReq(String url, String json) {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.addHeader("Cookie", "key=value")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
catch(Exception e){
}
}
The .addHeader("Cookie", "key=value") adds the cookie to the header to tell the webservice that I am authenticated.
Here comes my difficulty. Since the cookie expires after 20 minutes, I would like to be able to access the cookie itself to check for the expiration time and possibly redirect the user to the log in activity by calling the method,
myCookie.expiresAt()
and comparing it to
System.currentTimeMillis()
I tried to look at the PersistentCookieStore codes and found that it uses a SharedPreference with the key "CookiePersistence". I looked inside this file while my emulator was running the app and found it to be empty however.
How would I be able to access this cookie that I have obtained? Much thanks for any advice to be given.
OK, this is old, but I was facing the same problem, and here is how I fixed it.
Hold a reference to your SetCookieCache used to instantiate your CookieJar:
SetCookieCache cookieCache = new SetCookieCache();
CookieJar myCookieJar = new PersistentCookieJar(
cookieCache,
new SharedPrefsCookiePersistor(this)
);
Then use this to find your cookie and check it:
for (Cookie cookie : cookieCache) {
if (cookie.name().equals("cookie_name") && cookie.persistent()) {
//cookie is still good
break;
}
}
Or use cookie.expiresAt() to do your thing.

Okhttp Put method returning 'Method Not Allowed'

I am attempting to call a put method on my server using OkHttp from an Android application.
This is the api method signature:
public void Put(int userId, string regId)
{
}
This is the Android code to call the above method:
private boolean SendGCMRegIdToServer(String registrationId, Integer userId) throws IOException {
HttpUrl url = new HttpUrl.Builder()
.scheme("http")
.host(serverApiHost)
.addPathSegment("AppDashboard")
.addPathSegment("api")
.addPathSegment("GCM/")
.build();
MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
String json = "{'userId':" + userId + ","
+ "'regId':'" + registrationId + "'"
+ "}";
RequestBody requestBody = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.put(requestBody)
.build();
//this should post the data to my server
Response response = client.newCall(request).execute();
if(response.code() == 400)
return false;
return true;
}
Now the problem is I am getting the error code 405 in the response saying Method not allowed, but I cannot see where the problem is because I can successfully call the method using Postman on the server itself as below:
http://localhost/AppDashboard/api/GCM?userId=5&regId=123
I'm thinking it may have something to do with an integer or string being passed incorrectly in the JSON string, but cannot see why this isn't working.
i had the same problem and server was returning 405 . after some search i realized that is a configuration problem on IIS that does not let put requests. so there is no problem in android code and you should config your server to let this kind of requests.
see this , this and this
Ok thanks for replies guys but seems I was getting a little confused between the two methods I was using to pass the params to my API.
Here's what I did:
changed the signature of the method to post with a param [FromBody] as a Model (only supports one paramater)...
public void Post([FromBody]UserGcmRegIdModel model)
{
}
I was then able to change my method call to the following using a nicer JSONBuilder and using .post in the request builder rather than .put
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("UserId", userId);
jsonObject.put("RegId", registrationId);
} catch (JSONException e) {
e.printStackTrace();
}
String json = jsonObject.toString();
RequestBody requestBody = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
I still don't know if there is a problem with put() methods on IIS but using a post in my case was absolutely fine so I'm going with that...
I see two different approaches in your REST api calls. In the one of OkHttp you send a PUT method with a JSON object serialized, and in POSTMAN you send a PUT (although I guess you do a GET) request with the parameters within the URL, I mean not in JSON body structure.
Anyway, HTTP 405 is telling you that your backend does not support the PUT method, and probably it's expecting a POST method with the "X-HTTP-Method-Override:PUT" HTTP header since POST is more standard method in REST than PUT.
What would I do is check your POSTMAN request carefully and adjust the one of Android to be the same method, parameters and headers, not more.
Answer Update (as question has been updated)
Of course there is a problem with that verb, as I said above IIS handles only the standard methods and PUT is not one of those. You have three choices:
Change your PUT to POST.
Use POST with X-HTTP-Method-Override to PUT. (reference)
Modify IIS config to support non standard REST methods. I
personally wouldn't suggest the 3rd one, since it's attached to the
backend config (e.g. imagine you change IIS to NancyFX).

Opening the connection using okhttp

I'm trying to Open the connection using okhttp.
something like,
urlConnection = client.open(url);
does not work with the new ok-http.jar file.
It was working with 1.5.x of okhttp version
Any suggestions?
Thanks
Code from documentation
public static void main(String[] args) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://kenumir.pl/")
.build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
}
Method execute is the key ;-)
What does it means "it does not work"??? Does it fails at compile time or runtime? What kind of error does it shows? As of OkHttip 2.x.x, there's been a change in the way to open HttpUrlConnections, you need to include a new module and this should work:
// OkHttp 1.x:
HttpURLConnection connection = client.open(url);
// OkHttp 2.x:
HttpURLConnection connection = new OkUrlFactory(client).open(url);
see OkHttp Release notes for more information .

Categories

Resources