Skip to content

Commit

Permalink
app: annual refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Netdex committed Jul 20, 2024
1 parent fa9ca48 commit 68a2503
Show file tree
Hide file tree
Showing 36 changed files with 1,271 additions and 1,253 deletions.
89 changes: 47 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

**Use at your own risk. For educational purposes only.**

An Android app that provides a simple Lua interface for enumerating and interfacing
with arbitrary composite USB devices.
An Android app that provides a simple Lua interface for creating and interfacing
with arbitrary composite USB devices, allowing your phone to act as a USB device.

**Root access is required.**

Expand All @@ -14,69 +14,74 @@ with arbitrary composite USB devices.
Download debug build artifacts from [the latest workflow run](https://github.com/Netdex/android-usb-script/actions).

## Demonstration

The best way to explain what this app does is with a code example. The following script
does the following when interpreted by this app:

When interpreted by this app, the following script:
1. Configures your phone to become a USB keyboard
2. Sends a series of key presses to the computer your phone is plugged in to, changing
its wallpaper

```lua
-- create a USB composite device composed of a single keyboard
usb = luausb.create({ id = 0, type = "keyboard" })
kb = usb.dev[1]
---
--- Change Windows 10 desktop wallpaper
---

require('common')

kb = luausb.create({ type = "keyboard" })

local file = prompt("Wallpaper to download?", "https://i.imgur.com/46wWHZ3.png")
local file = prompt{
message="Enter the URL of the wallpaper to download.",
hint="Image URL",
default="https://i.imgur.com/46wWHZ3.png"
}

while true do
print("idle")

-- wait for the phone to be plugged into a computer
while usb.state() == "not attached" do
wait(1000)
end

-- wait for USB device to be plugged in
wait_for_state('configured')
-- wait for host to detect this USB device
wait_for_detect(kb)
print("running")
wait(1000)

kb.chord(MOD_LSUPER, KEY_R) -- open Windows run dialog
wait(2000) -- wait for it to open
kb.string("powershell\n") -- open powershell
kb:chord(MOD_LSUPER, KEY_R)
wait(2000)
kb:string("powershell\n")
wait(2000)
-- execute a script that downloads and changes the wallpaper
kb.string("[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;" ..
"(new-object System.Net.WebClient).DownloadFile('" .. file .. "',\"$Env:Temp\\b.jpg\");\n" ..
"Add-Type @\"\n" ..
"using System;using System.Runtime.InteropServices;using Microsoft.Win32;namespa" ..
"ce W{public class S{ [DllImport(\"user32.dll\")]static extern int SystemParamet" ..
"ersInfo(int a,int b,string c,int d);public static void SW(string a){SystemParam" ..
"etersInfo(20,0,a,3);RegistryKey c=Registry.CurrentUser.OpenSubKey(\"Control Pan" ..
"el\\\\Desktop\",true);c.SetValue(@\"WallpaperStyle\", \"2\");c.SetValue(@\"Tile" ..
"Wallpaper\", \"0\");c.Close();}}}\n" ..
"\"@\n" ..
"[W.S]::SW(\"$Env:Temp\\b.jpg\")\n" ..
"exit\n")
kb:string("[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;" ..
"(new-object System.Net.WebClient).DownloadFile('" .. file .. "',\"$Env:Temp\\b.jpg\");\n" ..
"Add-Type @\"\n" ..
"using System;using System.Runtime.InteropServices;using Microsoft.Win32;namespa" ..
"ce W{public class S{ [DllImport(\"user32.dll\")]static extern int SystemParamet" ..
"ersInfo(int a,int b,string c,int d);public static void SW(string a){SystemParam" ..
"etersInfo(20,0,a,3);RegistryKey c=Registry.CurrentUser.OpenSubKey(\"Control Pan" ..
"el\\\\Desktop\",true);c.SetValue(@\"WallpaperStyle\", \"2\");c.SetValue(@\"Tile" ..
"Wallpaper\", \"0\");c.Close();}}}\n" ..
"\"@\n" ..
"[W.S]::SW(\"$Env:Temp\\b.jpg\")\n" ..
"exit\n")

print("done")
-- wait until the phone is unplugged
while usb.state() == "configured" do
wait(1000)
end
-- wait for USB device to be unplugged
wait_for_state("not attached")
end
```

Several other sample scripts are
[included in the repository](https://github.com/Netdex/android-usb-script/tree/master/app/src/main/assets/scripts).
The following USB gadgets are currently supported:
- Keyboard (keyboard)
- Mouse (mouse)
- Mass Storage (storage)

Built-in scripts can be run using the "Select Asset" menu item. You can run an external script using
the "Load Script" menu item. New demo applications can be added to `assets/scripts`. The API is
pretty much self-documenting, just look at the existing demos to get a feel for how the API works.
Several other sample scripts
are [included in the repository](https://github.com/Netdex/android-usb-script/tree/master/app/src/main/assets/scripts).

## Requirements
**This app will not work on every Android device.** If your Android OS has Linux Kernel
version >= 3.18 and is compiled with configfs and f_hid, then the app can try to create usb
gadgets.

New demo applications can be added to `assets/scripts`. The API is pretty much self-documenting,
just look at the existing demos to get a feel for how the API works.

## Troubleshooting
### "Device Malfunctioned" on Windows 10
There may be an incompatibility between the supported USB speed between the USB function and USB
Expand All @@ -90,5 +95,5 @@ Try setting SELinux to permissive mode by running `setenforce 0` as root.


## Third-party
- [libsuperuser](https://github.com/Chainfire/libsuperuser)
- [libsu](https://github.com/topjohnwu/libsu)
- [LuaJ](http://www.luaj.org/luaj/3.0/README.html)
15 changes: 9 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
apply plugin: 'com.android.application'
apply plugin: 'org.jetbrains.kotlin.android'

android {
compileSdk 34
compileSdk 35
defaultConfig {
applicationId "org.netdex.androidusbscript"
minSdkVersion 26
targetSdkVersion 34
versionCode 121
versionName '1.2.1'
targetSdkVersion 35
versionCode 122
versionName '1.2.2'
}
buildTypes {
release {
Expand All @@ -30,17 +31,19 @@ android {

dependencies {
implementation 'androidx.core:core:1.13.1'
implementation 'androidx.core:core-ktx:1.13.1'
implementation 'androidx.appcompat:appcompat:1.7.0'

implementation 'com.google.android.material:material:1.12.0'

implementation 'com.jakewharton.timber:timber:5.0.1'
implementation 'org.luaj:luaj-jse:3.0.1'
implementation 'androidx.appcompat:appcompat:1.7.0'

implementation "com.github.topjohnwu.libsu:core:5.2.0"
implementation "com.github.topjohnwu.libsu:service:5.2.0"
implementation "com.github.topjohnwu.libsu:nio:5.2.0"
implementation "com.github.topjohnwu.libsu:io:5.2.0"

implementation 'com.jakewharton.timber:timber:5.0.1'
}
repositories {
mavenCentral()
Expand Down
8 changes: 7 additions & 1 deletion app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,10 @@
# This is generated automatically by the Android Gradle plugin.

-dontwarn javax.script.**
-keepnames class org.luaj.vm2.** {*; }
-dontwarn org.apache.bcel.**

-dontobfuscate

# Do NOT optimize LuaJ or classes which serve as Lua API boundary
-keep class org.luaj.vm2.** {*; }
-keep class org.netdex.androidusbscript.lua.** {*; }
8 changes: 4 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
android:theme="@style/AppTheme">

<activity
android:name="org.netdex.androidusbscript.MainActivity"
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleInstance">
<intent-filter>
Expand All @@ -21,15 +21,15 @@
</activity>

<activity
android:name="org.netdex.androidusbscript.SelectAssetActivity"
android:name=".SelectAssetActivity"
android:exported="true"
android:label="@string/title_activity_select_asset"
android:parentActivityName="org.netdex.androidusbscript.MainActivity" />

<service
android:name="org.netdex.androidusbscript.service.LuaUsbService"
android:name=".service.LuaUsbService"
android:enabled="true"
android:foregroundServiceType="specialUse"/>
android:foregroundServiceType="specialUse" />
</application>

</manifest>
2 changes: 1 addition & 1 deletion app/src/main/assets/lib/common.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ end

function wait_for_state(state)
while luausb.state() ~= state do
wait(1000)
wait(100)
end
end

Expand Down
16 changes: 8 additions & 8 deletions app/src/main/assets/scripts/composite.lua
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
---
--- Composite device composed of two keyboards
---
--- Composite device composed of every suupported gadget
---

require('common')

kb1, kb2 = luausb.create({ type = "keyboard" }, { type = "keyboard" })
kb, ms, st, sl = luausb.create(
{ type = "keyboard" },
{ type = "mouse" },
{ type = "storage" },
{ type = "serial" }
)

while true do
print("idle")

wait_for_state("configured")
wait_for_detect(kb1)
wait_for_detect(kb)
print("running")

-- send a string from keyboard 1
kb1:string("kb1")
wait(1000)
-- send a string from keyboard 2
kb2:string("kb2")

print("done")
wait_for_state("not attached")
Expand Down
26 changes: 14 additions & 12 deletions app/src/main/assets/scripts/wallpaper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ local file = prompt{
while true do
print("idle")

-- poll until usb plugged in
-- wait for USB device to be plugged in
wait_for_state('configured')
-- wait for host to detect this USB device
wait_for_detect(kb)
print("running")

Expand All @@ -25,18 +26,19 @@ while true do
kb:string("powershell\n")
wait(2000)
kb:string("[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;" ..
"(new-object System.Net.WebClient).DownloadFile('" .. file .. "',\"$Env:Temp\\b.jpg\");\n" ..
"Add-Type @\"\n" ..
"using System;using System.Runtime.InteropServices;using Microsoft.Win32;namespa" ..
"ce W{public class S{ [DllImport(\"user32.dll\")]static extern int SystemParamet" ..
"ersInfo(int a,int b,string c,int d);public static void SW(string a){SystemParam" ..
"etersInfo(20,0,a,3);RegistryKey c=Registry.CurrentUser.OpenSubKey(\"Control Pan" ..
"el\\\\Desktop\",true);c.SetValue(@\"WallpaperStyle\", \"2\");c.SetValue(@\"Tile" ..
"Wallpaper\", \"0\");c.Close();}}}\n" ..
"\"@\n" ..
"[W.S]::SW(\"$Env:Temp\\b.jpg\")\n" ..
"exit\n")
"(new-object System.Net.WebClient).DownloadFile('" .. file .. "',\"$Env:Temp\\b.jpg\");\n" ..
"Add-Type @\"\n" ..
"using System;using System.Runtime.InteropServices;using Microsoft.Win32;namespa" ..
"ce W{public class S{ [DllImport(\"user32.dll\")]static extern int SystemParamet" ..
"ersInfo(int a,int b,string c,int d);public static void SW(string a){SystemParam" ..
"etersInfo(20,0,a,3);RegistryKey c=Registry.CurrentUser.OpenSubKey(\"Control Pan" ..
"el\\\\Desktop\",true);c.SetValue(@\"WallpaperStyle\", \"2\");c.SetValue(@\"Tile" ..
"Wallpaper\", \"0\");c.Close();}}}\n" ..
"\"@\n" ..
"[W.S]::SW(\"$Env:Temp\\b.jpg\")\n" ..
"exit\n")

print("done")
-- wait for USB device to be unplugged
wait_for_state("not attached")
end
Loading

0 comments on commit 68a2503

Please sign in to comment.