Skip to content

Commit

Permalink
* Added logging
Browse files Browse the repository at this point in the history
* Added exit button
* Added checks to see if client is a PS4 running firmware 9.00
  • Loading branch information
rangerare committed Jan 12, 2022
1 parent 347fe8b commit d5a2eb6
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 16 deletions.
45 changes: 34 additions & 11 deletions app/src/main/java/org/ktech/ps4jailbreak/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,31 @@ import android.os.Bundle
import android.text.format.Formatter.formatIpAddress
import android.view.Menu
import android.view.MenuItem
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.Spinner
import android.widget.TextView
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import java.lang.StringBuilder
import java.util.*
import kotlin.collections.ArrayList
import kotlin.system.exitProcess


class MainActivity : AppCompatActivity(){

//HTTP server
lateinit var server: NanoServer
//WifiManager
lateinit var wifiManager: WifiManager

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))

findViewById<FloatingActionButton>(R.id.fab).setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
Toast.makeText(this, "Closing app.", Toast.LENGTH_LONG).show()
exitProcess(0)
}

//Create an array list of items to be displayed in the spinner underneath the start button
Expand All @@ -46,19 +47,41 @@ class MainActivity : AppCompatActivity(){
//Initialize the NanoHTTPD server custom class passing the context so we can access resources in the assets folder
server = NanoServer(this)

log("Logging enabled...")

server.onLogMessage = {
log(it)
}

//Get WifiManager Service so we can retrieve our WiFi IP Address
wifiManager = getApplicationContext().getSystemService(Context.WIFI_SERVICE) as WifiManager

//Setup event for when the start button is clicked
findViewById<Button>(R.id.btnStartServer).setOnClickListener {
//Start the NanoHTTPD server
server.start()
//Get WifiManager Service so we can retrieve the IP Address
val wm: WifiManager = getApplicationContext().getSystemService(Context.WIFI_SERVICE) as WifiManager
//Only start NanoHTTPD server if its not already running
if (!server.isAlive) {
log("Starting server...")
server.start()
} else {
log("Server is already running...")
Toast.makeText(this, "Server is already running...", Toast.LENGTH_LONG).show()
}

//Convert IP address to readable string
val serverIP = formatIpAddress(wm.connectionInfo.ipAddress)
val serverIP = formatIpAddress(wifiManager.connectionInfo.ipAddress)
//Update the TextView above the Start button with below text
findViewById<TextView>(R.id.txtVWStatus).text = "Visit \"http://$serverIP:8080/\" in PS4 browser"
}
}

private fun log(message: String) {
runOnUiThread{
val logTextView = findViewById<TextView>(R.id.txtVwLog)
logTextView.append(message)
logTextView.append("\n")
}
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
Expand Down
39 changes: 35 additions & 4 deletions app/src/main/java/org/ktech/ps4jailbreak/NanoServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,45 @@ import java.net.Socket
class NanoServer(current: Context): NanoHTTPD(8080) {
//Store context so we can access assets from main activity
var context: Context = current
//
var lastPS4: String? = null

//Handle connection from (hopefully) PS4
//TODO: Check if device is a PS4 and if it is running Firmware 9.0
override fun serve(session: IHTTPSession?): Response {
//Retrieve client IP address from the request headers. Seems to be the only way possible with
// NanoHTTPD

//Check if client is a PS4 running firmware 9.0 by looking for string "PlayStation 4/9.00"
//in "user-agent" header.
if (session?.headers?.get("user-agent")?.contains("PlayStation 4/9.00") == false) {
onLogMessage("Non-PS4_FW9.0 client connected.")
return NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/html", """
<!DOCTYPE html>
<html lang="en">
<head>
<title>Client Mismatch</title>
</head>
<body>
<h1>Run this on a PS4 running firmware 9.00 only!</h1>
</body>
</html>
""")
}

val clientIP: String = session?.headers?.get("http-client-ip").toString()
val requestURL: String = session?.uri.toString()

if (lastPS4 != clientIP) {
onLogMessage("PS4 running firmware 9.00 connected with IP Address $clientIP")
lastPS4 = clientIP
} else {
onLogMessage("PS4 browser requesting $requestURL")
}


//React to request uri path
when (session?.uri.toString()) {
when (requestURL) {
//Return index.html to client/PS4
"/" -> {
return NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/html", getResourceAsText("index.html"))
Expand All @@ -30,6 +59,7 @@ class NanoServer(current: Context): NanoHTTPD(8080) {
and kexploit.js:640
*/
"/log/done" -> {
onLogMessage("Sending payload to PS4 with IP $clientIP on port 9020...")
//Setup a connection to the PS4 to send the payload on port 9020
val outSock = Socket(clientIP, 9020)
val outStream = outSock.getOutputStream()
Expand All @@ -42,19 +72,20 @@ class NanoServer(current: Context): NanoHTTPD(8080) {
}
else -> {
//This is a hack to serve all the static files in the assets folder
val path = session?.uri.toString().drop(1)
val path = requestURL.drop(1)
//if the request path ends with .html then always return the index.html file
if ( session?.uri.toString().endsWith(".html") ) {
if ( requestURL.endsWith(".html") ) {
return NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/html", getResourceAsText("index.html"))
//Else if the request path ends with .js then return the javascript files with the correct mime type
} else if ( session?.uri.toString().endsWith(".js") ) {
} else if ( requestURL.endsWith(".js") ) {
return NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/javascript ", getResourceAsText(path))
}
}
}
return super.serve(session)
}

var onLogMessage: ((String) -> Unit) = {}
//get the string contents of a resource from the assets folder using its path
private fun getResourceAsText(path: String): String {
return context.assets.open(path).reader().readText()
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />
app:srcCompat="@android:drawable/ic_lock_power_off" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
9 changes: 9 additions & 0 deletions app/src/main/res/layout/content_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,14 @@
android:layout_marginLeft="10dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"/>

<TextView
android:id="@+id/txtVwLog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginEnd="15dp"
android:layout_marginRight="15dp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

0 comments on commit d5a2eb6

Please sign in to comment.