From 6ea17e7aa1e9bc4013dbd6cd1b90759e8ba4f874 Mon Sep 17 00:00:00 2001 From: William Shackleton Date: Mon, 12 May 2014 22:07:18 +0100 Subject: [PATCH 1/3] Added HTML content changing spoofs, including changing text and embedding JS in pages. --- res/values/spoofs.xml | 5 ++ .../digitalsquid/netspoofer/config/Lists.java | 11 +++ .../netspoofer/config/RunManager.java | 4 + .../netspoofer/proxy/NSProxy.java | 14 +++- .../netspoofer/spoofs/ContentChange.java | 83 +++++++++++++++++++ .../netspoofer/spoofs/TitleChange.java | 9 +- 6 files changed, 118 insertions(+), 8 deletions(-) create mode 100644 src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java diff --git a/res/values/spoofs.xml b/res/values/spoofs.xml index 2601827..db0ae52 100644 --- a/res/values/spoofs.xml +++ b/res/values/spoofs.xml @@ -49,4 +49,9 @@ Reverse title Reverse all website titles + Flip content + Turn the content of all websites upside down + + Websites experience gravity + All elements on websites fall to the bottom of the page diff --git a/src/uk/digitalsquid/netspoofer/config/Lists.java b/src/uk/digitalsquid/netspoofer/config/Lists.java index 38fe435..8d42e38 100644 --- a/src/uk/digitalsquid/netspoofer/config/Lists.java +++ b/src/uk/digitalsquid/netspoofer/config/Lists.java @@ -22,6 +22,7 @@ package uk.digitalsquid.netspoofer.config; import java.util.ArrayList; +import java.util.Map; public final class Lists { private Lists() {} @@ -31,4 +32,14 @@ public static final ArrayList singleton(T x) { result.add(x); return result; } + + public static final String map(Map map, String in) { + StringBuilder result = new StringBuilder(in.length()); + for(char c : in.toCharArray()) { + Character ud = map.get(c); + if(ud == null) ud = c; + result.append(ud); + } + return result.toString(); + } } diff --git a/src/uk/digitalsquid/netspoofer/config/RunManager.java b/src/uk/digitalsquid/netspoofer/config/RunManager.java index 75736f7..1f48e5f 100644 --- a/src/uk/digitalsquid/netspoofer/config/RunManager.java +++ b/src/uk/digitalsquid/netspoofer/config/RunManager.java @@ -31,6 +31,7 @@ import java.util.Map; import uk.digitalsquid.netspoofer.proxy.NSProxy; +import uk.digitalsquid.netspoofer.spoofs.ContentChange; import uk.digitalsquid.netspoofer.spoofs.CustomGalleryImageChange; import uk.digitalsquid.netspoofer.spoofs.ImageSpoof; import uk.digitalsquid.netspoofer.spoofs.MultiSpoof; @@ -74,6 +75,9 @@ public ArrayList getSpoofList() { spoofs.add(new TitleChange(context, TitleChange.MODE_FLIP)); spoofs.add(new TitleChange(context, TitleChange.MODE_REVERSE)); + + spoofs.add(new ContentChange(context, ContentChange.MODE_FLIP)); + spoofs.add(new ContentChange(context, ContentChange.MODE_GRAVITY)); Collections.sort(spoofs); diff --git a/src/uk/digitalsquid/netspoofer/proxy/NSProxy.java b/src/uk/digitalsquid/netspoofer/proxy/NSProxy.java index 117b8ca..366199e 100644 --- a/src/uk/digitalsquid/netspoofer/proxy/NSProxy.java +++ b/src/uk/digitalsquid/netspoofer/proxy/NSProxy.java @@ -166,7 +166,8 @@ protected int doInBackground(StartParams params) { Log.d(TAG, "Sending request"); HttpResponse response = executeRequest(request); Log.d(TAG, "Response received"); - manipulateResponse(response, request); + if(!whitelistRequest(request)) + manipulateResponse(response, request); Log.d(TAG, "Response manipulated"); output.write(String.format("HTTP/1.1 %d %s\r\n", response.getResponseCode(), @@ -278,4 +279,15 @@ private boolean filterRequest(HttpRequest request) { if(host.contains(".dropbox.com")) return false; return true; } + + /** + * Filters out requests that shouldn't be modified. + * @param request + * @return true if the request shouldn't be modified. + */ + private boolean whitelistRequest(HttpRequest request) { + String host = request.getHost(); + if(host.equals("gravityscript.googlecode.com")) return true; + return false; + } } diff --git a/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java b/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java new file mode 100644 index 0000000..c669425 --- /dev/null +++ b/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java @@ -0,0 +1,83 @@ +package uk.digitalsquid.netspoofer.spoofs; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; +import org.jsoup.nodes.TextNode; + +import uk.digitalsquid.netspoofer.R; +import uk.digitalsquid.netspoofer.config.Lists; +import android.content.Context; + +public class ContentChange extends HtmlEditorSpoof { + + private static final long serialVersionUID = 792590861534877480L; + public static final int MODE_FLIP = 1; + public static final int MODE_GRAVITY = 2; + + private static String getTitle(Context context, int mode) { + switch(mode) { + case MODE_FLIP: + return context.getResources().getString(R.string.spoof_content_flip); + case MODE_GRAVITY: + + return context.getResources().getString(R.string.spoof_gravity); + default: + return "Unknown image spoof"; + } + } + private static String getDescription(Context context, int mode) { + switch(mode) { + case MODE_FLIP: + return context.getResources().getString(R.string.spoof_content_flip_description); + case MODE_GRAVITY: + return context.getResources().getString(R.string.spoof_gravity_description); + default: + return ""; + } + } + + private final int mode; + + public ContentChange(Context context, int mode) { + super(getTitle(context, mode), getDescription(context, mode)); + this.mode = mode; + } + + @Override + protected void modifyDocument(Document document, Element body) { + switch(mode) { + case MODE_FLIP: + modifyElement(body); + break; + case MODE_GRAVITY: + document.select("head").append( + ""); + break; + } + } + + /** + * Recursively modifies an element according to mode. + * @param element + */ + private void modifyElement(Element element) { + for(Node node : element.childNodes()) { + if(node instanceof TextNode) { + modifyTextNode((TextNode) node); + } else if(node instanceof Element) { + modifyElement((Element) node); + } + } + } + + private void modifyTextNode(TextNode node) { + switch(mode) { + case MODE_FLIP: + String reversed = + new StringBuilder(node.text()).reverse().toString(); + node.text(Lists.map(TitleChange.upsideDown, reversed)); + break; + } + } +} diff --git a/src/uk/digitalsquid/netspoofer/spoofs/TitleChange.java b/src/uk/digitalsquid/netspoofer/spoofs/TitleChange.java index d9ac003..0ad50d3 100644 --- a/src/uk/digitalsquid/netspoofer/spoofs/TitleChange.java +++ b/src/uk/digitalsquid/netspoofer/spoofs/TitleChange.java @@ -7,6 +7,7 @@ import org.jsoup.select.Elements; import uk.digitalsquid.netspoofer.R; +import uk.digitalsquid.netspoofer.config.Lists; import android.content.Context; public class TitleChange extends HtmlEditorSpoof { @@ -52,13 +53,7 @@ protected void modifyDocument(Document document, Element body) { Element title = titles.first(); String reversed = new StringBuilder(title.text()).reverse().toString(); - StringBuilder result = new StringBuilder(reversed.length()); - for(char c : reversed.toCharArray()) { - Character ud = upsideDown.get(c); - if(ud == null) ud = c; - result.append(ud); - } - title.text(result.toString()); + title.text(Lists.map(upsideDown, reversed)); } break; case MODE_REVERSE: From 031d5f470b494936d703d0ad44a405822f618710 Mon Sep 17 00:00:00 2001 From: William Shackleton Date: Mon, 12 May 2014 22:39:08 +0100 Subject: [PATCH 2/3] Added word deletion spoof --- res/raw/js_removewords | 18 +++++++++ res/values/spoofs.xml | 3 +- .../netspoofer/config/IOHelpers.java | 13 ++++--- .../netspoofer/config/RunManager.java | 1 + .../netspoofer/spoofs/ContentChange.java | 39 +++++++++++++++++-- 5 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 res/raw/js_removewords diff --git a/res/raw/js_removewords b/res/raw/js_removewords new file mode 100644 index 0000000..c44b27a --- /dev/null +++ b/res/raw/js_removewords @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/res/values/spoofs.xml b/res/values/spoofs.xml index db0ae52..22e2efd 100644 --- a/res/values/spoofs.xml +++ b/res/values/spoofs.xml @@ -51,7 +51,8 @@ Flip content Turn the content of all websites upside down - Websites experience gravity All elements on websites fall to the bottom of the page + Delete random words + Words disappear from pages every second diff --git a/src/uk/digitalsquid/netspoofer/config/IOHelpers.java b/src/uk/digitalsquid/netspoofer/config/IOHelpers.java index 20fd933..0c34a84 100644 --- a/src/uk/digitalsquid/netspoofer/config/IOHelpers.java +++ b/src/uk/digitalsquid/netspoofer/config/IOHelpers.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.StringWriter; import java.util.ArrayList; import java.util.List; @@ -40,12 +41,14 @@ private IOHelpers() {} * @throws IOException */ public static final String readFileContents(InputStream is) throws IOException { - StringBuffer out = new StringBuffer(); - byte[] b = new byte[256]; - for (int n; (n = is.read(b)) != -1;) { - out.append(new String(b, 0, n)); + StringWriter out = new StringWriter(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line; + while((line = reader.readLine()) != null) { + out.append(line); + out.append('\n'); } - is.close(); + reader.close(); return out.toString(); } diff --git a/src/uk/digitalsquid/netspoofer/config/RunManager.java b/src/uk/digitalsquid/netspoofer/config/RunManager.java index 1f48e5f..2a591aa 100644 --- a/src/uk/digitalsquid/netspoofer/config/RunManager.java +++ b/src/uk/digitalsquid/netspoofer/config/RunManager.java @@ -78,6 +78,7 @@ public ArrayList getSpoofList() { spoofs.add(new ContentChange(context, ContentChange.MODE_FLIP)); spoofs.add(new ContentChange(context, ContentChange.MODE_GRAVITY)); + spoofs.add(new ContentChange(context, ContentChange.MODE_DELETE)); Collections.sort(spoofs); diff --git a/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java b/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java index c669425..899b6c0 100644 --- a/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java +++ b/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java @@ -1,27 +1,35 @@ package uk.digitalsquid.netspoofer.spoofs; +import java.io.IOException; + import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.nodes.Node; import org.jsoup.nodes.TextNode; import uk.digitalsquid.netspoofer.R; +import uk.digitalsquid.netspoofer.config.IOHelpers; import uk.digitalsquid.netspoofer.config.Lists; +import uk.digitalsquid.netspoofer.config.LogConf; import android.content.Context; +import android.content.res.Resources.NotFoundException; +import android.util.Log; -public class ContentChange extends HtmlEditorSpoof { +public class ContentChange extends HtmlEditorSpoof implements LogConf { private static final long serialVersionUID = 792590861534877480L; public static final int MODE_FLIP = 1; public static final int MODE_GRAVITY = 2; + public static final int MODE_DELETE = 3; private static String getTitle(Context context, int mode) { switch(mode) { case MODE_FLIP: return context.getResources().getString(R.string.spoof_content_flip); case MODE_GRAVITY: - return context.getResources().getString(R.string.spoof_gravity); + case MODE_DELETE: + return context.getResources().getString(R.string.spoof_delete); default: return "Unknown image spoof"; } @@ -32,16 +40,38 @@ private static String getDescription(Context context, int mode) { return context.getResources().getString(R.string.spoof_content_flip_description); case MODE_GRAVITY: return context.getResources().getString(R.string.spoof_gravity_description); + case MODE_DELETE: + return context.getResources().getString(R.string.spoof_delete_description); default: return ""; } } private final int mode; + + private final String js; public ContentChange(Context context, int mode) { super(getTitle(context, mode), getDescription(context, mode)); this.mode = mode; + switch(mode) { + default: + case MODE_GRAVITY: + js = ""; + break; + case MODE_DELETE: + String payload = ""; + try { + payload = IOHelpers.readFileContents( + context.getResources().openRawResource(R.raw.js_removewords)); + } catch (NotFoundException e) { + Log.w(TAG, "Failed to load js_removewords payload", e); + } catch (IOException e) { + Log.w(TAG, "Failed to load js_removewords payload", e); + } + js = payload; + break; + } } @Override @@ -51,9 +81,10 @@ protected void modifyDocument(Document document, Element body) { modifyElement(body); break; case MODE_GRAVITY: - document.select("head").append( - ""); + case MODE_DELETE: + document.select("head").append(js); break; + } } From 9a33d95e3f8984693af13a7d1c040dc86362625f Mon Sep 17 00:00:00 2001 From: William Shackleton Date: Mon, 12 May 2014 22:52:00 +0100 Subject: [PATCH 3/3] Added a couple of remaining missing spoofs --- res/values/spoofs.xml | 3 ++ .../netspoofer/config/RunManager.java | 3 ++ .../netspoofer/spoofs/ContentChange.java | 17 ++++++++-- .../netspoofer/spoofs/CustomTextChange.java | 34 +++++++++++-------- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/res/values/spoofs.xml b/res/values/spoofs.xml index 22e2efd..869f06b 100644 --- a/res/values/spoofs.xml +++ b/res/values/spoofs.xml @@ -55,4 +55,7 @@ All elements on websites fall to the bottom of the page Delete random words Words disappear from pages every second + + Change text + Replace words with others diff --git a/src/uk/digitalsquid/netspoofer/config/RunManager.java b/src/uk/digitalsquid/netspoofer/config/RunManager.java index 2a591aa..55ab41e 100644 --- a/src/uk/digitalsquid/netspoofer/config/RunManager.java +++ b/src/uk/digitalsquid/netspoofer/config/RunManager.java @@ -33,6 +33,7 @@ import uk.digitalsquid.netspoofer.proxy.NSProxy; import uk.digitalsquid.netspoofer.spoofs.ContentChange; import uk.digitalsquid.netspoofer.spoofs.CustomGalleryImageChange; +import uk.digitalsquid.netspoofer.spoofs.CustomTextChange; import uk.digitalsquid.netspoofer.spoofs.ImageSpoof; import uk.digitalsquid.netspoofer.spoofs.MultiSpoof; import uk.digitalsquid.netspoofer.spoofs.NullSpoof; @@ -70,6 +71,8 @@ public ArrayList getSpoofList() { spoofs.add(new VideoChange(context, true)); spoofs.add(new VideoChange(context, false)); + spoofs.add(new CustomTextChange(context)); + spoofs.add(new RedirectSpoof(context, RedirectSpoof.MODE_BLUEBALL)); spoofs.add(new RedirectSpoof(context, RedirectSpoof.MODE_CUSTOM)); diff --git a/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java b/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java index 899b6c0..1e72b6b 100644 --- a/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java +++ b/src/uk/digitalsquid/netspoofer/spoofs/ContentChange.java @@ -47,7 +47,7 @@ private static String getDescription(Context context, int mode) { } } - private final int mode; + protected final int mode; private final String js; @@ -73,10 +73,23 @@ public ContentChange(Context context, int mode) { break; } } + + /** + * If using a custom mode it MUST NOT collide with existing modes. + * @param title + * @param description + * @param mode + */ + protected ContentChange(String title, String description, int mode) { + super(title, description); + js = ""; + this.mode = mode; + } @Override protected void modifyDocument(Document document, Element body) { switch(mode) { + default: // To allow custom implementations to pass through case MODE_FLIP: modifyElement(body); break; @@ -102,7 +115,7 @@ private void modifyElement(Element element) { } } - private void modifyTextNode(TextNode node) { + protected void modifyTextNode(TextNode node) { switch(mode) { case MODE_FLIP: String reversed = diff --git a/src/uk/digitalsquid/netspoofer/spoofs/CustomTextChange.java b/src/uk/digitalsquid/netspoofer/spoofs/CustomTextChange.java index 9b56c2a..6266107 100644 --- a/src/uk/digitalsquid/netspoofer/spoofs/CustomTextChange.java +++ b/src/uk/digitalsquid/netspoofer/spoofs/CustomTextChange.java @@ -24,8 +24,7 @@ import java.util.HashMap; import java.util.Map; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; import uk.digitalsquid.netspoofer.R; import android.app.AlertDialog; @@ -43,12 +42,14 @@ * @author Will Shackleton * */ -public class CustomTextChange extends HtmlEditorSpoof { +public class CustomTextChange extends ContentChange { private static final long serialVersionUID = 8490503138296852028L; + + private static final int MODE = 1005; - public CustomTextChange() { - // TODO: Localise - super("Text change", "Change all text on all websites"); + public CustomTextChange(Context context) { + super(context.getResources().getString(R.string.spoof_textchange), + context.getResources().getString(R.string.spoof_textchange_description), MODE); } private final Map changeValues = new HashMap(8); @@ -134,14 +135,19 @@ public void onClick(DialogInterface dialog, int which) { } @Override - public Map getCustomEnv() { - return changeValues; - } - - @Override - protected void modifyDocument(Document document, Element body) { - if(body != null) { - + protected void modifyTextNode(TextNode node) { + super.modifyTextNode(node); + switch(mode) { + case MODE: + String text = node.text(); + for(int i = 0 ; i < 8; i++) { + String from = changeValues.get(String.format("TEXT%dOLD", i)); + String to = changeValues.get(String.format("TEXT%dNEW", i)); + if(from != null && to != null) + text = text.replace(from, to); + } + node.text(text); + break; } } }