Skip to content

Commit

Permalink
add watch simulator
Browse files Browse the repository at this point in the history
  • Loading branch information
rec0de committed Sep 25, 2024
1 parent 227e620 commit 5458b2c
Show file tree
Hide file tree
Showing 17 changed files with 785 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.util.Base64
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import net.rec0de.android.watchwitch.bitmage.fromIndex
import net.rec0de.android.watchwitch.bitmage.hex
import net.rec0de.android.watchwitch.decoders.aoverc.MPKeys
import java.net.DatagramPacket
import java.net.DatagramSocket
Expand Down Expand Up @@ -93,9 +92,9 @@ class KeyReceiver : Thread() {

RoutingManager.registerAddresses()
Logger.log("got keys!", 0)
Logger.log("remote public (C/D):", 1)
Logger.log(Base64.decode(map["cr"]!!, Base64.DEFAULT).hex(), 1)
Logger.log(Base64.decode(map["dr"]!!, Base64.DEFAULT).hex(), 1)
//Logger.log("remote public (C/D):", 1)
//Logger.log(Base64.decode(map["cr"]!!, Base64.DEFAULT).hex(), 1)
//Logger.log(Base64.decode(map["dr"]!!, Base64.DEFAULT).hex(), 1)
}
}
catch (e: Throwable) {
Expand Down
15 changes: 8 additions & 7 deletions app/src/main/java/net/rec0de/android/watchwitch/Logger.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.rec0de.android.watchwitch

import android.annotation.SuppressLint
import android.util.Log
import net.rec0de.android.watchwitch.activities.MainActivity

object Logger {
Expand Down Expand Up @@ -53,48 +54,48 @@ object Logger {
if(level <= GEN_SCREEN_LVL)
logToScreen(msg)
if(level <= GEN_LOG_LVL)
println(msg)
Log.d("WatchWitch", msg)
}

fun logIDS(msg: String, level: Int) {
if(level <= IDS_SCREEN_LVL)
logToScreen(msg)
if(level <= IDS_LOG_LVL)
println(msg)
Log.d("WatchWitchIDS", msg)
}

fun logUTUN(msg: String, level: Int) {
if(level <= UTUN_SCREEN_LVL)
logToScreen(msg)
if(level <= UTUN_LOG_LVL)
println(msg)
Log.d("WatchWitchAlloy", msg)
}

fun logShoes(msg: String, level: Int) {
if(level <= SHOES_SCREEN_LVL)
logToScreen(msg)
if(level <= SHOES_LOG_LVL)
println(msg)
Log.d("WatchWitchShoes", msg)
}

fun logIKE(msg: String, level: Int) {
if(level <= IKE_SCREEN_LVL)
logToScreen(msg)
if(level <= IKE_LOG_LVL)
println(msg)
Log.d("WatchWitchIKE", msg)
}

fun logSQL(msg: String, level: Int) {
if(level <= SQL_SCREEN_LVL)
logToScreen(msg)
if(level <= SQL_LOG_LVL)
println(msg)
Log.d("WatchWitchSQL", msg)
}

fun logCmd(msg: String, level: Int) {
if(level <= CMD_SCREEN_LVL)
logToScreen(msg)
if(level <= CMD_LOG_LVL)
println(msg)
Log.d("WatchWitchCmd", msg)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import android.text.InputType
import android.widget.Button
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.LinearLayout.GONE
import android.widget.LinearLayout.VERTICAL
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
Expand All @@ -33,6 +34,7 @@ import net.rec0de.android.watchwitch.WatchState
import net.rec0de.android.watchwitch.nwsc.NWSCManager
import net.rec0de.android.watchwitch.servicehandlers.messaging.BulletinDistributorService
import net.rec0de.android.watchwitch.shoes.ShoesService
import net.rec0de.android.watchwitch.watchsim.SimulatedWatch


class MainActivity : AppCompatActivity() {
Expand Down Expand Up @@ -135,6 +137,14 @@ class MainActivity : AppCompatActivity() {
this@MainActivity.startActivity(healthLog)
}

val simButton: Button = findViewById(R.id.btnSimWatch)
simButton.setOnClickListener {
val simulator = SimulatedWatch()
simulator.start()
val buttonContainer: LinearLayout = findViewById(R.id.layoutSimulateButton)
buttonContainer.visibility = GONE
}

val transitKeyButton: Button = findViewById(R.id.btnSetTransitKey)
transitKeyButton.setOnClickListener {
val builder: AlertDialog.Builder = AlertDialog.Builder(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ object AlloyController {

// attempt to open an actual connection
GlobalScope.launch {
delay((200 + 30*i).toLong())
delay((400 + 30*i).toLong())
// we may have received and accepted an incoming request for this channel in the meantime
if(!establishedChannels.contains(fullService)) {
val handler = AlloyHandler(fullService, null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class Hello(
var deviceID: UUID? = null

companion object : ParseCompanion() {

@Synchronized
fun parse(bytes: ByteArray): Hello {
if(bytes[0].toInt() != 0x01)
throw Exception("Expected UTunControlMsg type 0x01 for Hello but got ${bytes[0]}")
Expand Down Expand Up @@ -206,6 +208,7 @@ class Hello(
// the sender port is completely meaningless??
class SetupChannel(val protocol: Int, val receiverPort: Int, val senderPort: Int, val senderUUID: UUID, val receiverUUID: UUID?, val account: String, val service: String, val name: String): UTunControlMessage() {
companion object : ParseCompanion() {
@Synchronized
fun parse(bytes: ByteArray): SetupChannel {
if(bytes[0].toInt() != 0x02)
throw Exception("Expected UTunControlMsg type 0x02 for SetupChannel but got ${bytes[0]}")
Expand Down Expand Up @@ -236,22 +239,25 @@ class SetupChannel(val protocol: Int, val receiverPort: Int, val senderPort: Int
val accBytes = account.encodeToByteArray()
val serviceBytes = service.encodeToByteArray()
val nameBytes = name.encodeToByteArray()
val senderUUIDBytes = senderUUID.toString().encodeToByteArray()
val receiverUUIDBytes = receiverUUID?.toString()?.encodeToByteArray()


val header = ByteBuffer.allocate(16)
header.put(0x02) // SetupChannel type byte
header.put(protocol.toByte())
header.putShort(senderPort.toShort())
header.putShort(receiverPort.toShort())
header.putShort(0x24) // sender UUID length
header.putShort(if(receiverUUID != null) 0x24 else 0x00) // receiver UUID length
header.putShort(senderUUIDBytes.size.toShort()) // sender UUID length
header.putShort(receiverUUIDBytes?.size?.toShort() ?: 0x00) // receiver UUID length
header.putShort(accBytes.size.toShort())
header.putShort(serviceBytes.size.toShort())
header.putShort(nameBytes.size.toShort())

val uuids = if(receiverUUID != null)
senderUUID.toString().encodeToByteArray() + receiverUUID.toString().encodeToByteArray()
val uuids = if(receiverUUIDBytes != null)
senderUUIDBytes + receiverUUIDBytes
else
senderUUID.toString().encodeToByteArray()
senderUUIDBytes

return header.array() + uuids + accBytes + serviceBytes + nameBytes
}
Expand All @@ -263,6 +269,8 @@ class SetupChannel(val protocol: Int, val receiverPort: Int, val senderPort: Int

class SetupDirectChannel(val protocol: Int, val receiverPort: Int, val senderPort: Int, val senderUUID: UUID, val receiverUUID: UUID?, val account: String, val service: String, val name: String): UTunControlMessage() {
companion object : ParseCompanion() {

@Synchronized
fun parse(bytes: ByteArray): SetupDirectChannel {
if(bytes[0].toInt() != 0x02)
throw Exception("Expected UTunControlMsg type 0x0d for SetupDirectChannel but got ${bytes[0]}")
Expand Down Expand Up @@ -293,14 +301,16 @@ class SetupDirectChannel(val protocol: Int, val receiverPort: Int, val senderPor
val accBytes = account.encodeToByteArray()
val serviceBytes = service.encodeToByteArray()
val nameBytes = name.encodeToByteArray()
val senderUUIDBytes = senderUUID.toString().encodeToByteArray()
val receiverUUIDBytes = receiverUUID?.toString()?.encodeToByteArray()

val header = ByteBuffer.allocate(16)
header.put(0x0d) // SetupDirectChannel type byte
header.put(protocol.toByte())
header.putShort(receiverPort.toShort())
header.putShort(senderPort.toShort())
header.putShort(0x24) // sender UUID length
header.putShort(if(receiverUUID != null) 0x24 else 0x00) // receiver UUID length
header.putShort(senderUUIDBytes.size.toShort()) // sender UUID length
header.putShort(receiverUUIDBytes?.size?.toShort() ?: 0x00) // receiver UUID length
header.putShort(accBytes.size.toShort())
header.putShort(serviceBytes.size.toShort())
header.putShort(nameBytes.size.toShort())
Expand All @@ -321,6 +331,8 @@ class SetupDirectChannel(val protocol: Int, val receiverPort: Int, val senderPor

class CloseChannel(val senderUUID: UUID, val receiverUUID: UUID?, val account: String, val service: String, val name: String): UTunControlMessage() {
companion object : ParseCompanion() {

@Synchronized
fun parse(bytes: ByteArray): CloseChannel {
if(bytes[0].toInt() != 0x03)
throw Exception("Expected UTunControlMsg type 0x03 for CloseChannel but got ${bytes[0]}")
Expand Down Expand Up @@ -361,6 +373,8 @@ class CompressionRequest(
val name: String
): UTunControlMessage() {
companion object : ParseCompanion() {

@Synchronized
fun parse(bytes: ByteArray): CompressionRequest {
if(bytes[0].toInt() != 0x04)
throw Exception("Expected UTunControlMsg type 0x04 for CompressionRequest but got ${bytes[0]}")
Expand Down Expand Up @@ -401,6 +415,8 @@ class CompressionResponse(
val name: String
): UTunControlMessage() {
companion object : ParseCompanion() {

@Synchronized
fun parse(bytes: ByteArray): CompressionResponse {
if(bytes[0].toInt() != 0x05)
throw Exception("Expected UTunControlMsg type 0x05 for CompressionResponse but got ${bytes[0]}")
Expand Down Expand Up @@ -443,6 +459,8 @@ class SetupEncryptedChannel(
val key: ByteArray
): UTunControlMessage() {
companion object : ParseCompanion() {

@Synchronized
fun parse(bytes: ByteArray): SetupEncryptedChannel {
if(bytes[0].toInt() != 0x06)
throw Exception("Expected UTunControlMsg type 0x06 for SetupEncryptedChannel but got ${bytes[0]}")
Expand Down Expand Up @@ -477,14 +495,16 @@ class SetupEncryptedChannel(
val accBytes = account.encodeToByteArray()
val serviceBytes = service.encodeToByteArray()
val nameBytes = name.encodeToByteArray()
val senderUUIDBytes = senderUUID.toString().encodeToByteArray()
val receiverUUIDBytes = receiverUUID?.toString()?.encodeToByteArray()

val header = ByteBuffer.allocate(24)
header.put(0x06) // SetupChannel type byte
header.put(protocol.toByte())
header.putShort(senderPort.toShort())
header.putShort(receiverPort.toShort())
header.putShort(0x24) // sender UUID length
header.putShort(if(receiverUUID != null) 0x24 else 0x00) // receiver UUID length
header.putShort(senderUUIDBytes.size.toShort()) // sender UUID length
header.putShort(receiverUUIDBytes?.size?.toShort() ?: 0x00) // receiver UUID length
header.putShort(accBytes.size.toShort())
header.putShort(serviceBytes.size.toShort())
header.putShort(nameBytes.size.toShort())
Expand All @@ -508,6 +528,8 @@ class SetupEncryptedChannel(

class DirectMsgInfo(val data: ByteArray): UTunControlMessage() {
companion object : ParseCompanion() {

@Synchronized
fun parse(bytes: ByteArray): DirectMsgInfo {
if(bytes[0].toInt() != 0x0e)
throw Exception("Expected UTunControlMsg type 0x0e for DirectMsgInfo but got ${bytes[0]}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ fun Int.toBytes(byteOrder: ByteOrder): ByteArray {
}
fun UInt.toBytes(byteOrder: ByteOrder) = this.toInt().toBytes(byteOrder)

fun Short.toBytes(byteOrder: ByteOrder): ByteArray {
val bytesBE = byteArrayOf((this.toInt() shr 8).toByte(), (this.toInt() shr 0).toByte())
return if(byteOrder == ByteOrder.BIG) bytesBE else bytesBE.reversed().toByteArray()
}
fun UShort.toBytes(byteOrder: ByteOrder) = this.toShort().toBytes(byteOrder)

// Floats

fun Float.Companion.fromBytes(bytes: ByteArray, byteOrder: ByteOrder): Float {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,9 @@ object NWSCManager {
return microsecondsSinceEpoch + microsecondsSinceSecond
}

fun simulatorSetRemotePubkey(key: ByteArray) {
remotePubKey = key
gotPubkey = true
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ object ShoesProxyHandler {
fromWatch.readUnsignedShort()
}

//Logger.logShoes("TLS rcv trying to read $headerLen header bytes", 10)
Logger.logShoes("Shoes request reading $headerLen bytes", 10)

val requestBytes = ByteArray(headerLen)
withContext(Dispatchers.IO) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class ShoesService : Service() {
Logger.logShoes("started shoes server on port 62742", 1)
while (true) {
socket = serverSocket.accept()
Logger.logShoes("got shoes connection", 5)
val dataInputStream = DataInputStream(socket.getInputStream())
val dataOutputStream = DataOutputStream(socket.getOutputStream())
GlobalScope.launch { ShoesProxyHandler.handleConnection(dataInputStream, dataOutputStream) }
Expand Down
Loading

0 comments on commit 5458b2c

Please sign in to comment.