Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions jadx-core/src/main/java/jadx/core/utils/log/LogUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@
*/
public class LogUtils {

private static final Pattern ALFA_NUMERIC = Pattern.compile("\\w*");
/**
* We replace everything except alphanumeric characters, underscore, dots, colon, semicolon, comma,
* spaces, minus
*/
private static final Pattern REPLACE_PATTERN = Pattern.compile("[^\\w\\.:;, -]");

public static String escape(String input) {
if (input == null) {
return "null";
}
if (ALFA_NUMERIC.matcher(input).matches()) {
return input;
}
return input.replaceAll("\\W", ".");

return REPLACE_PATTERN.matcher(input).replaceAll(".");
}

public static String escape(byte[] input) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class LogUtilsTest {

@Test
void escape() {
assertThat(LogUtils.escape("Guest'%0AUser:'Admin")).isEqualTo("Guest..0AUser..Admin");
String src = "a.b,c:d;e disallowed\"a'b#c*d\te\rf\ng";
String out = "a.b,c:d;e disallowed.a.b.c.d.e.f.g";
assertThat(LogUtils.escape(src)).isEqualTo(out);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -26,7 +28,7 @@ public class LogcatController {
private final String timezone;
private LogcatInfo recent = null;
private List<LogcatInfo> events = new ArrayList<>();
private LogcatFilter filter = new LogcatFilter(null, null);
private LogcatFilter filter = new LogcatFilter();
private String status = "null";

public LogcatController(LogcatPanel logcatPanel, ADBDevice adbDevice) throws IOException {
Expand Down Expand Up @@ -155,7 +157,7 @@ public void clearEvents() {

public void exit() {
stopLogcat();
filter = new LogcatFilter(null, null);
filter = new LogcatFilter();
recent = null;
}

Expand All @@ -164,44 +166,25 @@ public LogcatFilter getFilter() {
}

public class LogcatFilter {
private final List<Integer> pid;
private List<Byte> msgType = new ArrayList<>() {
{
add((byte) 1);
add((byte) 2);
add((byte) 3);
add((byte) 4);
add((byte) 5);
add((byte) 6);
add((byte) 7);
add((byte) 8);
}
};

public LogcatFilter(ArrayList<Integer> pid, ArrayList<Byte> msgType) {
if (pid != null) {
this.pid = pid;
} else {
this.pid = new ArrayList<>();
}
private final Set<Integer> pid;
private final Set<Byte> msgType;

if (msgType != null) {
this.msgType = msgType;
}
public LogcatFilter() {
this(new TreeSet<>(), new TreeSet<>(List.of((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6, (byte) 7, (byte) 8)));
}

public void addPid(int pid) {
public LogcatFilter(Set<Integer> pid, Set<Byte> msgType) {
this.pid = pid;
this.msgType = msgType;
}

if (!this.pid.contains(pid)) {
this.pid.add(pid);
}
public void addPid(int pid) {
this.pid.add(pid);
}

public void removePid(int pid) {
int pidPos = this.pid.indexOf(pid);
if (pidPos >= 0) {
this.pid.remove(pidPos);
}
this.pid.remove(pid);
}

public void togglePid(int pid, boolean state) {
Expand All @@ -213,16 +196,11 @@ public void togglePid(int pid, boolean state) {
}

public void addMsgType(byte msgType) {
if (!this.msgType.contains(msgType)) {
this.msgType.add(msgType);
}
this.msgType.add(msgType);
}

public void removeMsgType(byte msgType) {
int typePos = this.msgType.indexOf(msgType);
if (typePos >= 0) {
this.msgType.remove(typePos);
}
this.msgType.remove(msgType);
}

public void toggleMsgType(byte msgType, boolean state) {
Expand All @@ -234,10 +212,7 @@ public void toggleMsgType(byte msgType, boolean state) {
}

public boolean doFilter(LogcatInfo inInfo) {
if (pid.contains(inInfo.getPid())) {
return msgType.contains(inInfo.getMsgType());
}
return false;
return (pid.contains(inInfo.getPid())) && msgType.contains(inInfo.getMsgType());
}

public List<LogcatInfo> getFilteredList(List<LogcatInfo> inInfoList) {
Expand Down
79 changes: 56 additions & 23 deletions jadx-gui/src/main/java/jadx/gui/device/protocol/ADB.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand All @@ -24,17 +28,20 @@
import jadx.gui.utils.IOUtils;

public class ADB {

public static final Charset ADB_CHARSET = StandardCharsets.UTF_8;

private static final Logger LOG = LoggerFactory.getLogger(ADB.class);

private static final int DEFAULT_PORT = 5037;
private static final String DEFAULT_ADDR = "localhost";

private static final String CMD_FEATURES = "000dhost:features";
private static final String CMD_TRACK_DEVICES = "0014host:track-devices-l";
private static final byte[] OKAY = "OKAY".getBytes();
private static final byte[] FAIL = "FAIL".getBytes();
private static final byte[] OKAY = "OKAY".getBytes(ADB_CHARSET);
private static final byte[] FAIL = "FAIL".getBytes(ADB_CHARSET);

static boolean isOkay(InputStream stream) throws IOException {
static boolean isOkay(InputStream stream, String command) throws IOException {
byte[] buf = IOUtils.readNBytes(stream, 4);
if (Arrays.equals(buf, OKAY)) {
return true;
Expand All @@ -45,13 +52,13 @@ static boolean isOkay(InputStream stream) throws IOException {
// int msgLen = Integer.parseInt(new String(IOUtils.readNBytes(stream, 4)), 16);
// byte[] errorMsg = IOUtils.readNBytes(stream, msgLen);
// LOG.error("isOkay failed: received error message: {}", new String(errorMsg));
LOG.error("isOkay failed");
LOG.error("isOkay failed for command: {}", command);
return false;
}
if (buf == null) {
throw new IOException("isOkay failed - steam ended");
}
throw new IOException("isOkay failed - unexpected response " + new String(buf));
throw new IOException("isOkay failed - unexpected response " + new String(buf, ADB_CHARSET));
}

public static byte[] exec(String cmd, OutputStream outputStream, InputStream inputStream) throws IOException {
Expand All @@ -73,13 +80,13 @@ public static Socket connect(String host, int port) throws IOException {
}

static boolean execCommandAsync(OutputStream outputStream, InputStream inputStream, String cmd) throws IOException {
outputStream.write(cmd.getBytes());
return isOkay(inputStream);
outputStream.write(cmd.getBytes(ADB_CHARSET));
return isOkay(inputStream, "execCommandAsync");
}

private static byte[] execCommandSync(OutputStream outputStream, InputStream inputStream, String cmd) throws IOException {
outputStream.write(cmd.getBytes());
if (isOkay(inputStream)) {
outputStream.write(cmd.getBytes(ADB_CHARSET));
if (isOkay(inputStream, "execCommandSync")) {
return readServiceProtocol(inputStream);
}
return null;
Expand All @@ -91,7 +98,7 @@ static byte[] readServiceProtocol(InputStream stream) {
if (buf == null) {
return null;
}
int len = unhex(buf);
int len = hexToInt(buf);
byte[] result;
if (len == 0) {
result = new byte[0];
Expand All @@ -111,13 +118,15 @@ static byte[] readServiceProtocol(InputStream stream) {
}

static boolean setSerial(String serial, OutputStream outputStream, InputStream inputStream) throws IOException {
checkSerial(serial);
LOG.trace("setSerial({})", serial);
String setSerialCmd = String.format("host:tport:serial:%s", serial);
setSerialCmd = String.format("%04x%s", setSerialCmd.length(), setSerialCmd);
outputStream.write(setSerialCmd.getBytes());
boolean ok = isOkay(inputStream);
outputStream.write(setSerialCmd.getBytes(ADB_CHARSET));
boolean ok = isOkay(inputStream, setSerialCmd);
if (ok) {
// skip the shell-state-id returned by ADB server, it's not important for the following actions.
IOUtils.readNBytes(inputStream, 8);
inputStream.readNBytes(8);
} else {
LOG.error("setSerial command {} failed", LogUtils.escape(setSerialCmd));
}
Expand All @@ -127,8 +136,8 @@ static boolean setSerial(String serial, OutputStream outputStream, InputStream i
private static byte[] execShellCommandRaw(String cmd, OutputStream outputStream, InputStream inputStream) throws IOException {
cmd = String.format("shell,v2,TERM=xterm-256color,raw:%s", cmd);
cmd = String.format("%04x%s", cmd.length(), cmd);
outputStream.write(cmd.getBytes());
if (isOkay(inputStream)) {
outputStream.write(cmd.getBytes(ADB_CHARSET));
if (isOkay(inputStream, cmd)) {
return ShellProtocol.readStdout(inputStream);
}
return null;
Expand All @@ -144,7 +153,7 @@ static byte[] execShellCommandRaw(String serial, String cmd, OutputStream output
public static List<String> getFeatures() throws IOException {
byte[] rst = exec(CMD_FEATURES);
if (rst != null) {
return Arrays.asList(new String(rst).trim().split(","));
return Arrays.asList(new String(rst, ADB_CHARSET).trim().split(","));
}
return Collections.emptyList();
}
Expand Down Expand Up @@ -202,7 +211,7 @@ public static Socket listenForDeviceState(DeviceStateListener listener, String h
break; // socket disconnected
}
if (listener != null) {
String payload = new String(res);
String payload = new String(res, ADB_CHARSET);
String[] deviceLines = payload.split("\n");
List<ADBDeviceInfo> deviceInfoList = new ArrayList<>(deviceLines.length);
for (String deviceLine : deviceLines) {
Expand All @@ -225,11 +234,11 @@ public static List<String> listForward(String host, int port) throws IOException
String cmd = "0011host:list-forward";
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
outputStream.write(cmd.getBytes());
if (isOkay(inputStream)) {
outputStream.write(cmd.getBytes(ADB_CHARSET));
if (isOkay(inputStream, "listForward")) {
byte[] bytes = readServiceProtocol(inputStream);
if (bytes != null) {
String[] forwards = new String(bytes).split("\n");
String[] forwards = new String(bytes, ADB_CHARSET).split("\n");
return Stream.of(forwards).map(String::trim).collect(Collectors.toList());
}
}
Expand All @@ -244,8 +253,8 @@ public static boolean removeForward(String host, int port, String serial, String
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
if (setSerial(serial, outputStream, inputStream)) {
outputStream.write(cmd.getBytes());
return isOkay(inputStream) && isOkay(inputStream);
outputStream.write(cmd.getBytes(ADB_CHARSET));
return isOkay(inputStream, "removeForward1") && isOkay(inputStream, "removeForward2");
}
}
return false;
Expand All @@ -267,7 +276,21 @@ private static byte[] appendBytes(byte[] dest, byte[] src, int realSrcSize) {
return rst;
}

private static int unhex(byte[] hex) {
private static final Pattern SERIAL_PATTERN = Pattern.compile("^[\\w-]{10,20}$");

private static void checkSerial(String serial) {
if (!SERIAL_PATTERN.matcher(serial).matches()) {
throw new IllegalArgumentException("Invalid serial: " + serial);
}
}

/**
* Convert 4 hex characters to int
*
* @param hex
* @return
*/
private static int hexToInt(byte[] hex) {
int n = 0;
byte b;
for (int i = 0; i < 4; i++) {
Expand Down Expand Up @@ -340,6 +363,16 @@ public static Process make(String processLine) {
}
return null;
}

@Override
public String toString() {
return new StringJoiner(", ", Process.class.getSimpleName() + "[", "]")
.add("user='" + user + "'")
.add("pid='" + pid + "'")
.add("ppid='" + ppid + "'")
.add("name='" + name + "'")
.toString();
}
}

private static class ShellProtocol {
Expand Down
Loading