Created
October 20, 2014 13:22
-
-
Save endeav0r/6213b4069ccce06d309c to your computer and use it in GitHub Desktop.
luadebug and queso
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
require ('ldebug') | |
require ('lqueso') | |
function map (f, t) | |
local result = {} | |
for k,v in pairs(t) do | |
result[k] = f(v) | |
end | |
return result | |
end | |
function setRegisters (debugger, machine) | |
local registers = debugger:registers() | |
for k,v in pairs(registers) do | |
machine:s_variable(k, luint32(v), 32) | |
print(k .. "=" .. string.format("%08x", v)) | |
end | |
end | |
function checkRegisters (debugger, machine, registers) | |
local debuggerRegisters = debugger:registers() | |
for k,name in pairs(registers) do | |
local variable = machine:g_variable(name) | |
if luint32(debuggerRegisters[name]) ~= variable:value() then | |
for k,rname in pairs(registers) do | |
print(rname .. ' ' .. | |
string.format("%08x", debuggerRegisters[rname]) .. " " .. | |
machine:g_variable(rname):value():string()) | |
end | |
error("checkRegisters failed " .. name .. " " .. | |
string.format("%08x", debuggerRegisters[name]) .. " " .. | |
variable:value():string()) | |
end | |
end | |
end | |
function printQueso (instruction, depth) | |
padding = '' | |
for d=0,depth do padding = padding .. ' ' end | |
print(padding .. instruction:queso()) | |
if instruction:depth_instructions() then | |
for k,instruction in pairs(instruction:depth_instructions()) do | |
printQueso(instruction, depth + 2) | |
end | |
end | |
end | |
function readMaps (debugger, machine) | |
local filename = "/proc/" .. tostring(debugger:pid()) .. "/maps" | |
local fh = io.open(filename, "r") | |
local raw = fh:read("*a") | |
fh:close() | |
local totalSize = 0 | |
for startAddr, endAddr, permissions in string.gmatch(raw, '(%x+)-(%x+) (r...)') do | |
startAddr = tonumber(startAddr, 16) | |
endAddr = tonumber(endAddr, 16) | |
local size = endAddr - startAddr | |
local memory = debugger:readmem(startAddr, size) | |
print(string.format("%x %x %x", startAddr, endAddr, size) | |
.. "\t read " .. #memory .. " bytes of memory") | |
machine:s_memory(startAddr, table.concat(map(string.char, memory))) | |
totalSize = totalSize + size | |
end | |
print("totalSize: " .. totalSize) | |
end | |
function stepPrint (d) | |
d:step() | |
pcString = string.format('%x', d:getpc()) | |
bytes = d:readmem(d:getpc(), 16) | |
function formatByte (b) | |
return string.format('%02x', b) | |
end | |
bytesString = table.concat(map(formatByte, bytes)) | |
ins = lqueso:x86translate(table.concat(map(string.char, bytes))) | |
print(string.format(pcString .. '\t' .. bytesString)) | |
printQueso(ins, 2) | |
end | |
function stepBoth (debugger, machine) | |
-- get bytes from the machine memory | |
local instructionBytes = machine:g_memory(machine:g_variable('eip'):value(), 16) | |
-- get bytes from the debugger memory | |
local debuggerBytes = debugger:readmem(debugger:registers()['eip'], 16) | |
-- print both | |
function formatByte (b) return string.format("%02x", b) end | |
local instructionBytesTable = {} | |
for i=1,#instructionBytes do | |
local b = string.byte(instructionBytes:sub(i,i)) | |
table.insert(instructionBytesTable, b) | |
end | |
print('machine bytes: ' .. table.concat(map(formatByte, instructionBytesTable))) | |
print('debugger bytes: ' .. table.concat(map(formatByte, debuggerBytes))) | |
debugger:step() | |
-- get IL instruction | |
local instruction = lqueso.x86translate(instructionBytes) | |
-- print IL instruction | |
printQueso(instruction, 0) | |
-- execute IL instruction | |
machine:concreteExecution(instruction) | |
end | |
local debugger = ldebug.execv('/bin/ls', {'/'}) | |
local machine = lqueso.machine() | |
debugger:breakpoint(0x804c1b4) | |
debugger:wait() | |
debugger:step() | |
readMaps(debugger, machine) | |
setRegisters(debugger, machine) | |
checkRegisters(debugger, machine, {'eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip'}) | |
print ('begin stepping debugger and machine') | |
for i=1,64 do | |
print('------------------------------------') | |
print('step: ' .. i) | |
print('debugger eip: ' .. luint32(debugger:registers()['eip']):string()) | |
print('machine eip: ' .. machine:g_variable('eip'):value():string()) | |
stepBoth(debugger, machine) | |
checkRegisters(debugger, machine, {'eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip'}) | |
end | |
print('done') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment