-
Notifications
You must be signed in to change notification settings - Fork 183
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
可以使用XServer进行内存读取/修改。 用于脱简单壳以及获取运行时SO文件。
- Loading branch information
Monkeylord
committed
Jun 4, 2019
1 parent
edfe73e
commit 6505455
Showing
7 changed files
with
228 additions
and
5 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>MemoryReader</title> | ||
</head> | ||
<body> | ||
<details> | ||
<summary>Memory Maps</summary> | ||
<#list maps as map> | ||
<p>${map}</p> | ||
</#list> | ||
</details> | ||
<h1>Memory Editor:</h1> | ||
<p>Address:<input id="addr" type="text"/></p> | ||
<p>Count :<input id="count" type="text"/></p> | ||
|
||
<input id="read" type="button" value="Read" onclick="readMem()"/> | ||
<input id="write" type="button" value="Write" onclick="writeMem()"/> | ||
<input id="dump" type="button" value="Dump" onclick="dumpMem()"/> | ||
<p></p> | ||
<textarea id="mem" rows="8" cols="32"></textarea> | ||
</body> | ||
<script type="text/javascript"> | ||
function readMem(){ | ||
var addr = parseInt(document.getElementById("addr").value, 16); | ||
var count = parseInt(document.getElementById("count").value); | ||
xml = new XMLHttpRequest(); | ||
xml.open("GET","/memory?op=read&addr="+addr+"&count="+count, false); | ||
xml.send(); | ||
document.getElementById("mem").value=xml.responseText; | ||
} | ||
function dumpMem(){ | ||
var addr = parseInt(document.getElementById("addr").value, 16); | ||
var count = parseInt(document.getElementById("count").value); | ||
xml = new XMLHttpRequest(); | ||
xml.open("GET","/memory?op=dump&addr="+addr+"&count="+count, false); | ||
xml.send(); | ||
document.getElementById("mem").value=xml.responseText; | ||
} | ||
|
||
// Does not work. | ||
function writeMem(){ | ||
var addr = parseInt(document.getElementById("addr").value, 16); | ||
var count = parseInt(document.getElementById("count").value); | ||
xml = new XMLHttpRequest(); | ||
xml.open("POST","/memory?op=write&addr="+addr, false); | ||
xml.send(document.getElementById("mem").value); | ||
document.getElementById("mem").value=xml.responseText; | ||
} | ||
|
||
</script> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package monkeylord.XServer.api; | ||
|
||
import android.util.Log; | ||
|
||
import java.io.File; | ||
import java.io.FileOutputStream; | ||
import java.lang.reflect.Method; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import monkeylord.XServer.XServer; | ||
import monkeylord.XServer.handler.MemoryHandler; | ||
import monkeylord.XServer.handler.MethodHandler; | ||
|
||
public class MemoryView implements XServer.Operation { | ||
@Override | ||
public String handle(String url, Map<String, String> parms, Map<String, String> headers, Map<String, String> files) { | ||
try { | ||
Method method=null; | ||
if(parms.get("op")!=null) { | ||
switch (parms.get("op")){ | ||
case "dump": | ||
byte[] binary=MemoryHandler.readMemory(Long.parseLong(parms.get("addr")),Integer.parseInt(parms.get("count"))); | ||
FileOutputStream fo = new FileOutputStream(new File("/sdcard/XServer.dump")); | ||
fo.write(binary); | ||
return "Dumped at /sdcard/XServer.dump"; | ||
case "read": | ||
byte[] bytes=MemoryHandler.readMemory(Long.parseLong(parms.get("addr")),Integer.parseInt(parms.get("count"))); | ||
return bytesToHexString(bytes); | ||
case "write": | ||
MemoryHandler.writeMemory(Long.parseLong(parms.get("addr")),hexStringToBytes(files.get("postData"))); | ||
byte[] bytes_res=MemoryHandler.readMemory(Long.parseLong(parms.get("addr")),hexStringToBytes(files.get("postData")).length); | ||
return bytesToHexString(bytes_res); | ||
default: | ||
return ""; | ||
} | ||
}else{ | ||
HashMap<String, Object> map = new HashMap<>(); | ||
map.put("maps", MemoryHandler.getMaps()); | ||
return XServer.render(map, "pages/memory.html"); | ||
} | ||
} catch (Exception e) { | ||
return e.getLocalizedMessage(); | ||
} | ||
} | ||
|
||
public static String bytesToHexString(byte[] src){ | ||
StringBuffer stringBuffer = new StringBuffer(src.length*2+2); | ||
byte[] hexs = "0123456789ABCDEF".getBytes(); | ||
if (src == null || src.length <= 0) { | ||
return null; | ||
} | ||
for (int i = 0; i < src.length; i++) { | ||
//Log.e("XServer", "bytesToHexString: "+((src[i]&0xFF)>>4)); | ||
//Log.e("XServer", "bytesToHexString: "+((src[i]&0x0F))); | ||
stringBuffer.append((char) (hexs[(src[i]&0xFF)>>4])); | ||
stringBuffer.append((char) (hexs[src[i]&0x0F])); | ||
/* | ||
int v = src[i] & 0xFF; | ||
String hv = Integer.toHexString(v); | ||
if (hv.length() < 2) { | ||
stringBuffer.append(0); | ||
} | ||
stringBuffer.append(hv); | ||
*/ | ||
} | ||
return stringBuffer.toString(); | ||
} | ||
public static byte[] hexStringToBytes(String hexString) { | ||
if (hexString == null || hexString.equals("")) { | ||
return null; | ||
} | ||
hexString = hexString.toUpperCase(); | ||
int length = hexString.length() / 2; | ||
char[] hexChars = hexString.toCharArray(); | ||
byte[] d = new byte[length]; | ||
for (int i = 0; i < length; i++) { | ||
int pos = i * 2; | ||
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); | ||
} | ||
return d; | ||
} | ||
/** | ||
* Convert char to byte | ||
* @param c char | ||
* @return byte | ||
*/ | ||
private static byte charToByte(char c) { | ||
return (byte) "0123456789ABCDEF".indexOf(c); | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
app/src/main/java/monkeylord/XServer/handler/MemoryHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package monkeylord.XServer.handler; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
import java.util.HashMap; | ||
|
||
import de.robv.android.xposed.XposedBridge; | ||
import monkeylord.XServer.XposedEntry; | ||
|
||
public class MemoryHandler { | ||
static HashMap<String, Method> Memory = new HashMap<>(); | ||
static { | ||
try { | ||
// http://androidxref.com/4.4_r1/xref/libcore/luni/src/main/java/libcore/io/Memory.java | ||
Class clzMemory = Class.forName("libcore.io.Memory"); | ||
for (Method m:clzMemory.getDeclaredMethods()) { | ||
Memory.put(m.getName(),m); | ||
} | ||
} catch (ClassNotFoundException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
public static byte[] readMemory(long address,int count) throws InvocationTargetException, IllegalAccessException { | ||
if(Memory.get("peekByteArray")==null)throw new IllegalAccessException(); | ||
byte[] data=new byte[count]; | ||
Memory.get("peekByteArray").invoke(null,address, data, 0, count); | ||
return data; | ||
} | ||
public static void writeMemory(long address,byte[] data) throws IllegalAccessException, InvocationTargetException { | ||
if(Memory.get("pokeByteArray")==null)throw new IllegalAccessException(); | ||
byte[] mem = readMemory(address,data.length); | ||
for (int i = 0; i < mem.length; i++) { | ||
if(mem[i]!=data[i]){ | ||
Memory.get("pokeByte").invoke(null,address+i,data[i]); | ||
} | ||
} | ||
//Memory.get("pokeByteArray").invoke(null,address, mem, 0, mem.length); | ||
} | ||
public static String[] getMaps(){ | ||
File maps=new File("/proc/self/maps"); | ||
StringBuilder sb = new StringBuilder(); | ||
try { | ||
FileInputStream is = new FileInputStream(maps); | ||
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); | ||
String str; | ||
while((str=reader.readLine())!=null){ | ||
sb.append(str+"\r\n"); | ||
} | ||
/* | ||
Process p = Runtime.getRuntime().exec("cat /proc/self/maps"); | ||
p.waitFor(); | ||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); | ||
String str; | ||
while((str=reader.readLine())!=null){ | ||
sb.append(str+"\r\n"); | ||
} | ||
*/ | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
return sb.toString().split("\r\n"); | ||
} | ||
|
||
} |