mirror of
https://github.com/geohot/qira
synced 2025-03-18 13:02:54 +03:00
support for args, removing qira_binary soon
This commit is contained in:
parent
d3a727c16a
commit
08fe8e4eab
Binary file not shown.
Binary file not shown.
@ -126,7 +126,14 @@ int websocket_thread(void *) {
|
||||
info.uid = -1;
|
||||
info.options = 0;
|
||||
|
||||
// i assume this does the bind?
|
||||
context = libwebsocket_create_context(&info);
|
||||
|
||||
if (context == NULL) {
|
||||
msg("websocket init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg("yay websockets\n");
|
||||
|
||||
while (websockets_running) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
# QIRA would be a better place if these things came from QEMU
|
||||
# ALL DEAD CODE, remove ELFFile
|
||||
|
||||
import subprocess
|
||||
from elftools.elf.elffile import ELFFile
|
||||
@ -46,6 +47,11 @@ def mem_commit_base_binary(prog, mem):
|
||||
# should we gate the segment on something?
|
||||
# i think any data actually in the ELF file is good
|
||||
print " committing %x with len %x" % (vaddr, len(data))
|
||||
|
||||
# old method was too slow
|
||||
mem.bcommit(vaddr, data)
|
||||
"""
|
||||
for i in range(0, len(data)):
|
||||
mem.commit(0, vaddr+i, ord(data[i]))
|
||||
"""
|
||||
|
||||
|
@ -19,10 +19,12 @@ class Address:
|
||||
class Memory:
|
||||
def __init__(this):
|
||||
this.daddr = {}
|
||||
this.backing = {}
|
||||
|
||||
def copy(this):
|
||||
new = Memory()
|
||||
new.daddr = this.daddr.copy()
|
||||
new.backing = this.backing # no copy required
|
||||
return new
|
||||
|
||||
def fetch(this, clnum, addr, l):
|
||||
@ -32,8 +34,17 @@ class Memory:
|
||||
rret = this.daddr[i].fetch(clnum)
|
||||
if rret != None:
|
||||
ret[i] = rret
|
||||
else:
|
||||
# slow
|
||||
for (s, e) in this.backing:
|
||||
if s <= i and i < e:
|
||||
ret[i] = ord(this.backing[(s,e)][i-s])
|
||||
return ret
|
||||
|
||||
# backing commit
|
||||
def bcommit(this, addr, dat):
|
||||
this.backing[(addr, addr+len(dat))] = dat
|
||||
|
||||
def dump(this):
|
||||
ret = {}
|
||||
for i in this.daddr:
|
||||
|
@ -208,6 +208,8 @@ def run_middleware():
|
||||
time.sleep(0.2)
|
||||
did_update = False
|
||||
for i in os.listdir("/tmp/qira_logs/"):
|
||||
if "_" in i:
|
||||
continue
|
||||
i = int(i)
|
||||
if i not in program.traces:
|
||||
qira_trace.Trace(program, i)
|
||||
@ -272,6 +274,8 @@ def start_bindserver(myss, parent_id, start_cl, loop = False):
|
||||
def get_next_run_id():
|
||||
ret = -1
|
||||
for i in os.listdir("/tmp/qira_logs/"):
|
||||
if "_" in i:
|
||||
continue
|
||||
ret = max(ret, int(i))
|
||||
return ret+1
|
||||
|
||||
|
@ -2,6 +2,7 @@ import qira_binary
|
||||
import qira_log
|
||||
import qira_memory
|
||||
import threading
|
||||
import struct
|
||||
from collections import defaultdict
|
||||
import os
|
||||
import sys
|
||||
@ -38,22 +39,28 @@ class Program:
|
||||
self.pmaps = {}
|
||||
#self.instructions = qira_binary.objdump_binary(prog)
|
||||
self.instructions = {}
|
||||
"""
|
||||
self.basemem = qira_memory.Memory()
|
||||
|
||||
print "committing base memory..."
|
||||
qira_binary.mem_commit_base_binary(prog, self.basemem)
|
||||
"""
|
||||
|
||||
# get file type
|
||||
self.fb = qira_binary.file_binary(prog)
|
||||
if 'ARM' in self.fb:
|
||||
#self.fb = qira_binary.file_binary(prog)
|
||||
self.fb = struct.unpack("H", open(prog).read(0x18)[0x12:0x14])[0]
|
||||
print "e_machine is",hex(self.fb)
|
||||
if self.fb == 0x28:
|
||||
self.tregs = ARMREGS
|
||||
self.qirabinary = "qira-arm"
|
||||
elif 'x86-64' in self.fb:
|
||||
elif self.fb == 0x3e:
|
||||
self.tregs = X64REGS
|
||||
self.qirabinary = "qira-x86_64"
|
||||
else:
|
||||
elif self.fb == 0x03:
|
||||
self.tregs = X86REGS
|
||||
self.qirabinary = "qira-i386"
|
||||
else:
|
||||
print "BINARY TYPE NOT SUPPORTED"
|
||||
|
||||
# no traces yet
|
||||
self.traces = {}
|
||||
@ -77,7 +84,7 @@ class Program:
|
||||
# hacks
|
||||
addr = int(d.split(" ")[0].strip(":"), 16)
|
||||
#print repr(d)
|
||||
if 'ARM' in self.fb:
|
||||
if self.fb == 0x28: # ARM
|
||||
inst = d[d.rfind(" ")+2:]
|
||||
else:
|
||||
inst = d[d.find(":")+3:]
|
||||
@ -106,7 +113,8 @@ class Trace:
|
||||
|
||||
def reset(self):
|
||||
self.regs = qira_memory.Memory()
|
||||
self.mem = self.program.basemem.copy()
|
||||
self.mem = qira_memory.Memory()
|
||||
#self.mem = self.program.basemem.copy()
|
||||
self.minclnum = -1
|
||||
self.maxclnum = 1
|
||||
|
||||
@ -118,6 +126,23 @@ class Trace:
|
||||
self.pydb_addr = defaultdict(list)
|
||||
self.pydb_clnum = defaultdict(list)
|
||||
|
||||
for ln in open("/tmp/qira_logs/"+str(self.forknum)+"_base").read().split("\n"):
|
||||
ln = ln.split(" ")
|
||||
if len(ln) < 3:
|
||||
continue
|
||||
(ss, se) = ln[0].split("-")
|
||||
ss = int(ss, 16)
|
||||
se = int(se, 16)
|
||||
offset = int(ln[1])
|
||||
fn = ' '.join(ln[2:])
|
||||
|
||||
f = open(fn)
|
||||
f.seek(offset)
|
||||
dat = f.read(se-ss)
|
||||
self.mem.bcommit(ss, dat)
|
||||
f.close()
|
||||
print hex(ss)+"-"+hex(se), offset, fn
|
||||
|
||||
# *** HANDLER FOR qira_log ***
|
||||
def process(self, log_entries):
|
||||
for (address, data, clnum, flags) in log_entries:
|
||||
|
@ -19,9 +19,10 @@ if [ ! -d qemu/qemu-latest ]; then
|
||||
mv linux-user/qemu.h linux-user/qemu.h.bak
|
||||
mv linux-user/main.c linux-user/main.c.bak
|
||||
cd ../../
|
||||
|
||||
sudo apt-get build-dep qemu
|
||||
fi
|
||||
|
||||
sudo apt-get build-dep qemu
|
||||
cd qemu/qemu-latest
|
||||
ln -sf ../../qemu_mods/tci.c tci.c
|
||||
ln -sf ../../qemu_mods/disas.c disas.c
|
||||
|
@ -425,6 +425,8 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/file.h>
|
||||
#include "qemu.h"
|
||||
|
||||
#define QIRA_DEBUG(...) {}
|
||||
//#define QIRA_DEBUG qemu_debug
|
||||
@ -447,10 +449,12 @@ void track_read(target_ulong base, target_ulong offset, target_ulong data, int s
|
||||
void track_write(target_ulong base, target_ulong offset, target_ulong data, int size);
|
||||
void add_pending_change(target_ulong addr, uint64_t data, uint32_t flags);
|
||||
void commit_pending_changes(void);
|
||||
void track_kernel_read(void *host_addr, target_ulong guest_addr, long len);
|
||||
void track_kernel_write(void *host_addr, target_ulong guest_addr, long len);
|
||||
void resize_change_buffer(size_t size);
|
||||
|
||||
// defined in qemu.h
|
||||
//void track_kernel_read(void *host_addr, target_ulong guest_addr, long len);
|
||||
//void track_kernel_write(void *host_addr, target_ulong guest_addr, long len);
|
||||
|
||||
#define IS_VALID 0x80000000
|
||||
#define IS_WRITE 0x40000000
|
||||
#define IS_MEM 0x20000000
|
||||
@ -501,9 +505,9 @@ void resize_change_buffer(size_t size) {
|
||||
void init_QIRA(CPUArchState *env, int id) {
|
||||
QIRA_DEBUG("init QIRA called\n");
|
||||
GLOBAL_QIRA_did_init = 1;
|
||||
GLOBAL_CPUArchState = env; // unused
|
||||
|
||||
char fn[PATH_MAX];
|
||||
GLOBAL_CPUArchState = env;
|
||||
sprintf(fn, "/tmp/qira_logs/%d", id);
|
||||
|
||||
// unlink it first
|
||||
@ -681,7 +685,8 @@ void track_kernel_write(void *host_addr, target_ulong guest_addr, long len) {
|
||||
#endif
|
||||
|
||||
// poorly written, and it fills in holes
|
||||
int get_next_id() {
|
||||
int get_next_id(void);
|
||||
int get_next_id(void) {
|
||||
char fn[PATH_MAX];
|
||||
int this_id = 0;
|
||||
struct stat junk;
|
||||
@ -694,7 +699,6 @@ int get_next_id() {
|
||||
}
|
||||
|
||||
void run_QIRA_log(CPUArchState *env, int this_id, int to_change);
|
||||
|
||||
void run_QIRA_log(CPUArchState *env, int this_id, int to_change) {
|
||||
char fn[PATH_MAX];
|
||||
sprintf(fn, "/tmp/qira_logs/%d", this_id);
|
||||
@ -754,12 +758,13 @@ void run_QIRA_log(CPUArchState *env, int this_id, int to_change) {
|
||||
|
||||
bool is_filtered_address(target_ulong pc);
|
||||
bool is_filtered_address(target_ulong pc) {
|
||||
// to remove the warning
|
||||
uint64_t bpc = (uint64_t)pc;
|
||||
// TODO(geohot): FIX THIS!, filter anything that isn't the user binary and not dynamic
|
||||
return ((pc > 0x40000000 && pc < 0xf6800000) || pc >= 0x100000000);
|
||||
return ((bpc > 0x40000000 && bpc < 0xf6800000) || bpc >= 0x100000000);
|
||||
}
|
||||
|
||||
void real_target_disas(FILE *out, CPUArchState *env, target_ulong code, target_ulong size, int flags);
|
||||
void target_disas(FILE *out, CPUArchState *env, target_ulong code, target_ulong size, int flags);
|
||||
void target_disas(FILE *out, CPUArchState *env, target_ulong code, target_ulong size, int flags) {
|
||||
if (unlikely(GLOBAL_asm_file == NULL)) {
|
||||
GLOBAL_asm_file = fopen("/tmp/qira_asm", "a");
|
||||
@ -779,18 +784,85 @@ int GLOBAL_last_was_syscall = 0;
|
||||
uint32_t GLOBAL_last_fork_change = -1;
|
||||
target_long last_pc = 0;
|
||||
|
||||
|
||||
void write_out_base(CPUArchState *env, int id);
|
||||
void write_out_base(CPUArchState *env, int id) {
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
TaskState *ts = (TaskState *)cpu->opaque;
|
||||
|
||||
char fn[PATH_MAX];
|
||||
char envfn[PATH_MAX];
|
||||
|
||||
sprintf(envfn, "/tmp/qira_logs/%d_env", id);
|
||||
FILE *envf = fopen(envfn, "wb");
|
||||
|
||||
target_ulong ss = ts->info->start_stack;
|
||||
target_ulong se = (ts->info->start_stack + (TARGET_PAGE_SIZE - 1)) & TARGET_PAGE_MASK;
|
||||
|
||||
fwrite(g2h(ss), 1, se-ss, envf);
|
||||
fclose(envf);
|
||||
|
||||
sprintf(fn, "/tmp/qira_logs/%d_base", id);
|
||||
FILE *f = fopen(fn, "w");
|
||||
|
||||
|
||||
// code copied from linux-user/syscall.c
|
||||
FILE *maps = fopen("/proc/self/maps", "r");
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
while (getline(&line, &len, maps) != -1) {
|
||||
int fields, dev_maj, dev_min, inode;
|
||||
uint64_t min, max, offset;
|
||||
char flag_r, flag_w, flag_x, flag_p;
|
||||
char path[512] = "";
|
||||
fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
|
||||
" %512s", &min, &max, &flag_r, &flag_w, &flag_x,
|
||||
&flag_p, &offset, &dev_maj, &dev_min, &inode, path);
|
||||
if ((fields < 10) || (fields > 11)) { continue; }
|
||||
|
||||
if (h2g_valid(min) && h2g_valid(max) && strlen(path) && flag_w == '-') {
|
||||
fprintf(f, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx " %"PRIx64" %s\n", h2g(min), h2g(max), offset, path);
|
||||
//printf("%p - %p -- %s", h2g(min), h2g(max), line);
|
||||
//fflush(stdout);
|
||||
}
|
||||
|
||||
/*printf("%s", line);
|
||||
fflush(stdout);*/
|
||||
}
|
||||
|
||||
// env
|
||||
fprintf(f, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx " %"PRIx64"\n", ss, se, (uint64_t)0, envfn);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
/* Interpret pseudo code in tb. */
|
||||
uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
|
||||
{
|
||||
#ifdef QIRA_TRACKING
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
TranslationBlock *tb = cpu->current_tb;
|
||||
//TaskState *ts = (TaskState *)cpu->opaque;
|
||||
|
||||
if (unlikely(GLOBAL_QIRA_did_init == 0)) {
|
||||
// do initial core dump
|
||||
/*struct rlimit core_limit, core_limit_old;
|
||||
getrlimit(RLIMIT_CORE, &core_limit_old);
|
||||
core_limit.rlim_cur = RLIM_INFINITY;
|
||||
core_limit.rlim_max = RLIM_INFINITY;
|
||||
setrlimit(RLIMIT_CORE, &core_limit);
|
||||
(*ts->bprm->core_dump)(0, env);
|
||||
setrlimit(RLIMIT_CORE, &core_limit_old);*/
|
||||
/*page_dump(stderr);
|
||||
fflush(stderr);*/
|
||||
|
||||
write_out_base(env, GLOBAL_id);
|
||||
|
||||
// these three arguments (parent_id, start_clnum, id) must be passed into QIRA
|
||||
if (GLOBAL_parent_id != -1) {
|
||||
run_QIRA_log(env, GLOBAL_parent_id, GLOBAL_start_clnum);
|
||||
}
|
||||
|
||||
init_QIRA(env, GLOBAL_id);
|
||||
return 0;
|
||||
}
|
||||
@ -894,14 +966,14 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
|
||||
#ifdef R_EAX
|
||||
struct change *a = NULL;
|
||||
|
||||
if (t0 == helper_load_seg) {
|
||||
if ((void*)t0 == helper_load_seg) {
|
||||
if (GLOBAL_logstate->is_filtered == 1) {
|
||||
commit_pending_changes();
|
||||
}
|
||||
a = track_syscall_begin(env, FAKE_SYSCALL_LOADSEG);
|
||||
a->data = a1<<32 | a2;
|
||||
//printf("LOAD SEG %x %x %x %x\n", a0, a1, a2, a3);
|
||||
} else if (t0 == helper_raise_interrupt) {
|
||||
} else if ((void*)t0 == helper_raise_interrupt) {
|
||||
if (GLOBAL_logstate->is_filtered == 1) {
|
||||
commit_pending_changes();
|
||||
// syscalls always get a change?
|
||||
|
BIN
tests/argtest
Executable file
BIN
tests/argtest
Executable file
Binary file not shown.
9
tests/argtest.c
Normal file
9
tests/argtest.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
for (i = 0; i < argc; i++) {
|
||||
printf("%d: %s\n", i, argv[i]);
|
||||
}
|
||||
}
|
||||
|
BIN
tests/argtest_static
Executable file
BIN
tests/argtest_static
Executable file
Binary file not shown.
11
tests/procselfmaps.c
Normal file
11
tests/procselfmaps.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include <stdio.h>
|
||||
char buf[0x1000];
|
||||
|
||||
int main() {
|
||||
FILE *f = fopen("/proc/self/maps", "rb");
|
||||
buf[fread(buf, 1, 0x1000, f)] = '\0';
|
||||
fclose(f);
|
||||
printf("%s\n", buf);
|
||||
return 0;
|
||||
}
|
||||
|
@ -58,15 +58,59 @@ function zoom_out_max(dontforce) {
|
||||
else Session.set("cview", [0, max]);
|
||||
}
|
||||
|
||||
|
||||
// uniform events everywhere
|
||||
var baseevents = {
|
||||
'mousedown .datamemory': function(e) { return false; },
|
||||
'mousedown .datainstruction': function(e) { return false; },
|
||||
// ugh highlights
|
||||
'click .datamemory': function(e) {
|
||||
var daddr = parseInt(e.target.innerHTML, 16);
|
||||
update_dview(daddr);
|
||||
},
|
||||
'click .datainstruction': function(e) {
|
||||
var daddr = parseInt(e.target.innerHTML, 16);
|
||||
update_dview(daddr);
|
||||
},
|
||||
'contextmenu .datainstruction': function(e) {
|
||||
// right click to follow in instruction dump
|
||||
// add menu maybe?
|
||||
var iaddr = parseInt(e.target.innerHTML, 16);
|
||||
Session.set("dirtyiaddr", true);
|
||||
Session.set('iaddr', iaddr);
|
||||
return false;
|
||||
},
|
||||
'click .data': function(e) {
|
||||
var daddr = parseInt(e.target.getAttribute('daddr'));
|
||||
Session.set('daddr', daddr);
|
||||
},
|
||||
};
|
||||
|
||||
// uniform events everywhere
|
||||
// ugh duplicated code, i'm bad at javascript
|
||||
var basedblevents = {
|
||||
'mousedown .datamemory': function(e) { return false; },
|
||||
'mousedown .datainstruction': function(e) { return false; },
|
||||
// ugh highlights
|
||||
'dblclick .datamemory': function(e) {
|
||||
var daddr = parseInt(e.target.innerHTML, 16);
|
||||
update_dview(daddr);
|
||||
},
|
||||
'dblclick .datainstruction': function(e) {
|
||||
var daddr = parseInt(e.target.innerHTML, 16);
|
||||
update_dview(daddr);
|
||||
},
|
||||
'contextmenu .datainstruction': function(e) {
|
||||
// right click to follow in instruction dump
|
||||
// add menu maybe?
|
||||
var iaddr = parseInt(e.target.innerHTML, 16);
|
||||
Session.set("dirtyiaddr", true);
|
||||
Session.set('iaddr', iaddr);
|
||||
return false;
|
||||
},
|
||||
'click .data': function(e) {
|
||||
var daddr = parseInt(e.target.getAttribute('daddr'));
|
||||
Session.set('daddr', daddr);
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -33,8 +33,12 @@ Template.idump.events({
|
||||
'click .change': function() {
|
||||
Session.set('clnum', this.clnum);
|
||||
},
|
||||
'mousedown .datainstruction': function(e) { return false; },
|
||||
'click .datainstruction': function() {
|
||||
Session.set('iaddr', this.address);
|
||||
},
|
||||
'dblclick .datainstruction': function() {
|
||||
update_dview(this.address);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -84,30 +84,6 @@ stream.on('memory', function(msg) {
|
||||
});
|
||||
|
||||
|
||||
Template.memviewer.events({
|
||||
'dblclick .datamemory': function(e) {
|
||||
var daddr = parseInt(e.target.innerHTML, 16);
|
||||
update_dview(daddr);
|
||||
},
|
||||
'dblclick .datainstruction': function(e) {
|
||||
var daddr = parseInt(e.target.innerHTML, 16);
|
||||
update_dview(daddr);
|
||||
},
|
||||
'contextmenu .datainstruction': function(e) {
|
||||
// right click to follow in instruction dump
|
||||
// add menu maybe?
|
||||
var iaddr = parseInt(e.target.innerHTML, 16);
|
||||
Session.set("dirtyiaddr", true);
|
||||
Session.set('iaddr', iaddr);
|
||||
return false;
|
||||
},
|
||||
'click .data': function(e) {
|
||||
var daddr = parseInt(e.target.getAttribute('daddr'));
|
||||
Session.set('daddr', daddr);
|
||||
},
|
||||
});
|
||||
|
||||
Template.regviewer.events(baseevents);
|
||||
|
||||
Template.regviewer.hexvalue = function() {
|
||||
return this.value;
|
||||
@ -138,10 +114,13 @@ stream.on('registers', function(msg) {
|
||||
UI.insert(UI.renderWithData(Template.regviewer, {regs: msg}), $('#regviewer')[0]);
|
||||
});
|
||||
|
||||
// *** datachanges ***
|
||||
|
||||
// events, add the editing here
|
||||
Template.memviewer.events(basedblevents);
|
||||
Template.regviewer.events(baseevents);
|
||||
Template.datachanges.events(baseevents);
|
||||
|
||||
// *** datachanges ***
|
||||
|
||||
Template.datachanges.hexaddress = function() {
|
||||
return this.address;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user