4
-- 2008 pancake <youterm.com>
24
-- ================= --
26
-- Namespace aliases --
28
-- ================= --
42
-- ================ --
44
-- Helper functions --
46
-- ================ --
50
print "Use help(Radare), help(Radare.Debugger) or help(Radare.Print)"
51
print "These namespaces has been aliased as 'r', 'd' and 'p'."
53
for key,val in pairs(table) do print(" "..key) end
62
print "List the contents of a table"
64
--for key,val in pairs(table) do print(" "..key) end
65
for k,v in pairs(table) do
67
print(" "..k) -- XXX crash
69
print(" "..k..": "..v)
78
-- join strings from a table
79
function join(delimiter, list)
80
local len = getn(list)
84
local string = list[1]
86
string = string .. delimiter .. list[i]
91
-- split a string by a separator
92
function split(text, sep)
98
local b,e = text:find(sep, pos)
99
if not b then table.insert(lines, text:sub(pos)) break end
100
table.insert(lines, text:sub(pos,b-1))
107
if text == nil then return "" end
108
return string.gsub(text, "\n$", "")
112
if text == nil then return "" end
113
text = string.gsub(text, "\ *$", "")
114
return string.gsub(text, "^\ *", "")
117
function hexpairs(buf)
118
for byte=1, #buf, 16 do
119
local chunk = buf:sub(byte, byte+15)
120
io.write(string.format('%08X ',byte-1))
121
chunk:gsub('.', function (c) io.write(string.format('%02X ',string.byte(c))) end)
122
io.write(string.rep(' ',3*(16-#chunk)))
123
io.write(' ',chunk:gsub('%c','.'),"\n")
127
function hexdump(buf)
128
for i=1,math.ceil(#buf/16) * 16 do
129
if (i-1) % 16 == 0 then io.write(string.format('%08X ', i-1)) end
130
io.write( i > #buf and ' ' or string.format('%02X ', buf:byte(i)) )
131
if i % 8 == 0 then io.write(' ') end
132
if i % 16 == 0 then io.write( buf:sub(i-16+1, i):gsub('%c','.'), '\n' ) end
144
-- ==================== --
146
-- Radare API functions --
148
-- ==================== --
150
function Radare.get(value)
151
-- | cut -d ' ' -f 1");
154
cmd_str("? "..value),'(0x[^ ])',
155
function(x)return x end),';')
156
return tonumber(foo[1])
159
Radare.bytes_help = 'Radare.bytes(addr)\tReturn hexpair string with block_size bytes at [addr]'
160
function Radare.bytes(addr)
161
local res = split(Radare.cmd("pX @"..addr), " ")
166
Radare.cmd_help = 'Radare.cmd(command)\tExecutes a radare command and returns its output'
167
function Radare.cmd(cmd)
168
return chomp(cmd_str(cmd))
171
Radare.system_help = 'Radare.system(command)\tExecute an IO system command'
172
function Radare.system(command)
174
-- todo handle errors here
178
Radare.iosystem_help = 'Radare.iosystem(command)\tExecute an IO system command'
179
function Radare.iosystem(command)
181
-- todo handle errors here
185
function Radare.open(filename)
186
r.cmd("o "..filename)
187
-- todo handle errors here
191
function Radare.attach(pid)
192
return r.cmd("o pid://"..pid)
195
function Radare.debug(filename)
196
return r.cmd("o dbg://"..filename)
199
function Radare.seek(offset)
204
function Radare.undo_seek()
206
-- todo handle errors here
210
function Radare.redo_seek()
212
-- todo handle errors here
216
function Radare.resize(newsize)
218
-- todo handle errors here
222
function Radare.fortune()
223
return r.cmd("fortune")
226
function Radare.interpret(file)
227
-- control block size
232
function Radare.copy(size,address)
233
-- control block size
234
if address == nil then
237
r.cmd("y "..size.." @ "..address)
242
function Radare.paste(address)
243
-- control block size
244
if address == nil then
247
r.cmd("yy @ "..address)
253
function Radare.endian(big)
254
r.cmd("eval cfg.bigendian = "..big)
258
function Radare.flag(name, address) -- rename to r.set() ?
259
if address == nil then
262
r.cmd("f "..name.." @ "..address)
267
function Radare.flag_get(name) -- rename to r.get() ?
268
local foo = str.split(r.cmd("? "..name), " ")
272
function Radare.flag_remove(name) -- rename to r.remove() ?
277
function Radare.flag_rename(oldname, newname)
278
r.cmd("fr "..oldname.." "..newname)
282
function Radare.flag_list(filter)
283
local list = split(r.cmd("f"))
286
while list[i] ~= nil do
287
local foo = split(list[i], " ")
294
function Radare.eval(key, value)
296
return r.cmd("eval "..key)
298
return r.cmd("eval "..key.." = "..value)
301
function Radare.cmp(value, address)
302
if address == nil then
305
r.cmd("c "..value.." @ "..address)
307
-- parse output and get ret value
311
function Radare.cmp_file(file, address)
312
if address == nil then
315
r.cmd("cf "..file.." @ "..address)
317
-- parse output and get ret value
321
function Radare.quit()
326
function Radare.exit()
332
function Radare.Analyze.opcode(addr)
333
if addr == nil then addr = "" else addr= "@ "..addr end
334
local res = split(Radare.cmd("ao "..addr),"\n")
337
local line = split(res[i], "=")
338
ret[chop(line[1])] = chop(line[2])
343
function Radare.Analyze.block(addr)
344
if addr == nil then addr = "" else addr= "@ "..addr end
345
local res = split(Radare.cmd("ab "..addr),"\n")
348
local line = split(res[i], "=")
349
ret[chop(line[1])] = chop(line[2])
353
-- Radare.Debugger API
355
function Radare.Debugger.step(times)
356
r.cmd("!step "..times);
357
return Radare.Debugger
360
function Radare.Debugger.attach(pid)
361
r.cmd("!attach "..pid);
362
return Radare.Debugger
365
function Radare.Debugger.detach(pid)
367
return Radare.Debugger
370
function Radare.Debugger.jmp(address)
371
r.cmd("!jmp "..address)
372
return Radare.Debugger
375
function Radare.Debugger.set(register, value)
376
r.cmd("!set "..register.." "..value)
377
return Radare.Debugger
380
function Radare.Debugger.call(address)
381
r.cmd("!call "..address)
382
return Radare.Debugger
385
function Radare.Debugger.dump(name)
386
r.cmd("!dump "..name)
387
return Radare.Debugger
390
function Radare.Debugger.restore(name)
391
r.cmd("!restore "..name)
392
return Radare.Debugger
395
function Radare.Debugger.bp(address)
396
r.cmd("!bp "..address)
397
return Radare.Debugger
402
function Radare.Print.hex(size, address)
403
if size == nil then size = "" end
404
if address == nil then
405
return r.cmd(":pX "..size)
407
return r.cmd(":pX "..size.." @ "..address)
411
function Radare.Print.dis(nops, address)
412
if nops == nil then nops = "" end
413
if address == nil then
414
return r.cmd("pd "..nops)
416
return r.cmd("pd "..nops.." @ "..address)
420
function Radare.Print.disasm(size, address)
421
if size == nil then size = "" end
422
if address == nil then
423
return r.cmd("pD "..size)
425
return r.cmd("pD "..size.." @ "..address)
429
function Radare.Print.bin(size, address) -- size has no sense here
430
if size == nil then size = "" end
431
if address == nil then
432
return r.cmd(":pb "..size)
434
return r.cmd(":pb "..size.." @ "..address)
438
function Radare.Print.string(address) -- size has no sense here
439
if address == nil then
442
return r.cmd("pz @ "..address)
446
function Radare.Print.oct(size,address) -- size has no sense here
447
if size == nil then size = "" end
448
if address == nil then
449
return r.cmd(":po "..size)
451
return r.cmd(":po "..size.."@ "..address)
456
function Radare.Search.parse(string)
457
local res = split(string,"\n")
460
local line = split(res[i], " ")
466
function Radare.Search.string(string)
467
return Radare.Search.parse(Radare.cmd("/ "..string))
470
function Radare.Search.hex(string)
471
return Radare.Search.parse(Radare.cmd("/x "..string))
474
function Radare.Search.replace(hex_search, hex_write, delta)
476
Radare.Config.set("cmd.hit","wx "..hex_write)
478
Radare.Config.set("cmd.hit","wx "..hex_write.." @ +"..delta)
480
return Radare.Search.parse(Radare.cmd("/x "..hex_search))
485
function Radare.Write.hex(string, address)
486
if address == nil then
487
return r.cmd("wx "..string)
489
return r.cmd("wx "..string.." @ "..address)
493
function Radare.Write.string(string, address)
494
if address == nil then
495
return r.cmd("w ", string)
497
return r.cmd("w "..string.." @ "..address)
501
function Radare.Write.wide_string(string, address)
502
if address == nil then
503
return r.cmd("ws "..string)
505
return r.cmd("ws "..string.." @ "..address)
509
function Radare.asm(string)
510
return r.cmd("!rasm '".. string.."'")
513
function Radare.Write.asm(string, address)
514
if address == nil then
515
return r.cmd("wa ".. string)
517
return r.cmd("wa "..string.." @ "..address)
521
function Radare.Write.rscasm(string, address)
522
if address == nil then
523
return r.cmd("wA "..string)
525
return r.cmd("wA "..string.." @ "..address)
529
function Radare.Write.from_file(filename, address)
530
if address == nil then
531
return r.cmd("wf "..filename)
533
return r.cmd("wf "..filename.." @ "..address)
540
function Radare.Config.verbose(level)
541
Radare.Config.set("asm.syntax","intel")
542
Radare.Config.set("asm.lines","false")
543
Radare.Config.set("asm.offset","false")
544
Radare.Config.set("asm.bytes","false")
545
Radare.Config.set("asm.flags","false")
546
Radare.Config.set("asm.split","false")
547
Radare.Config.set("scr.color","false")
548
Radare.Config.set("asm.comments","false")
550
Radare.Config.set("asm.size", "true")
553
Radare.Config.set("asm.offset", "true")
556
Radare.Config.set("asm.lines", "true")
557
Radare.Config.set("asm.bytes", "true")
558
Radare.Config.set("asm.split", "true")
559
Radare.Config.set("asm.flags", "true")
560
Radare.Config.set("scr.color", "true")
561
Radare.Config.set("asm.comments","true")
565
-- TODO: store/restore eval config
566
local Radare_Config_storage = {}
567
function Radare.Config.store()
568
local lines = split(r.cmd("e"),"\n")
570
local a = split(lines[i],"=")
572
if a[2] == nil then a[2]="" end
573
if (string.match(a[1], "file") ~= nil) then
576
-- TODO. should store everything! (but no reopen :O)
577
if (string.match(a[1], "asm") ~= nil)
578
or (string.match(a[1], "scr") ~= nil) then
579
Radare_Config_storage[a[1]] = a[2]
580
Radare_Config_storage[a[1]] = a[2]
587
function Radare.Config.restore()
588
for a,b in pairs(Radare_Config_storage) do
589
Radare.Config.set(a,b)
590
-- print (a.." = "..b)
594
function Radare.Config.set(key, val)
595
r.cmd("eval "..key.."="..val)
599
function Radare.Config.color(value)
600
r.cmd("eval scr.color ="..value)
604
function Radare.Config.get(key)
605
return r.cmd("eval "..key)
608
function Radare.Config.limit(sizs)
609
return r.cmd("eval cfg.limit = "..size)
614
function Radare.Hash.md5(size, address)
615
if size == nil then size = "" end
616
if address == nil then return r.cmd("#md5 "..size) end
617
return r.cmd("#md5 "..size.."@"..address)
620
function Radare.Hash.crc32(size, address)
621
if size == nil then size = "" end
622
if address == nil then return r.cmd("#crc32 "..size) end
623
return r.cmd("#crc32 "..size.."@"..address)
626
function Radare.Hash.md4(size, address)
627
if size == nil then size = "" end
628
if address == nil then return r.cmd("#md4 "..size) end
629
return r.cmd("#md4 "..size.."@"..address)
632
function Radare.Hash.sha1(size, address)
633
if size == nil then size = "" end
634
if address == nil then return r.cmd("#sha1 "..size) end
635
return r.cmd("#sha1 "..size.."@"..address)
638
function Radare.Hash.sha256(size, address)
639
if size == nil then size = "" end
640
if address == nil then return r.cmd("#sha256 "..size) end
641
return r.cmd("#sha256 "..size.."@"..address)
644
function Radare.Hash.sha384(size, address)
645
if size == nil then size = "" end
646
if address == nil then return r.cmd("#sha384 "..size) end
647
return r.cmd("#sha384 "..size.."@"..address)
650
function Radare.Hash.sha512(size, address)
651
if size == nil then size = "" end
652
if address == nil then return r.cmd("#sha512 "..size) end
653
return r.cmd("#sha512 "..size.."@"..address)
656
function Radare.Hash.hash(algo, size, address)
657
if size == nil then size = "" end
658
eval("#"..algo.." "..size)
661
function Radare.Hash.sha512(size, address)
662
return hash("sha512", size, address)
663
--if size == nil then size = "" end
664
--if address == nil then return r.cmd("#sha512 "..size) end
665
--return r.cmd("#sha512 "..size.."@"..address)
669
function Radare.Code.comment(offset, message)
670
-- TODO: if only offset passed, return comment string
671
r.cmd("CC "..message.." @ "..offset)
675
function Radare.Code.code(offset, len)
676
r.cmd("Cc "..len.." @ "..offset)
680
function Radare.Code.data(offset, len)
681
r.cmd("Cd "..len.." @ "..offset)
685
function Radare.Code.string(offset, len)
686
r.cmd("Cs "..len.." @ "..offset)
690
-- change a signal handler of the child process
691
function Radare.Debugger.signal(signum, sighandler)
692
r.cmd("!signal "..signum.." "..sighandler)
693
return Radare.Debugger
696
function Radare.Debugger.bp_remove(address)
697
r.cmd("!bp -"..address);
698
return Radare.Debugger
701
function Radare.Debugger.continue(address)
702
if address == nil then
705
r.cmd("!cont "..address);
707
return Radare.Debugger
710
function Radare.Debugger.step(num)
712
return Radare.Debugger
715
function Radare.Debugger.step(num)
717
return Radare.Debugger
720
function Radare.Debugger.step_over()
722
return Radare.Debugger
725
function Radare.Debugger.step_until_user_code()
727
return Radare.Debugger
730
function Radare.Debugger.add_bp(addr)
732
return Radare.Debugger
735
function Radare.Debugger.remove_bp(addr)
737
return Radare.Debugger
740
function Radare.Debugger.alloc(size)
741
return cmd_str("!alloc "..size)
744
function Radare.Debugger.free(addr) -- rename to dealloc?
745
return cmd_str("!free "..addr)
748
function Radare.Debugger.dump(dirname)
749
r.cmd("!dump "..dirname)
750
return Radare.Debugger
753
function Radare.Debugger.restore(dirname)
754
r.cmd("!restore "..dirname)
755
return Radare.Debugger
758
function Radare.Debugger.jump(addr)
760
return Radare.Debugger
763
function Radare.Debugger.backtrace()
764
local res = split(Radare.cmd("!bt"),"\n")
767
local line = split(res[i], " ")
773
print "[radare.lua] Type 'help()' or 'quit' to return to radare shell."