how to resize the screenshot of Android using adbkit? - android

I use client.screencap method from adbkit to get the PNG stream and save the image like this:
let stream = await client.screencap(deviceId);
stream.pipe(fs.createWriteStream('output.png'));
Rather, I want to resize it first because the output image is so big ( around 2 - 3 Mb ). So I try to get the buffer of the stream and resize it by reducing width, height (use Jimp library) and save the image.
let stream = await client.screencap(deviceId);
let chunks = [];
for await (const chunk of stream) {
chunks.push(chunk);
}
let buffer = Buffer.concat(chunks);
console.log(buffer);
// resize and save (Use Jimp library to read the buffer and resize)
...
in console.log(buffer), I got
<Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 00 00 01 73 ae ce 1c e9 00 00 00 04 ... 159002 more bytes>
But sometime I got empty buffer like this:
<Buffer >
I don't know why the buffer is empty. Because of client.screencap method is not stable?
Or they are an any better solution to do a thing like this?

Related

Get Card Number and Expire Data of Visa card through APDU commands (ISO 7816)

Trying to get cardNumber and expire data of my visa card, but always get 6700 response.
// 80 A8 00 00 12 83 10 F6 20 C0 00 00 00 00 00 00 01 76 20 60 B9 06 43 00
val step3 = sendCommand("80A80000128310F620C000000000000001762060B9064300")
val targetInfo = getTagValue(step3!!, "57")
val targetInfoTokens = targetInfo!!.split("D").toTypedArray()
val cardNumber = targetInfoTokens[0]
val expireDate = targetInfoTokens[1].substring(0, 4)
return BankCardInfo(cardNumber, expireDate, type)
For example, with MIR cards reading is ok.
// 80 A8 00 00 11 83 0F 00 06 43 00 00 00 00 00 01 22 8E 00 B0 50 05 00
val step3 = sendCommand("80A8000011830F000643000000000001228E00B0500500")
// 00 B2 01 14 00
val step4 = sendCommand("00B2011400")!!
val cardNumber = getTagValue(step4, "5A")!!
val expireDate = getTagValue(step4, "24")!!
return BankCardInfo(cardNumber, expireDate, type)
I tried other commands, I tried to figure out this topic, but nothing worked.
I would like a list of commands, how can I get the data I need.
You should at least first select the application like this 00A40400 07A000000003101000 for visa. Then send procession options and read all the records you got on tag APPLICATION_FILE_LOCATOR. Credit card information will not always be on the same record. You cannot hardcode the record you read.

How to parse multiline response of 09 04 PID from OBD adapter in Android

I am getting raw data from OBD adapter, It is getting parsed for single line but for multiline response I am not able to parse.
I used below code to parse
String hexaData = getResult(); // getResult is here the raw data("4904014A4D422A490402333637364904033135303049040400000000") after parsing I am getting parsed value(JMB*36761500) which is correct and only working for single line
Log.i("CalID_hexa", hexaData);
final String result = getResult();
String workingData;
if (result.contains(":")) {//CAN(ISO-15765) protocol.
workingData = result.replaceAll(".:", "").substring(9);//9 is xxx49040701, xxx is bytes of information to follow.
Matcher m = Pattern.compile("[^a-z0-9 ]", Pattern.CASE_INSENSITIVE).matcher(convertHexToString(workingData));
if(m.find()) workingData = result.replaceAll("0:49", "").replaceAll(".:", "");
} else {//ISO9141-2, KWP2000 Fast and KWP2000 5Kbps (ISO15031) protocols.
workingData = result.replaceAll("49040.", "");
}
calId = convertHexToString(workingData).replaceAll("[\u0000-\u001f]", "");
L.stringStringHashMap.put("CAL_ID",calId);
public String convertHexToString(String hex) {
StringBuilder sb = new StringBuilder();
//49204c6f7665204a617661 split into two characters 49, 20, 4c...
for (int i = 0; i < hex.length() - 1; i += 2) {
//grab the hex in pairs
String output = hex.substring(i, (i + 2));
//convert hex to decimal
int decimal = Integer.parseInt(output, 16);
//convert the decimal to character
sb.append((char) decimal);
}
return sb.toString();
}
How to parse multiline response like below response on PID 09 04 from OBD Adapter:
18 DA F1 11 10 13 49 04 01 33 37 38
18 DA F1 1D 10 13 49 04 01 33 37 38
18 DA F1 11 21 30 35 2D 52 59 45 2D
18 DA F1 11 22 41 37 34 30 00 00 55
18 DA F1 1D 21 30 36 2D 52 59 45 2D
18 DA F1 1D 22 41 37 37 30 00 00 55
How can I parse the above?
If you want to parse multiple line responses as single line responses then you can first form the array from the multiple line response separating the lines by character \n. After forming the array of responses, you can join the strings in one single line.
You have two issues here. The first is that you sent your request using a broadcast address, that's why two ECUs (namely, 18 DA F1 11 and 18 DA F1 1D) answered to your request. You either have to sort these out or ask only one ECU directly.
The second is you should learn about ISO 15765-2 (also named ISO-TP), which is a transport protocol, much like TCP (or rather IP) is for Ethernet. https://en.wikipedia.org/wiki/ISO_15765-2 contains a rough outline.
A general notice: If you're serious about implementing OBD2 communication, write a layered architecture, in which the communication layer (BLE, TTY, TCP, etc.) sits below the vehicle protocol which ISO-TP sits on top of. On the actual application layer you can then decode the individual PIDs and their measurements.

Is this native code possible for further static analysis?

I was trying to reverse engineer a native lib code in an android app. the .so contains many functions. But the function sUQWWyTBEs() was referred in the Java code. I was curious how this function works.
This function returns a string like this 47fjlkj843h9asjklj94kljfsad93j4l2715943hasd... but what I wanted is that how this value was generated or returned.
the code of the function sUQWWyTBEs() decompiled with Ghidra:
*************************************************************
* FUNCTION
*************************************************************
undefined __cdecl Myapp_sUQWWyTBEs()
undefined w0:1 <RETURN>
longlong * x0:8 param_1
Myapp_sUQWWyTBEs XREF[2]: Entry Point (*) , 00101350
00100e44 08 00 40 f9 ldr x8, [param_1 ]
00100e48 01 00 00 b0 adrp x1, s_c7a584936712f32773d3d0a_00101000 ; = "c7a584936712f32773d3d0a"
00100e4c 21 60 08 91 add x1, x1, #0x218
00100e50 02 9d 42 f9 ldr x2, [x8, #0x538 ]
00100e54 40 00 1f d6 br x2
in my understanding, I have made the static analysis as like following:
00100e44 08 00 40 f9 ldr x8, [param_1 ]
load the value at memory address param_1 into register x8.
0100e48 01 00 00 b0 adrp x1, s_c7a584936712f32773d3d0a_00101000
sets register x1 to 0x101000.
00100e4c 21 60 08 91 add x1, x1, #0x218
adds 0x218 to x1, so it sets x1 to 0x101218.
00100e50 02 9d 42 f9 ldr x2, [x8, #0x538 ]
loads the value at x8 + 0x538 into x2.
00100e54 40 00 1f d6 br x2
and finally branches to the address stored in x2.
with that being said, Here I don't know the memory at address at x2, obviously it initially depends on the value param_1 holds. is there way or how can I refer where param_1 was initialized? I don't know very much about usage of Ghidra or other reverse engineering tools. any one might help would be appreciated.
Assuming this function is declared on the Java side as a native function, param_1 is a JNIEnv*. The Android JNI documentation states:
JNI defines two key data structures, "JavaVM" and "JNIEnv". Both of these are essentially pointers to pointers to function tables.
The code you show thus basically calls the function in the function table at offset 0x538. Assuming you're showing a 64-bit Android program, function pointers are 8 bytes so you need to figure out the 167th function pointer (starting from 0).
Take your copy of jni.h and extract the members of struct JNINativeInterface, number them starting from 0:
0: void* reserved0;
1: void* reserved1;
2: void* reserved2;
3: void* reserved3;
4: jint (*GetVersion)(JNIEnv *);
...
167: jstring (*NewStringUTF)(JNIEnv*, const char*);
So, assuming I did not make any mistakes, the code you are showing calls env->NewStringUTF with s_c7a584936712f32773d3d0a_00101000+0x218 as argument.
I think you can let Ghidra parse jni.h to make those types available. If you then change the type of param_1, that might be sufficient to let Ghidra do this mapping for you and produce a sensible decompilation to C/C++.

Getting onCharacteristicWrite status=0, but BLE device does not send any data

I am sending this command AE A7 04 00 05 09 BC B7 to BLE, onCharacteristicWrite returns status=0, but BLE device does not send any data ( I mean I do not get any response ). So what is wrong ? Maybe I am sending in a wrong format ?
public void WriteValue()
{
mNotifyCharacteristic.setValue("AE A7 04 00 05 09 BC B7".getBytes());
mBluetoothGatt.writeCharacteristic(mNotifyCharacteristic);
}
On Android try set write type to WRITE_TYPE_NO_RESPONSE
Btw, you should use LightBlue to test first https://itunes.apple.com/us/app/lightblue-explorer-bluetooth-low-energy/id557428110?mt=8
Try to replace the third line with mNotifyCharacteristic.setValue(new byte[]{(byte)0xAE, (byte)0xA7, 4, 0, 5, 9, (byte)0xBC, (byte)0xB7});
Test use byte[ ]
I think it good then use getbyte
I use byte[ ] can write successful
You can try it
Byte[] data = new byte[5];
data[0]=xx;
data[1]=xx;
........
Characteristic.Setvalue(data);
If not work try use other road
Not the same characteristic

File access and retrieval within an android library

There must be some sort of small technical error that I am performing here that I cannot get a grasp on. The file is in the raw/ directory of the AndroidLibrary, and access to different files are being used just fine in this manner. Perhaps there is a slight error here that I keep glazing over?
Note: The raw resource is in an uncompressed format so that it can be read in with a .jet extension so that there are not any complaints by the internal file system.
Edit (Update): Apparently in order to get the stream open, the openRawResourceFd was not enough. In addition to that I needed to call assetDescriptor.createInputStream(); If I did not, the stream would not behave properly. Odd, as I would expect the openRawResourceFd to do the trick.
AssetFileDescriptor assetDescriptor = resources.openRawResourceFd(com.grubulon.R.raw.testing_patches);
BufferedReader bufferedInputStream = new BufferedReader(new FileReader(assetDescriptor.getFileDescriptor()));
colorSpace = bufferedInputStream.readLine();
while ((currentLine = bufferedInputStream.readLine()) != null)
{
rgbValues = currentLine.split("\\t");
red = Integer.parseInt(rgbValues[0]);
green = Integer.parseInt(rgbValues[1]);
blue = Integer.parseInt(rgbValues[2]);
rgbPatches.add(new RgbColorValue(red, green, blue));
}
bufferedInputStream.close();
assetDescriptor.close();
The file itself is really only an Excel spreadsheet of RGB color values that are being read in with tabs in between them. The tab component does not seem to be the issue, but the first line is a garble of lots and lots of text. Not the color space, or values at all for that matter. I am not sure what is going on here.
File example:
RGB
0 0 0
17 17 17
34 34 34
51 51 51
68 68 68
85 85 85
102 102 102
119 119 119
136 136 136
153 153 153
170 170 170
187 187 187
204 204 204
221 221 221
238 238 238
255 255 255
255 0 0
0 255 0
0 0 255
The following is an example of what is coming across in the Logcat even though there should be very little text coming across from the file.
The following based upon the update above is what has resolved the problem. Notice the line after the assetDescriptor is created with the openRawResourceFd call.
AssetFileDescriptor assetDescriptor = resources.openRawResourceFd(com.grubulon.R.raw.testing_patches);
assetDescriptor.createInputStream();
BufferedReader bufferedInputStream = new BufferedReader(new FileReader(assetDescriptor.getFileDescriptor()));
colorSpace = bufferedInputStream.readLine();
while ((currentLine = bufferedInputStream.readLine()) != null)
{
rgbValues = currentLine.split("\\t");
red = Integer.parseInt(rgbValues[0]);
green = Integer.parseInt(rgbValues[1]);
blue = Integer.parseInt(rgbValues[2]);
rgbPatches.add(new RgbColorValue(red, green, blue));
}
bufferedInputStream.close();
assetDescriptor.close();

Categories

Resources