Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 98d3543
Showing
8 changed files
with
295 additions
and
0 deletions.
There are no files selected for viewing
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,4 @@ | ||
{ | ||
"esversion":6, | ||
"asi":true | ||
} |
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,8 @@ | ||
# JavaScript Virtualization Obfuscation | ||
|
||
|
||
|
||
## Great, so yet another obfuscation scheme? | ||
Well yes kind of, but this one is different. | ||
- Regular schemes: make it incrementally harder | ||
- VO: sets the overall bar higher |
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,18 @@ | ||
function transform(text) { | ||
// ... | ||
return text; | ||
} | ||
|
||
document.getElementById("mybutton").onclick = function() { | ||
|
||
var secret_text = document.getElementById("secret_ipt").value; | ||
console.log(secret_text); | ||
|
||
document.getElementById("secret_output").value = transform(secret_text); | ||
}; | ||
|
||
|
||
|
||
|
||
|
||
// XMLHttpRequest |
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,7 @@ | ||
function wrapBytecode() | ||
{ | ||
|
||
} | ||
|
||
|
||
export {wrapBytecode}; |
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,18 @@ | ||
<html> | ||
<head> | ||
<meta charset="UTF-8"/> | ||
<!-- <script type='text/javascript' src="tests/vm.test.js"></script> --> | ||
</head> | ||
<body> | ||
<div> | ||
<input id="secret_ipt" placeholder="text" value="Secret Text"/> | ||
<button id="mybutton">Calculate</button> | ||
</div> | ||
<div> | ||
<input id="secret_output" placeholder="text" value=""/> | ||
</div> | ||
<script type='text/javascript' src="example.js"></script> | ||
<!-- <script type='text/javascript' src="tests/vm.test.js"></script> --> | ||
<script type='text/javascript' src="vm.js"></script> | ||
</body> | ||
</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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
var webdriver = require('selenium-webdriver'), | ||
By = webdriver.By, | ||
until = webdriver.until; | ||
|
||
var firefox = require('selenium-webdriver/firefox'); | ||
|
||
var options = new firefox.Options(); | ||
options.addArguments("-headless"); | ||
|
||
var driver = new webdriver.Builder() | ||
.forBrowser('firefox') | ||
.setFirefoxOptions(options) | ||
.build(); | ||
|
||
driver.get('https://www.google.com'); | ||
driver.findElement(By.name('q')).sendKeys('webdriver'); | ||
|
||
driver.sleep(1000).then(function() { | ||
driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB); | ||
}); | ||
|
||
driver.findElement(By.name('btnK')).click(); | ||
|
||
driver.sleep(2000).then(function() { | ||
driver.getTitle().then(function(title) { | ||
if(title === 'webdriver - Google Search') { | ||
console.log('Test passed'); | ||
} else { | ||
console.log('Test failed'); | ||
} | ||
}); | ||
}); | ||
|
||
driver.quit(); |
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,34 @@ | ||
import VM from '/home/motu/blogpost/code/vm.js'; | ||
import * as helpers from '../helpers.js'; | ||
|
||
const testDataSet = [ | ||
{ | ||
name: "Empty Bytecode", | ||
bytecode: [], | ||
registers: {}, | ||
} | ||
] | ||
|
||
function runVMTests(testData) | ||
{ | ||
try { | ||
var wrappedBytecode = helpers.wrapBytecode(testData[bytecode]); | ||
|
||
var vm = new VM(); | ||
var result = vm.invoke(wrappedBytecode); | ||
|
||
if(result == 0) { | ||
console.log(testData[name], "passed"); | ||
} else { | ||
console.warn(testData[name], "failed with return value: ", result); | ||
} | ||
} catch(e) { | ||
console.warn(testData[name], "failed with exception: ", e); | ||
} | ||
|
||
} | ||
|
||
|
||
|
||
|
||
runVMTests(); |
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,172 @@ | ||
// var bytecode = [50, 14, "getElementById".charCodeAt(0...13)]; | ||
|
||
const REGS = { | ||
STACK_PTR: 1, | ||
DOCUMENT: 2, | ||
RETURN_VAL: 3, | ||
}; | ||
|
||
const OP = { | ||
// Loaders | ||
LOAD_STRING: 1, | ||
LOAD_NUM: 2, | ||
|
||
// Misc | ||
PROPACCESS: 10, | ||
|
||
// Math | ||
ADD: 100, | ||
MUL: 101, | ||
}; | ||
|
||
class VM | ||
{ | ||
|
||
constructor() { | ||
this.regs = []; | ||
this.stack = []; | ||
this.ops = []; | ||
|
||
this.ops[OP.PROPACCESS] = function(vm) { | ||
var dst = vm.getByte(), obj = vm.getByte(), prop = vm.getByte(); | ||
obj = vm.getReg(obj); prop = vm.getReg(prop); | ||
|
||
vm.setReg(dst, obj[prop]); | ||
}; | ||
|
||
this.ops[OP.LOAD_STRING] = function(vm) { | ||
var dst = vm.getByte(), len = vm.getByte(); | ||
var str = ""; | ||
for(var i = 0; i < len; i++) { | ||
str = String.fromCharCode(vm.getByte()); | ||
} | ||
vm.setReg(dst, str); | ||
}; | ||
|
||
this.ops[OP.LOAD_NUM] = function(vm) { | ||
var dst = vm.getByte(), val = vm.getByte(); | ||
vm.setReg(dst, val); | ||
} | ||
|
||
this.ops[OP.ADD] = function(vm) { | ||
var dst = vm.getByte(), src = vm.getByte(); | ||
vm.setReg(dst, vm.regs[dst] + vm.regs[src]); | ||
} | ||
|
||
this.ops[OP.MUL] = function(vm) { | ||
var dst = vm.getByte(), src = vm.getByte(); | ||
vm.setReg(dst, vm.regs[dst] * vm.regs[src]); | ||
} | ||
} | ||
|
||
|
||
setReg(reg, value) { | ||
this.regs[reg] = value; | ||
}; | ||
|
||
getReg(reg) { | ||
return this.regs[reg]; | ||
}; | ||
|
||
getByte() { | ||
return this.stack[this.regs[REGS.STACK_PTR]++]; | ||
}; | ||
|
||
dispatcher() { | ||
while(this.regs[REGS.STACK_PTR] < this.stack.length) { | ||
var op_code = this.getByte(); | ||
var op = this.ops[op_code]; | ||
op(this); | ||
} | ||
|
||
return this.regs[REGS.RETURN_VAL]; | ||
}; | ||
|
||
decodeBytecode(encodedBytecode) { | ||
return encodedBytecode; | ||
}; | ||
|
||
init(bytecode) { | ||
this.stack = this.decodeBytecode(bytecode); | ||
this.regs[REGS.STACK_PTR] = 0; | ||
// this.regs[REGS.DOCUMENT] = document; | ||
this.regs[REGS.RETURN_VAL] = 0; | ||
}; | ||
|
||
invoke(bytecode) { | ||
this.init(bytecode); | ||
return this.dispatcher(); | ||
}; | ||
|
||
} | ||
|
||
|
||
|
||
///! HELPERS | ||
|
||
function wrapBytecode(nonWrappedBytecode) | ||
{ | ||
return nonWrappedBytecode; | ||
} | ||
|
||
|
||
|
||
|
||
///! TESTING | ||
|
||
const testDataSet = [ | ||
{ | ||
name: "Empty Bytecode", | ||
bytecode: [], | ||
registers: {}, | ||
}, | ||
{ | ||
name: "Set return value 66", | ||
bytecode: [ | ||
OP.LOAD_NUM, 100, 66, // LOAD NUM 66 INTO REGISTER 100 | ||
], | ||
registers: [ | ||
[100, 66] | ||
], | ||
}, | ||
{ | ||
name: "Multiply two registers", | ||
bytecode: [ | ||
OP.LOAD_NUM, 100, 3, // LOAD NUM 3 INTO REGISTER 100 | ||
OP.LOAD_NUM, 101, 2, // LOAD NUM 2 INTO REGISTER 101 | ||
OP.MUL, 100, 101, // MULTIPLY NUM IN REG 100 WITH NUM IN REG 101 | ||
], | ||
registers: [ | ||
[100, 6] | ||
], | ||
} | ||
] | ||
|
||
function runVMTests(testData) { | ||
try { | ||
var wrappedBytecode = wrapBytecode(testData.bytecode); | ||
|
||
var vm = new VM(); | ||
var result = vm.invoke(wrappedBytecode); | ||
|
||
if(result == 0) { | ||
|
||
for(let regData in testData.registers) { | ||
if(vm.getReg(regData[0]) !== regData[1]) { | ||
console.warn(testData.name, "failed with return value: ", result); | ||
} | ||
} | ||
|
||
console.log(testData.name, "passed"); | ||
} else { | ||
console.warn(testData.name, "failed with return value: ", result); | ||
} | ||
} catch(e) { | ||
console.warn(testData.name, "failed with exception: ", e); | ||
} | ||
|
||
} | ||
|
||
for(let testData of testDataSet) { | ||
runVMTests(testData); | ||
} |