-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathludis86.lua
executable file
·198 lines (187 loc) · 6.62 KB
/
ludis86.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
---[Udis86](http://udis86.sourceforge.net) C disassembler bindings for Lua.
--"Udis86 is an easy-to-use, minimalistic disassembler library (libudis86) for the x86 class of instruction set architectures."
--This bindings were former part of Lua code injection framework:
--[mmBBQ](http://duschkumpane.org/index.php/mmbbq)
--
--## Overview
-- The project contains a standard Makefile that is used to build
-- shared Lua libraries for Windows and Linux. The contained C code part
-- of the bindings can as well be integrated or hard-linked into a Lua project
--### Source
--The GitHub project site is: [here](https://github.com/willsteel/ludis86)
-- git clone https://github.com/willsteel/ludis86.git
--
--### Makefile targets
-- make all
-- # Build lib and doc
--
-- make doc
-- # Just build the docs
--
-- make test
-- # run 'test.lua'
--
--### Usage
-- -- initialize udis to a specific address
-- local ludis86 = require("ludis86")
-- ud = ludis86.init_addr_intel32(0x401000) -- your address here :D
-- -- disassemble and print instructions
-- while ud:dis() > 0 do
-- print(string.format("+%04X %016s %016s", ud:off(), ud:hex(), ud:asm()))
-- end
--
--### Notice
-- 2013 (c) by Michael Schmoock <[email protected]>
-- License: Free-BSD
--
--### C-Function API mapping
-- // Following code is taken from the file: ludis86.c
-- // API mapping
-- { "ud_init", ud_init_C },
-- { "ud_set_mode", ud_set_mode_C },
-- { "ud_set_pc", ud_set_pc_C },
-- { "ud_set_input_hook", ud_set_input_hook_C },
-- { "ud_set_input_buffer", ud_set_input_buffer_C },
-- { "ud_set_input_file", ud_set_input_file_C },
-- { "ud_set_vendor", ud_set_vendor_C },
-- { "ud_set_syntax", ud_set_syntax_C },
-- { "ud_input_skip", ud_input_skip_C },
-- { "ud_input_end", ud_input_end_C },
-- { "ud_decode", ud_decode_C },
-- { "ud_disassemble", ud_disassemble_C },
-- { "ud_translate_intel", ud_translate_intel_C },
-- { "ud_translate_att", ud_translate_att_C },
-- { "ud_insn_asm", ud_insn_asm_C },
-- { "ud_insn_ptr", ud_insn_ptr_C },
-- { "ud_insn_off", ud_insn_off_C },
-- { "ud_insn_hex", ud_insn_hex_C },
-- { "ud_insn_len", ud_insn_len_C },
-- { "ud_lookup_mnemonic", ud_lookup_mnemonic_C },
--
-- // shorthandles
-- { "new", ud_init },
-- { "dis", ud_disassemble_C },
-- { "asm", ud_insn_asm_C },
-- { "off", ud_insn_off_C },
-- { "hex", ud_insn_hex_C },
-- { "skip", ud_input_skip_C },
-- { "len", ud_insn_len_C },
-- { "ptr", ud_insn_ptr_C },
-- { "pc", ud_set_pc_C },
--
--
-- @module ludis86
local ludis86 = require("ludis86_C");
--local ludis86 = package.loadlib("ludis86", "luaopen_ludis86_C")();
--- initialiszes the disassembler to a file using intel syntax and 32bit.
-- @param filename the path to an assembly file
-- @param offset OPTIONAL the offset where to start disassembly
-- @param len OPTIONAL the number if bytes to disassemlbe
-- @param pc OPTIONAL the programm counter to use
ludis86.init_file_intel32 = function(filename, offset, len, pc)
local file = io.open(filename, "r")
if not file then error("file not found:"..filename) end
local buf = file:read("*a")
file:close();
if offset then buf=buf:sub(offset) end
return ludis86.init_buf_intel32(buf, len, pc);
end
--- initialiszes the disassembler to a file using intel syntax and 64bit.
-- @param filename the path to an assembly file
-- @param offset OPTIONAL the offset where to start disassembly
-- @param len OPTIONAL the number if bytes to disassemlbe
-- @param pc OPTIONAL the programm counter to use
ludis86.init_file_intel64 = function(filename, offset, len, pc)
local file = io.open(filename, "r")
if not file then error("file not found:"..filename) end
local buf = file:read("*a")
file:close();
if offset then buf=buf:sub(offset) end
return ludis86.init_buf_intel64(buf, len, pc);
end
--- disassemble and printf anything
-- @param ud initialized udis86 object
ludis86.print = function(ud)
while ud:dis() > 0 do
print(string.format("+%04X %-16s %-032s", ud:off(), ud:hex(), ud:asm()))
end
end
--- sets syntax to intel 32bit
-- @param ud initialized udis86 object
ludis86.intel32 = function(ud)
ud:ud_set_mode(32);
ud:ud_set_syntax(ud.UD_SYN_INTEL);
end
--- sets syntax to intel 64bit
-- @param ud initialized udis86 object
ludis86.intel64 = function(ud)
ud:ud_set_mode(64);
ud:ud_set_syntax(ud.UD_SYN_INTEL);
end
--- initializes the disassembler to a string buffer using intel syntax and 32bit.
-- @param buf the string buffer
-- @param len OPTIONAL the length to use. max and default: #buf
-- @param pc OPTIONAL the programm counter to use
ludis86.init_buf_intel32 = function(buf, len, pc)
if not len then len = #buf end
local ud = ludis86.ud_init()
ludis86.intel32(ud)
ud:ud_set_input_buffer(buf, len)
ud:ud_set_pc(pc or 0)
return ud
end
--- initializes the disassembler to a string buffer using intel syntax and 64bit.
-- @param buf the string buffer
-- @param len OPTIONAL the length to use. max and default: #buf
-- @param pc OPTIONAL the programm counter to use
ludis86.init_buf_intel64 = function(buf, len, pc)
if not len then len = #buf end
local ud = ludis86.ud_init()
ludis86.intel64(ud)
ud:ud_set_input_buffer(buf, len)
ud:ud_set_pc(pc or 0)
return ud
end
--- initializes the disassembler to an address using intel syntax and 32bit.
-- @param addr the address to disassemble. can be userdata cdata or number
-- @param len OPTIONAL the maximum number of bytes to read
ludis86.init_addr_intel32 = function(addr, len)
if not len then len = 2^31 end
local ud = ludis86.ud_init()
ludis86.intel32(ud)
ud:ud_set_input_buffer(addr, len)
ud:ud_set_pc(addr)
return ud
end
--- initializes the disassembler to an address using intel syntax and 64bit.
-- @param addr the address to disassemble. can be userdata cdata or number
-- @param len OPTIONAL the maximum number of bytes to read
ludis86.init_addr_intel64 = function(addr, len)
if not len then len = 2^31 end
local ud = ludis86.ud_init()
ludis86.intel64(ud)
ud:ud_set_input_buffer(addr, len)
ud:ud_set_pc(addr)
return ud;
end
--
-- tests
--
ludis86.testbuf = string.char( -- some binary data
0x90, -- nop
0x55, -- push ebp
0x41, -- inc ecx
0x5d, -- pop ebp
0xc3 -- ret
)
ludis86.test = function(suppressMsg)
local ud = ludis86.init_buf_intel32(ludis86.testbuf)
ud:dis(); assert(ud:asm():match("nop"))
ud:dis(); assert(ud:asm() == "push ebp")
ud:dis(); assert(ud:asm() == "inc ecx")
ud:dis(); assert(ud:asm() == "pop ebp")
ud:dis(); assert(ud:asm():match("ret"))
if not suppressMsg then print("tests run successfully") end
end
ludis86.test(true)
return ludis86