mirror of
https://github.com/geohot/qira
synced 2025-01-13 22:29:24 +03:00
refactoring
This commit is contained in:
parent
59073e74a0
commit
c10058babd
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
web/.meteor
|
||||
.*.swp
|
||||
tests/a.out
|
||||
*.pyc
|
||||
|
||||
|
@ -13,7 +13,8 @@ class Address:
|
||||
if clnum in this.backing:
|
||||
return this.backing[clnum]
|
||||
clnum -= 1
|
||||
return 0xAA # canary
|
||||
# if the change is before it was written to
|
||||
return 0 # canary
|
||||
|
||||
def commit(this, clnum, dat):
|
||||
this.backing[clnum] = dat
|
||||
|
2
web/client/compatibility/socket.io.min.js
vendored
Normal file
2
web/client/compatibility/socket.io.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
241
web/client/qira.js
Normal file
241
web/client/qira.js
Normal file
@ -0,0 +1,241 @@
|
||||
Change = new Meteor.Collection("change");
|
||||
Program = new Meteor.Collection("program");
|
||||
|
||||
// bitops make numbers negative
|
||||
|
||||
var X86REGS = ['EAX', 'ECX', 'EDX', 'EBX', 'ESP', 'EBP', 'ESI', 'EDI', 'EIP'];
|
||||
|
||||
function p(a) {
|
||||
console.log(a);
|
||||
}
|
||||
|
||||
function hex(a) {
|
||||
if (a == undefined) {
|
||||
return "";
|
||||
} else {
|
||||
if (a < 0) a += 0x100000000;
|
||||
return "0x"+a.toString(16);
|
||||
}
|
||||
}
|
||||
|
||||
window.onmousewheel = function(e) {
|
||||
if (e.target.id == "cfg" || $(e.target).parents("#cfg").length > 0) {
|
||||
if (e.wheelDelta < 0) {
|
||||
Session.set('clnum', Session.get('clnum')+1);
|
||||
} else if (e.wheelDelta > 0) {
|
||||
Session.set('clnum', Session.get('clnum')-1);
|
||||
}
|
||||
} else if (e.target.id == "hexdump" || $(e.target).parents("#hexdump").length > 0) {
|
||||
if (e.wheelDelta < 0) {
|
||||
Session.set('daddr', Session.get('daddr')+0x10);
|
||||
} else if (e.wheelDelta > 0) {
|
||||
Session.set('daddr', Session.get('daddr')-0x10);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var socket = undefined;
|
||||
function do_socket(callme) {
|
||||
if (socket == undefined) {
|
||||
p('connecting');
|
||||
socket = io.connect('http://localhost:3002');
|
||||
socket.on('connect', function() {
|
||||
p("socket connected");
|
||||
callme();
|
||||
});
|
||||
socket.on('memory', function(msg) {
|
||||
p(msg);
|
||||
var dat = atob(msg['raw'])
|
||||
// render the hex editor
|
||||
var addr = msg['address'];
|
||||
html = "<table><tr>";
|
||||
for (var i = 0; i < dat.length; i++) {
|
||||
if ((i&0xF) == 0) html += "</tr><tr><td>"+hex(addr+i)+":</td>";
|
||||
if ((i&0x3) == 0) html += "<td></td>";
|
||||
var me = dat.charCodeAt(i).toString(16);
|
||||
if (me.length == 1) me = "0" + me;
|
||||
if (addr+i == Session.get('daddr')) {
|
||||
html += '<td class="highlight">'+me+"</td>";
|
||||
} else {
|
||||
html += "<td>"+me+"</td>";
|
||||
}
|
||||
}
|
||||
html += "</tr></table>";
|
||||
$("#hexdump")[0].innerHTML = html;
|
||||
});
|
||||
socket.on('registers', function(msg) {
|
||||
//p(msg);
|
||||
html = "";
|
||||
for (i in msg) {
|
||||
html += "<div class=reg>"+i+": "+hex(msg[i])+"</div>";
|
||||
}
|
||||
$("#regviewer")[0].innerHTML = html;
|
||||
});
|
||||
} else {
|
||||
callme();
|
||||
}
|
||||
}
|
||||
Deps.autorun(function() {
|
||||
var daddr = Session.get('daddr');
|
||||
var clnum = Session.get('clnum');
|
||||
do_socket(function() {
|
||||
socket.emit('getmemory',
|
||||
{"clnum":clnum-1, "address":(daddr-0x20)-(daddr-0x20)%0x10, "len":0x100});
|
||||
});
|
||||
});
|
||||
|
||||
Deps.autorun(function() {
|
||||
var clnum = Session.get('clnum');
|
||||
do_socket(function() {
|
||||
socket.emit('getregisters', {"clnum":clnum-1});
|
||||
});
|
||||
});
|
||||
|
||||
// there should be a library for this
|
||||
Deps.autorun(function() {
|
||||
var json = {};
|
||||
// for dep tracking, can't use keys
|
||||
json['max_clnum'] = Session.get('max_clnum');
|
||||
json['clnum'] = Session.get('clnum');
|
||||
json['iaddr'] = Session.get('iaddr');
|
||||
json['daddr'] = Session.get('daddr');
|
||||
var hash = JSON.stringify(json);
|
||||
//p("updating hash to "+hash);
|
||||
window.location.hash = hash;
|
||||
});
|
||||
|
||||
function check_hash() {
|
||||
p("onhashchange");
|
||||
var hash = window.location.hash.substring(1);
|
||||
if (hash.length == 0) return;
|
||||
var json = JSON.parse(hash);
|
||||
//p(json);
|
||||
for (k in json) {
|
||||
if (Session.get(k) != json[k]) {
|
||||
Session.set(k, json[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = check_hash;
|
||||
|
||||
// TODO: fix this to not snapback
|
||||
//window.onhashchange = check_hash;
|
||||
|
||||
Deps.autorun(function() {
|
||||
var cl_selector = $('#cl_selector');
|
||||
var clnum = Session.get("clnum");
|
||||
var max_clnum = Session.get("max_clnum");
|
||||
if (cl_selector.length > 0) {
|
||||
cl_selector[0].value = clnum;
|
||||
cl_selector[0].max = max_clnum;
|
||||
cl_selector.slider('refresh');
|
||||
}
|
||||
});
|
||||
|
||||
Template.cfg.isiaddr = function() {
|
||||
var iaddr = Session.get('iaddr');
|
||||
if (this.address == iaddr) return "highlight";
|
||||
else return "";
|
||||
}
|
||||
|
||||
Template.cfg.hexaddress = function() { return hex(this.address)+": "; };
|
||||
|
||||
Template.cfg.lineardump = function() {
|
||||
var iaddr = Session.get('iaddr');
|
||||
if (iaddr !== undefined) {
|
||||
return Program.find({address: {$gt: iaddr-0x30, $lt: iaddr+0x80}}, {sort: {address:1}});
|
||||
}
|
||||
};
|
||||
|
||||
Template.timeline.max_clnum = function() {
|
||||
post = Change.findOne({}, {sort: {clnum: -1}});
|
||||
if (post != undefined) {
|
||||
Session.setDefault("clnum", post.clnum);
|
||||
Session.set("max_clnum", post.clnum);
|
||||
}
|
||||
};
|
||||
|
||||
Template.timeline.rendered = function() {
|
||||
$('#cl_selector').on("change", function(e) {
|
||||
var val = parseInt($('#cl_selector')[0].value);
|
||||
//p("change "+val);
|
||||
Session.set('clnum', val);
|
||||
});
|
||||
};
|
||||
|
||||
Template.changelist.currentchanges = function() {
|
||||
var clnum = Session.get('clnum');
|
||||
return Change.find({clnum: clnum}, {sort: {address: 1}, limit:20});
|
||||
};
|
||||
|
||||
Template.changelist.iaddr = function() { return hex(Session.get('iaddr')); };
|
||||
Template.changelist.daddr = function() { return hex(Session.get('daddr')); };
|
||||
Template.changelist.clnum = function() { return Session.get('clnum'); };
|
||||
|
||||
Template.changelist.icllist = function() {
|
||||
var iaddr = Session.get('iaddr');
|
||||
return Change.find({address: iaddr, type: "I"}, {sort: {clnum: 1},limit:10})
|
||||
};
|
||||
|
||||
Template.changelist.dcllist = function() {
|
||||
var daddr = Session.get('daddr');
|
||||
if (daddr >= 0x1000) {
|
||||
return Change.find({address:daddr}, {sort: {clnum: 1},limit:10});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Template.change.is_mem = function() {
|
||||
return this.type == "L" || this.type == "S";
|
||||
};
|
||||
|
||||
Template.cl.events({
|
||||
'click .change': function() {
|
||||
Session.set('clnum', this.clnum);
|
||||
}
|
||||
});
|
||||
|
||||
Template.change.events({
|
||||
'click .address': function() {
|
||||
p("new daddr is "+hex(this.address));
|
||||
Session.set('daddr', this.address);
|
||||
}
|
||||
});
|
||||
|
||||
Template.cfg.events({
|
||||
'click .address': function() {
|
||||
p("new iaddr from click is "+hex(this.address));
|
||||
Session.set('iaddr', this.address);
|
||||
}
|
||||
});
|
||||
|
||||
Template.change.handleaddress = function () {
|
||||
if (this.type == "I") {
|
||||
p("new iaddr is "+hex(this.address));
|
||||
Session.set('iaddr', this.address);
|
||||
}
|
||||
if (this.type == "R" || this.type == "W") {
|
||||
if (this.address < (X86REGS.length*4)) {
|
||||
return X86REGS[this.address/4];
|
||||
} else {
|
||||
return hex(this.address);
|
||||
}
|
||||
} else {
|
||||
return hex(this.address);
|
||||
}
|
||||
};
|
||||
|
||||
Template.change.handledata = function () {
|
||||
return hex(this.data);
|
||||
};
|
||||
|
||||
Deps.autorun(function(){ Meteor.subscribe('dat_iaddr', Session.get("iaddr")); });
|
||||
Deps.autorun(function(){ Meteor.subscribe('dat_daddr', Session.get("daddr")); });
|
||||
Deps.autorun(function(){ Meteor.subscribe('dat_clnum', Session.get("clnum")); });
|
||||
Deps.autorun(function(){ Meteor.subscribe('hexedit_daddr', Session.get("daddr"), Session.get("clnum")); });
|
||||
Deps.autorun(function(){ Meteor.subscribe('instruction_iaddr', Session.get("iaddr")); });
|
||||
|
||||
Meteor.subscribe('max_clnum');
|
||||
|
@ -2,7 +2,6 @@
|
||||
<title>qira</title>
|
||||
|
||||
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css">
|
||||
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
|
||||
<script src="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.16/socket.io.min.js"></script>
|
||||
</head>
|
||||
|
282
web/qira.js
282
web/qira.js
@ -1,282 +0,0 @@
|
||||
Change = new Meteor.Collection("change");
|
||||
Program = new Meteor.Collection("program");
|
||||
|
||||
// bitops make numbers negative
|
||||
|
||||
var X86REGS = ['EAX', 'ECX', 'EDX', 'EBX', 'ESP', 'EBP', 'ESI', 'EDI', 'EIP'];
|
||||
|
||||
function p(a) {
|
||||
console.log(a);
|
||||
}
|
||||
|
||||
function hex(a) {
|
||||
if (a == undefined) {
|
||||
return "";
|
||||
} else {
|
||||
if (a < 0) a += 0x100000000;
|
||||
return "0x"+a.toString(16);
|
||||
}
|
||||
}
|
||||
|
||||
if (Meteor.isClient) {
|
||||
window.onmousewheel = function(e) {
|
||||
if (e.wheelDelta < 0) {
|
||||
setters['clnum'](Session.get('clnum')+1);
|
||||
} else if (e.wheelDelta > 0) {
|
||||
setters['clnum'](Session.get('clnum')-1);
|
||||
}
|
||||
};
|
||||
|
||||
var socket = undefined;
|
||||
function do_socket(callme) {
|
||||
if (socket == undefined || socket.socket.connected == false) {
|
||||
p('connecting');
|
||||
socket = io.connect('http://localhost:3002');
|
||||
socket.on('connect', function() {
|
||||
p("socket connected");
|
||||
callme();
|
||||
});
|
||||
socket.on('memory', function(msg) {
|
||||
p(msg);
|
||||
var dat = atob(msg['raw'])
|
||||
// render the hex editor
|
||||
var addr = msg['address'];
|
||||
html = "<table><tr>";
|
||||
for (var i = 0; i < dat.length; i++) {
|
||||
if ((i&0xF) == 0) html += "</tr><tr><td>"+hex(addr+i)+":</td>";
|
||||
var me = dat.charCodeAt(i).toString(16);
|
||||
if (me.length == 1) me = "0" + me;
|
||||
if (addr+i == Session.get('daddr')) {
|
||||
html += '<td class="highlight">'+me+"</td>";
|
||||
} else {
|
||||
html += "<td>"+me+"</td>";
|
||||
}
|
||||
}
|
||||
html += "</tr></table>";
|
||||
$("#hexdump")[0].innerHTML = html;
|
||||
});
|
||||
socket.on('registers', function(msg) {
|
||||
html = "";
|
||||
for (i in msg) {
|
||||
html += "<div class=reg>"+i+": "+hex(msg[i])+"</div>";
|
||||
}
|
||||
$("#regviewer")[0].innerHTML = html;
|
||||
});
|
||||
} else {
|
||||
callme();
|
||||
}
|
||||
}
|
||||
function update_hexeditor(daddr, clnum) {
|
||||
do_socket(function() {
|
||||
socket.emit('getmemory',
|
||||
{"clnum":clnum, "address":(daddr-0x20)-(daddr-0x20)%0x10, "len":0x100});
|
||||
});
|
||||
}
|
||||
|
||||
function update_regdump(clnum) {
|
||||
do_socket(function() {
|
||||
socket.emit('getregisters', {"clnum":clnum});
|
||||
});
|
||||
}
|
||||
|
||||
// there should be a library for this
|
||||
function update_hash() {
|
||||
var json = {};
|
||||
// must call session get to get a number
|
||||
for (k in Session.keys) { json[k] = Session.get(k); }
|
||||
var hash = JSON.stringify(json);
|
||||
//p("updating hash to "+hash);
|
||||
window.location.hash = hash;
|
||||
}
|
||||
var setters = {
|
||||
"maxclnum": function(clnum) {
|
||||
Session.set("maxclnum", clnum);
|
||||
Session.setDefault("clnum", clnum);
|
||||
if ($('#cl_selector').length > 0) {
|
||||
$('#cl_selector')[0].max = clnum;
|
||||
update_current_clnum(Session.get("clnum"));
|
||||
}
|
||||
},
|
||||
"clnum": function(clnum) {
|
||||
Session.set("clnum", clnum);
|
||||
update_hash();
|
||||
update_hexeditor(Session.get("daddr"), clnum);
|
||||
update_regdump(clnum);
|
||||
},
|
||||
"iaddr": function(iaddr) {
|
||||
Session.set("iaddr", iaddr);
|
||||
update_hash();
|
||||
},
|
||||
"daddr": function(daddr) {
|
||||
Session.set("daddr", daddr);
|
||||
update_hash();
|
||||
update_hexeditor(daddr, Session.get("clnum"));
|
||||
}
|
||||
};
|
||||
function check_hash() {
|
||||
var hash = window.location.hash.substring(1);
|
||||
if (hash.length == 0) return;
|
||||
var json = JSON.parse(hash);
|
||||
//p(json);
|
||||
for (k in json) {
|
||||
if (Session.get(k) != json[k]) {
|
||||
setters[k](json[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
window.onload = check_hash;
|
||||
window.onhashchange = function() { check_hash(); }
|
||||
|
||||
function update_current_clnum(clnum) {
|
||||
var cl_selector = $('#cl_selector');
|
||||
cl_selector[0].value = clnum;
|
||||
cl_selector.slider('refresh');
|
||||
$(".ui-slider-handle").select();
|
||||
}
|
||||
|
||||
Template.cfg.isiaddr = function() {
|
||||
var iaddr = Session.get('iaddr');
|
||||
if (this.address == iaddr) return "highlight";
|
||||
else return "";
|
||||
}
|
||||
|
||||
Template.cfg.hexaddress = function() { return hex(this.address)+": "; };
|
||||
|
||||
Template.cfg.lineardump = function() {
|
||||
var iaddr = Session.get('iaddr');
|
||||
if (iaddr !== undefined) {
|
||||
return Program.find({address: {$gt: iaddr-0x30, $lt: iaddr+0x80}}, {sort: {address:1}});
|
||||
}
|
||||
};
|
||||
|
||||
Template.timeline.max_clnum = function() {
|
||||
var post = Change.findOne({}, {sort: {clnum: -1}});
|
||||
if (post != undefined) {
|
||||
setters['maxclnum'](post.clnum);
|
||||
}
|
||||
};
|
||||
|
||||
Template.timeline.rendered = function() {
|
||||
$('#cl_selector').on("change", function(e) {
|
||||
var val = parseInt($('#cl_selector')[0].value);
|
||||
setters['clnum'](val);
|
||||
});
|
||||
};
|
||||
|
||||
Template.changelist.currentchanges = function() {
|
||||
var clnum = Session.get('clnum');
|
||||
return Change.find({clnum: clnum}, {sort: {address: 1}, limit:20});
|
||||
};
|
||||
|
||||
Template.changelist.iaddr = function() { return hex(Session.get('iaddr')); };
|
||||
Template.changelist.daddr = function() { return hex(Session.get('daddr')); };
|
||||
Template.changelist.clnum = function() { return Session.get('clnum'); };
|
||||
|
||||
Template.changelist.icllist = function() {
|
||||
var iaddr = Session.get('iaddr');
|
||||
return Change.find({address: iaddr, type: "I"}, {sort: {clnum: 1},limit:10})
|
||||
};
|
||||
|
||||
Template.changelist.dcllist = function() {
|
||||
var daddr = Session.get('daddr');
|
||||
if (daddr >= 0x1000) {
|
||||
return Change.find({address:daddr}, {sort: {clnum: 1},limit:10});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Template.change.is_mem = function() {
|
||||
return this.type == "L" || this.type == "S";
|
||||
};
|
||||
|
||||
Template.cl.events({
|
||||
'click .change': function() {
|
||||
update_current_clnum(this.clnum);
|
||||
}
|
||||
});
|
||||
Template.change.events({
|
||||
'click .address': function() {
|
||||
p("new daddr is "+hex(this.address));
|
||||
setters['daddr'](this.address);
|
||||
}
|
||||
});
|
||||
|
||||
Template.cfg.events({
|
||||
'click .address': function() {
|
||||
p("new iaddr from click is "+hex(this.address));
|
||||
setters['iaddr'](this.address);
|
||||
}
|
||||
});
|
||||
|
||||
Template.change.handleaddress = function () {
|
||||
if (this.type == "I") {
|
||||
p("new iaddr is "+hex(this.address));
|
||||
setters['iaddr'](this.address);
|
||||
}
|
||||
if (this.type == "R" || this.type == "W") {
|
||||
if (this.address < (X86REGS.length*4)) {
|
||||
return X86REGS[this.address/4];
|
||||
} else {
|
||||
return hex(this.address);
|
||||
}
|
||||
} else {
|
||||
return hex(this.address);
|
||||
}
|
||||
};
|
||||
|
||||
Template.change.handledata = function () {
|
||||
return hex(this.data);
|
||||
};
|
||||
|
||||
var subs = new Meteor.autosubscribe(function(){
|
||||
Meteor.subscribe('dat_iaddr', Session.get("iaddr"));
|
||||
Meteor.subscribe('dat_daddr', Session.get("daddr"));
|
||||
Meteor.subscribe('dat_clnum', Session.get("clnum"));
|
||||
|
||||
Meteor.subscribe('hexedit_daddr', Session.get("daddr"), Session.get("clnum"));
|
||||
|
||||
Meteor.subscribe('instruction_iaddr', Session.get("iaddr"));
|
||||
});
|
||||
Meteor.subscribe('max_clnum');
|
||||
}
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Meteor.startup(function () {
|
||||
});
|
||||
|
||||
Meteor.publish('max_clnum', function() {
|
||||
// extract 'clnum' from this to get the max clnum
|
||||
return Change.find({}, {sort: {clnum: -1}, limit: 1});
|
||||
});
|
||||
|
||||
Meteor.publish('dat_clnum', function(clnum){
|
||||
// can only return as many as in the changelist
|
||||
return Change.find({clnum: clnum}, {sort: {address: 1}, limit:20});
|
||||
});
|
||||
|
||||
Meteor.publish('instruction_iaddr', function(iaddr){
|
||||
return Program.find({address: {$gt: iaddr-0x50, $lt: iaddr+0x100}}, {sort: {address:1}});
|
||||
});
|
||||
|
||||
Meteor.publish('dat_iaddr', function(iaddr){
|
||||
// fetch the static info about the range
|
||||
return Change.find({address: iaddr, type: "I"}, {sort: {clnum: 1}, limit:10})
|
||||
});
|
||||
|
||||
Meteor.publish('dat_daddr', function(daddr){
|
||||
// fetch the dynamic info about the instruction range
|
||||
//return Change.find({address : {$gt: daddr-0x100, $lt: daddr+0x300}});
|
||||
if (daddr >= 0x1000) {
|
||||
return Change.find({address:daddr}, {sort: {clnum: 1}, limit:10});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.publish('hexedit_daddr', function(daddr, clnum) {
|
||||
return Change.find({address:daddr, clnum:{$lte: clnum}}, {sort: {clnum: -1}, limit:1});
|
||||
});
|
||||
}
|
||||
|
||||
|
39
web/server/qira.js
Normal file
39
web/server/qira.js
Normal file
@ -0,0 +1,39 @@
|
||||
Change = new Meteor.Collection("change");
|
||||
Program = new Meteor.Collection("program");
|
||||
|
||||
Meteor.startup(function () {
|
||||
});
|
||||
|
||||
Meteor.publish('max_clnum', function() {
|
||||
// extract 'clnum' from this to get the max clnum
|
||||
return Change.find({}, {sort: {clnum: -1}, limit: 1});
|
||||
});
|
||||
|
||||
Meteor.publish('dat_clnum', function(clnum){
|
||||
// can only return as many as in the changelist
|
||||
return Change.find({clnum: clnum}, {sort: {address: 1}, limit:20});
|
||||
});
|
||||
|
||||
Meteor.publish('instruction_iaddr', function(iaddr){
|
||||
return Program.find({address: {$gt: iaddr-0x50, $lt: iaddr+0x100}}, {sort: {address:1}});
|
||||
});
|
||||
|
||||
Meteor.publish('dat_iaddr', function(iaddr){
|
||||
// fetch the static info about the range
|
||||
return Change.find({address: iaddr, type: "I"}, {sort: {clnum: 1}, limit:10})
|
||||
});
|
||||
|
||||
Meteor.publish('dat_daddr', function(daddr){
|
||||
// fetch the dynamic info about the instruction range
|
||||
//return Change.find({address : {$gt: daddr-0x100, $lt: daddr+0x300}});
|
||||
if (daddr >= 0x1000) {
|
||||
return Change.find({address:daddr}, {sort: {clnum: 1}, limit:10});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.publish('hexedit_daddr', function(daddr, clnum) {
|
||||
return Change.find({address:daddr, clnum:{$lte: clnum}}, {sort: {clnum: -1}, limit:1});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user