Skip to content
This repository was archived by the owner on Mar 14, 2019. It is now read-only.

Commit 4b5e8ee

Browse files
committed
Updated HENkaku to Release 7.
Updated VitaShell to 1.51.
1 parent f1354ac commit 4b5e8ee

12 files changed

Lines changed: 40 additions & 61 deletions

File tree

app/build.gradle

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
apply plugin: 'com.android.application'
22

33
android {
4-
compileSdkVersion 24
5-
buildToolsVersion "24.0.2"
4+
compileSdkVersion 25
5+
buildToolsVersion "25.0.2"
66

77
defaultConfig {
88
applicationId "com.codestation.henkakuserver"
99
minSdkVersion 10
10-
targetSdkVersion 24
11-
versionCode 7
12-
versionName "1.6"
10+
targetSdkVersion 25
11+
versionCode 8
12+
versionName "1.7"
1313
}
1414
buildTypes {
1515
release {
@@ -21,9 +21,9 @@ android {
2121

2222
dependencies {
2323
compile fileTree(include: ['*.jar'], dir: 'libs')
24-
compile 'com.android.support:appcompat-v7:24.1.1'
24+
compile 'com.android.support:appcompat-v7:25.1.0'
2525
compile 'org.nanohttpd:nanohttpd:2.3.0'
26-
compile 'com.android.support:design:24.1.1'
26+
compile 'com.android.support:design:25.1.0'
2727
compile 'org.apache.directory.studio:org.apache.commons.io:2.4'
2828
compile 'org.apache.commons:commons-lang3:3.4'
2929
}

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
<application
1111
android:allowBackup="true"
12+
android:fullBackupContent="true"
1213
android:icon="@mipmap/ic_launcher"
1314
android:label="@string/app_name"
1415
android:supportsRtl="true"
-152 KB
Binary file not shown.

app/src/main/assets/loader.rop.bin

0 Bytes
Binary file not shown.

app/src/main/assets/pkg/eboot.bin

-363 KB
Binary file not shown.
3.16 KB
Binary file not shown.
2.38 KB
Binary file not shown.
248 KB
Binary file not shown.

app/src/main/assets/stage2.bin

281 KB
Binary file not shown.

app/src/main/java/com/codestation/henkakuserver/HenkakuServer.java

Lines changed: 29 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.text.TextUtils;
2121
import android.util.Log;
2222
import android.util.Pair;
23+
import android.util.SparseArray;
2324

2425
import org.apache.commons.io.IOUtils;
2526
import org.apache.commons.lang3.ArrayUtils;
@@ -41,7 +42,7 @@
4142
import fi.iki.elonen.NanoHTTPD;
4243

4344

44-
public class HenkakuServer extends NanoHTTPD {
45+
class HenkakuServer extends NanoHTTPD {
4546

4647
private Context context;
4748

@@ -50,12 +51,12 @@ public class HenkakuServer extends NanoHTTPD {
5051
private byte[] stage1;
5152
private byte[] stage2;
5253

53-
public HenkakuServer(Context ctx, int port) {
54+
HenkakuServer(Context ctx, int port) {
5455
super(port);
5556
context = ctx;
5657
}
5758

58-
public synchronized void setIpAddress(String ipAddress) {
59+
synchronized void setIpAddress(String ipAddress) {
5960
currentIpAddress = ipAddress;
6061
}
6162

@@ -85,7 +86,7 @@ private Pair<ArrayList<Integer>, List<Byte>> preprocessRop(byte[] urop) throws E
8586
int symtab = reloc_offset + reloc_size;
8687
int symtab_n = symtab_size / 8;
8788

88-
Map<Integer, String> reloc_map = new HashMap<>();
89+
SparseArray<String> reloc_map = new SparseArray<>();
8990

9091
for (int x = 0; x < symtab_n; ++x) {
9192
int sym_id = buf.getInt(symtab + 8 * x);
@@ -168,33 +169,6 @@ private String preprocessToJs(byte[] loader) throws Exception {
168169
return String.format("\npayload = [%1$s];\nrelocs = [%2$s];\n", payload, relocations);
169170
}
170171

171-
/**
172-
* Convert the exploit to a shellcode in binary format
173-
*
174-
* @param exploit payload compiled code
175-
* @return the shellcode
176-
* @throws Exception
177-
*/
178-
private byte[] preprocessToBin(byte[] exploit) throws Exception {
179-
Pair<ArrayList<Integer>, List<Byte>> data = preprocessRop(exploit);
180-
181-
int size = 4 + data.first.size() * 4 + data.second.size();
182-
byte[] out = new byte[size + ((-size) & 3)];
183-
ByteBuffer buf = ByteBuffer.wrap(out).order(ByteOrder.LITTLE_ENDIAN);
184-
185-
buf.putInt(data.second.size());
186-
187-
for (Integer val : data.first) {
188-
buf.putInt(val);
189-
}
190-
191-
for (Byte val : data.second) {
192-
buf.put(val);
193-
}
194-
195-
return out;
196-
}
197-
198172
/**
199173
* Finalize the exploit with the addesses from the device
200174
*
@@ -258,10 +232,9 @@ private byte[] patchExploit(byte[] exploit, Map<String, String> params) throws E
258232
*
259233
* @param stage code of the current stage
260234
* @param url address to fetch the next stage
261-
* @return modified shellcode
262235
* @throws UnsupportedEncodingException
263236
*/
264-
private byte[] writePkgUrl(byte[] stage, String url) throws UnsupportedEncodingException {
237+
private void writePkgUrl(byte[] stage, String url) throws UnsupportedEncodingException {
265238

266239
// prepare search pattern
267240
byte[] pattern = new byte[256];
@@ -273,14 +246,16 @@ private byte[] writePkgUrl(byte[] stage, String url) throws UnsupportedEncodingE
273246
// find url placeholder in loader
274247
int idx = Collections.indexOfSubList(a, b);
275248

276-
// convert the url to a byte array
277-
byte[] urlArray = url.getBytes("UTF-8");
278-
279-
// write the url in the loader
280-
System.arraycopy(urlArray, 0, stage, idx, urlArray.length);
281-
Arrays.fill(stage, idx + urlArray.length, idx + 256, (byte) 0x0);
249+
if(idx >= 0) {
250+
// convert the url to a byte array
251+
byte[] urlArray = url.getBytes("UTF-8");
282252

283-
return stage;
253+
// write the url in the loader
254+
System.arraycopy(urlArray, 0, stage, idx, urlArray.length);
255+
Arrays.fill(stage, idx + urlArray.length, idx + 256, (byte) 0x0);
256+
} else {
257+
Log.e("henkaku", "URL filler not found in payload");
258+
}
284259
}
285260

286261
/**
@@ -293,11 +268,11 @@ private String getLoaderJs() throws Exception {
293268

294269
// reuse the modified loader if the ip address hasn't changed
295270
if (stage1 == null || lastIpAddress == null || !lastIpAddress.equals(getIpAddress())) {
296-
InputStream is = context.getAssets().open("loader.rop.bin");
297-
byte[] loader = IOUtils.toByteArray(is);
298-
String url = "http://" + getIpAddress() + ":" + getListeningPort() + "/stage2";
299-
stage1 = writePkgUrl(loader, url);
300271
lastIpAddress = getIpAddress();
272+
InputStream is = context.getAssets().open("loader.rop.bin");
273+
stage1 = IOUtils.toByteArray(is);
274+
String url = "http://" + lastIpAddress + ":" + getListeningPort() + "/stage2";
275+
writePkgUrl(stage1, url);
301276
}
302277

303278
return preprocessToJs(stage1);
@@ -314,16 +289,14 @@ private InputStream getExploitBin(Map<String, String> params) throws Exception {
314289

315290
// reuse the preprocessed exploit if the ip address hasn't changed
316291
if (stage2 == null || lastIpAddress == null || !lastIpAddress.equals(getIpAddress())) {
317-
InputStream is = context.getAssets().open("exploit.rop.bin");
318-
byte[] exploit = IOUtils.toByteArray(is);
319-
stage2 = preprocessToBin(exploit);
320-
String url = "http://" + getIpAddress() + ":" + getListeningPort() + "/pkg";
321-
stage2 = writePkgUrl(stage2, url);
322292
lastIpAddress = getIpAddress();
293+
InputStream is = context.getAssets().open("stage2.bin");
294+
stage2 = IOUtils.toByteArray(is);
295+
String url = "http://" + lastIpAddress + ":" + getListeningPort() + "/pkg";
296+
writePkgUrl(stage2, url);
323297
}
324298

325-
byte[] patched = patchExploit(stage2, params);
326-
return new ByteArrayInputStream(patched);
299+
return new ByteArrayInputStream(patchExploit(stage2, params));
327300
}
328301

329302
private InputStream getPackageFile(String uri) throws IOException {
@@ -339,8 +312,13 @@ public Response serve(IHTTPSession session) {
339312
Response response;
340313

341314
String uri = session.getUri();
315+
String query = session.getQueryParameterString();
342316
Log.d("henkaku", String.format("Request URI: %s", uri));
343317

318+
if(query != null) {
319+
Log.d("henkaku", String.format("Request params: %s", query));
320+
}
321+
344322
String agent = session.getHeaders().get("user-agent");
345323
if (agent != null && !agent.contains("PlayStation Vita 3.60") && (uri.equals("/") || uri.equals("stage1"))) {
346324
Log.d("henkaku", "Request from non PS Vita");

0 commit comments

Comments
 (0)