Skip to content

Commit e44d579

Browse files
committed
configfs: support mouse gadget
- check interruption signal in more places
1 parent e469bdd commit e44d579

File tree

15 files changed

+613
-512
lines changed

15 files changed

+613
-512
lines changed

app/src/main/assets/scripts/downloadrun.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ while true do
2424
if runAs then
2525
-- when running elevated prompt sometimes it pops in background, so we need
2626
-- to go to the desktop
27-
kb.press_keys(kb.LSUPER, kb.D)
27+
kb.press_keys(MOD_LSUPER, KEY_D)
2828
usb.delay(500)
29-
kb.press_keys(kb.LSUPER, kb.R)
29+
kb.press_keys(MOD_LSUPER, KEY_R)
3030
usb.delay(2000)
3131
kb.send_string("powershell Start-Process powershell -Verb runAs\n")
3232
usb.delay(3000)
33-
kb.press_keys(kb.LALT, kb.Y)
33+
kb.press_keys(MOD_LALT, KEY_Y)
3434
usb.delay(2000)
3535
else
36-
kb.press_keys(kb.LSUPER, kb.R)
36+
kb.press_keys(MOD_LSUPER, KEY_R)
3737
usb.delay(2000)
3838
kb.send_string("powershell\n")
3939
usb.delay(2000)
File renamed without changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
usb = luausb.create({ type = "mouse", id = 0 })
2+
3+
ms1 = usb.dev[1]
4+
5+
while true do
6+
ms1.click(BTN_LEFT)
7+
ms1.move(30, 0)
8+
ms1.scroll(128)
9+
usb.delay(1000)
10+
end

app/src/main/assets/scripts/wallpaper.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
usb = luausb.create({ id = 0, type = "keyboard" })
66
kb = usb.dev[1]
77

8-
local file = usb.ask("Wallpaper to download?", "https://i.redd.it/ur1mqcbpxou51.png")
8+
local file = usb.ask("Wallpaper to download?", "https://i.imgur.com/46wWHZ3.png")
99

1010
while true do
1111
usb.log("idle")
@@ -18,7 +18,7 @@ while true do
1818
usb.log("running")
1919
usb.delay(1000)
2020

21-
kb.press_keys(kb.LSUPER, kb.R)
21+
kb.press_keys(MOD_LSUPER, KEY_R)
2222
usb.delay(2000)
2323
kb.send_string("powershell\n")
2424
usb.delay(2000)

app/src/main/java/org/netdex/hidfuzzer/configfs/UsbGadget.java

Lines changed: 68 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -30,52 +30,46 @@ public Parameters(String manufacturer, String serial,
3030
}
3131
}
3232

33-
public static final String CONFIG_DIR = "c.1";
33+
private static final String CONFIG_DIR = "c.1";
34+
// https://android.googlesource.com/platform/system/core/+/master/rootdir/init.usb.configfs.rc
35+
private static final String SYSTEM_GADGET = "g1";
3436

35-
private final Parameters params_;
36-
private final String name_;
37+
private final String gadget_name_;
3738
private final String configFsPath_;
3839

3940
private final ArrayList<UsbGadgetFunction> functions_;
4041

41-
private String oldGadgetUsingUDC_ = null;
42-
private String oldGadgetUDCDriver_ = null;
43-
44-
public UsbGadget(Parameters parameters, String name, String configFsPath) {
45-
this.params_ = parameters;
46-
this.name_ = name;
42+
public UsbGadget(String name, String configFsPath) {
43+
this.gadget_name_ = name;
4744
this.configFsPath_ = configFsPath;
4845

4946
this.functions_ = new ArrayList<>();
5047
}
5148

52-
public void addFunction(UsbGadgetFunction function) {
53-
functions_.add(function);
54-
}
55-
56-
public void create(Shell.Threaded su) throws Shell.ShellDiedException {
57-
String gadgetPath = getGadgetPath();
58-
if (Command.pathExists(su, gadgetPath)) {
49+
public void create(Shell.Threaded su, Parameters params) throws Shell.ShellDiedException {
50+
String gadgetPath = getGadgetPath(gadget_name_);
51+
if (!Command.getSystemProp(su, "sys.usb.configfs").equals("1"))
52+
throw new IllegalStateException("Device does not support ConfigFS");
53+
if (isCreated(su))
5954
throw new IllegalStateException("USB gadget already exists");
60-
}
6155

6256
su.run(new String[]{
6357
"mkdir " + gadgetPath,
6458
"cd " + gadgetPath,
65-
Command.echoToFile(params_.idProduct, "idProduct"),
66-
Command.echoToFile(params_.idVendor, "idVendor"),
59+
Command.echoToFile(params.idProduct, "idProduct"),
60+
Command.echoToFile(params.idVendor, "idVendor"),
6761
Command.echoToFile("239", "bDeviceClass"),
6862
Command.echoToFile("0x02", "bDeviceSubClass"),
6963
Command.echoToFile("0x01", "bDeviceProtocol"),
7064

7165
"mkdir strings/0x409",
72-
Command.echoToFile(params_.serial, "strings/0x409/serialnumber"),
73-
Command.echoToFile(params_.manufacturer, "strings/0x409/manufacturer"),
74-
Command.echoToFile(params_.product, "strings/0x409/product"),
66+
Command.echoToFile(params.serial, "strings/0x409/serialnumber"),
67+
Command.echoToFile(params.manufacturer, "strings/0x409/manufacturer"),
68+
Command.echoToFile(params.product, "strings/0x409/product"),
7569

7670
String.format("mkdir \"configs/%s\"", CONFIG_DIR),
7771
String.format("mkdir \"configs/%s/strings/0x409\"", CONFIG_DIR),
78-
Command.echoToFile(params_.configName, String.format("configs/%s/strings/0x409/configuration", CONFIG_DIR)),
72+
Command.echoToFile(params.configName, String.format("configs/%s/strings/0x409/configuration", CONFIG_DIR)),
7973
});
8074

8175
for (UsbGadgetFunction function : this.functions_) {
@@ -84,62 +78,42 @@ public void create(Shell.Threaded su) throws Shell.ShellDiedException {
8478
}
8579

8680
public void bind(Shell.Threaded su) throws Shell.ShellDiedException {
87-
String gadgetPath = getGadgetPath();
88-
if (isBound(su)) {
81+
String gadgetPath = getGadgetPath(gadget_name_);
82+
if (!isCreated(su))
83+
throw new IllegalStateException("USB gadget does not exist");
84+
if (isBound(su))
8985
throw new IllegalStateException("USB gadget is already bound to UDC");
90-
}
9186

9287
for (UsbGadgetFunction function : this.functions_) {
9388
function.bind(su, gadgetPath, CONFIG_DIR);
9489
}
9590

96-
ArrayList<String> drivers = Command.ls(su, "/sys/class/udc");
97-
if (drivers.size() != 1) {
98-
// TODO allow multiple USB drivers
99-
throw new IllegalStateException("There must be exactly one USB driver");
100-
}
101-
String udc = drivers.get(0);
102-
this.oldGadgetUDCDriver_ = udc;
103-
104-
// Look for other gadgets using the same usb driver
105-
ArrayList<String> otherUsbGadgets = Command.ls(su, Paths.get(gadgetPath, "..").toString());
106-
for (String otherUsbGadgetPath : otherUsbGadgets) {
107-
String udcPath = Paths.get(gadgetPath, "..", otherUsbGadgetPath, "UDC").toString();
108-
String driver = Command.readFile(su, udcPath);
109-
if (driver.equals(udc)) {
110-
// Backup the driver so we can restore it later
111-
this.oldGadgetUsingUDC_ = udcPath;
112-
su.run(Command.echoToFile("", udcPath));
113-
break;
114-
}
115-
}
91+
String udc = getSystemUDC(su);
92+
if (udc.isEmpty()) throw new IllegalStateException("Could not determine system UDC");
11693

117-
su.run(Command.echoToFile(udc, Paths.get(gadgetPath, "UDC").toString()));
94+
su.run(Command.echoToFile("", getUDCPath(SYSTEM_GADGET)));
95+
su.run(Command.echoToFile(udc, getUDCPath(gadget_name_)));
11896
}
11997

12098
public void unbind(Shell.Threaded su) throws Shell.ShellDiedException {
121-
if (!isBound(su)) {
99+
if (!isCreated(su))
100+
throw new IllegalStateException("USB gadget does not exist");
101+
if (!isBound(su))
122102
throw new IllegalStateException("USB gadget is not bound to UDC");
123-
}
124103

125-
// Disable gadget
126-
su.run(Command.echoToFile("", getUDCPath()));
127-
// Restore old driver if we need to
128-
if (oldGadgetUsingUDC_ != null) {
129-
su.run(Command.echoToFile(oldGadgetUDCDriver_, oldGadgetUsingUDC_));
130-
}
104+
su.run(Command.echoToFile("", getUDCPath(gadget_name_)));
105+
su.run(Command.echoToFile(getSystemUDC(su), SYSTEM_GADGET));
131106

132-
String gadgetPath = getGadgetPath();
107+
String gadgetPath = getGadgetPath(gadget_name_);
133108
for (UsbGadgetFunction function : this.functions_) {
134109
function.unbind(su, gadgetPath, CONFIG_DIR);
135110
}
136111
}
137112

138113
public void remove(Shell.Threaded su) throws Shell.ShellDiedException {
139-
String gadgetPath = getGadgetPath();
140-
if (!Command.pathExists(su, gadgetPath)) {
114+
String gadgetPath = getGadgetPath(gadget_name_);
115+
if (!isCreated(su))
141116
throw new IllegalStateException("USB gadget does not exist");
142-
}
143117

144118
for (UsbGadgetFunction function : this.functions_) {
145119
function.remove(su, gadgetPath);
@@ -150,28 +124,52 @@ public void remove(Shell.Threaded su) throws Shell.ShellDiedException {
150124
String.format("rmdir \"configs/%s\"", CONFIG_DIR),
151125
"rmdir strings/0x409",
152126
"cd ..",
153-
String.format("rmdir \"%s\"", this.name_)
127+
String.format("rmdir \"%s\"", this.gadget_name_)
154128
});
155129
}
156130

157-
public String getGadgetPath() {
158-
return String.format("%s/usb_gadget/%s", configFsPath_, name_);
131+
public String getGadgetPath(String gadgetName) {
132+
return String.format("%s/usb_gadget/%s", configFsPath_, gadgetName);
159133
}
160134

161-
public String getUDCPath() {
162-
return Paths.get(getGadgetPath(), "UDC").toString();
135+
public String getUDCPath(String gadgetName) {
136+
return Paths.get(getGadgetPath(gadgetName), "UDC").toString();
163137
}
164138

165-
public String getUDC(Shell.Threaded su) {
166-
return Command.readFile(su, getUDCPath());
139+
public String getActiveUDC(Shell.Threaded su, String gadgetName) throws Shell.ShellDiedException {
140+
return Command.readFile(su, getUDCPath(gadgetName));
167141
}
168142

169-
public String getUDCState(Shell.Threaded su, String udc) {
170-
return Command.readFile(su, String.format("/sys/class/udc/%s/state", udc));
143+
public boolean isCreated(Shell.Threaded su) throws Shell.ShellDiedException {
144+
return Command.pathExists(su, getGadgetPath(gadget_name_));
171145
}
172146

173-
public boolean isBound(Shell.Threaded su) {
174-
return !getUDC(su).isEmpty();
147+
public boolean isBound(Shell.Threaded su) throws Shell.ShellDiedException {
148+
return !getActiveUDC(su, gadget_name_).isEmpty();
149+
}
150+
151+
public void addFunction(UsbGadgetFunction function) {
152+
functions_.add(function);
153+
}
154+
155+
public ArrayList<UsbGadgetFunction> getFunctions() {
156+
return functions_;
157+
}
158+
159+
public String serial() {
160+
ArrayList<String> functionDir = new ArrayList<>();
161+
for (UsbGadgetFunction function : getFunctions()) {
162+
functionDir.add(function.getFunctionDir());
163+
}
164+
return String.format("%x", functionDir.hashCode());
165+
}
166+
167+
public static String getSystemUDC(Shell.Threaded su) throws Shell.ShellDiedException {
168+
return Command.getSystemProp(su, "sys.usb.controller");
169+
}
170+
171+
public static String getUDCState(Shell.Threaded su, String udc) throws Shell.ShellDiedException {
172+
return Command.readFile(su, String.format("/sys/class/udc/%s/state", udc));
175173
}
176174

177175
}

app/src/main/java/org/netdex/hidfuzzer/configfs/function/UsbGadgetFunctionHid.java

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,46 +15,6 @@ public static class Parameters extends UsbGadgetFunction.Parameters {
1515
public int reportLength;
1616
public byte[] descriptor;
1717

18-
public static final Parameters DEFAULT = new Parameters(
19-
1,
20-
1,
21-
8,
22-
new byte[]{
23-
(byte) 0x05, (byte) 0x01, /* USAGE_PAGE (Generic Desktop) */
24-
(byte) 0x09, (byte) 0x06, /* USAGE (Keyboard) */
25-
(byte) 0xa1, (byte) 0x01, /* COLLECTION (Application) */
26-
(byte) 0x05, (byte) 0x07, /* USAGE_PAGE (Keyboard) */
27-
(byte) 0x19, (byte) 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */
28-
(byte) 0x29, (byte) 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
29-
(byte) 0x15, (byte) 0x00, /* LOGICAL_MINIMUM (0) */
30-
(byte) 0x25, (byte) 0x01, /* LOGICAL_MAXIMUM (1) */
31-
(byte) 0x75, (byte) 0x01, /* REPORT_SIZE (1) */
32-
(byte) 0x95, (byte) 0x08, /* REPORT_COUNT (8) */
33-
(byte) 0x81, (byte) 0x02, /* INPUT (Data,Var,Abs) */
34-
(byte) 0x95, (byte) 0x01, /* REPORT_COUNT (1) */
35-
(byte) 0x75, (byte) 0x08, /* REPORT_SIZE (8) */
36-
(byte) 0x81, (byte) 0x03, /* INPUT (Cnst,Var,Abs) */
37-
(byte) 0x95, (byte) 0x05, /* REPORT_COUNT (5) */
38-
(byte) 0x75, (byte) 0x01, /* REPORT_SIZE (1) */
39-
(byte) 0x05, (byte) 0x08, /* USAGE_PAGE (LEDs) */
40-
(byte) 0x19, (byte) 0x01, /* USAGE_MINIMUM (Num Lock) */
41-
(byte) 0x29, (byte) 0x05, /* USAGE_MAXIMUM (Kana) */
42-
(byte) 0x91, (byte) 0x02, /* OUTPUT (Data,Var,Abs) */
43-
(byte) 0x95, (byte) 0x01, /* REPORT_COUNT (1) */
44-
(byte) 0x75, (byte) 0x03, /* REPORT_SIZE (3) */
45-
(byte) 0x91, (byte) 0x03, /* OUTPUT (Cnst,Var,Abs) */
46-
(byte) 0x95, (byte) 0x06, /* REPORT_COUNT (6) */
47-
(byte) 0x75, (byte) 0x08, /* REPORT_SIZE (8) */
48-
(byte) 0x15, (byte) 0x00, /* LOGICAL_MINIMUM (0) */
49-
(byte) 0x25, (byte) 0x65, /* LOGICAL_MAXIMUM (101) */
50-
(byte) 0x05, (byte) 0x07, /* USAGE_PAGE (Keyboard) */
51-
(byte) 0x19, (byte) 0x00, /* USAGE_MINIMUM (Reserved) */
52-
(byte) 0x29, (byte) 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
53-
(byte) 0x81, (byte) 0x00, /* INPUT (Data,Ary,Abs) */
54-
(byte) 0xc0 /* END_COLLECTION */
55-
}
56-
);
57-
5818
public Parameters(int protocol, int subclass, int reportLength, byte[] descriptor) {
5919
this.protocol = protocol;
6020
this.subclass = subclass;

app/src/main/java/org/netdex/hidfuzzer/configfs/function/UsbGadgetFunctionMassStorage.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ public static class Parameters extends UsbGadgetFunction.Parameters {
2323

2424
public long size = 256; // in MB, ignored if the file already exists
2525

26-
public static final Parameters DEFAULT = new Parameters(
27-
"/data/local/tmp/mass_storage-lun0.img", 256);
28-
2926
public Parameters(String file, boolean ro, boolean removable,
3027
boolean cdrom, boolean nofua, boolean stall, long size) {
3128
this.file = file;

0 commit comments

Comments
 (0)