From e7b9c6e2552a861a949585c38e2a881f5cdcb0a7 Mon Sep 17 00:00:00 2001 From: bloodstalker Date: Fri, 29 Nov 2019 16:05:42 +0330 Subject: added libwasm32 as a lua module to bruiser now. you can get a quick wasm dump like that. some updates here and there to the READMEs. there is also a gitter group now. come say hi.and join please. --- bruiser/README.md | 16 ++- bruiser/bruiser.cpp | 30 +++++ bruiser/lua-scripts/libwasm32.lua | 265 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 308 insertions(+), 3 deletions(-) create mode 100644 bruiser/lua-scripts/libwasm32.lua (limited to 'bruiser') diff --git a/bruiser/README.md b/bruiser/README.md index 6d1b8d9..f7bb993 100644 --- a/bruiser/README.md +++ b/bruiser/README.md @@ -7,6 +7,7 @@ Object file libraries: Object file manipulation libraries are implemented in C a Xobj: Pull in funtions from ELF objects, call them and get the result back(basically ffi).
ASMrewriter: Currently returns a table containing all the jumps in the x86-64 machine code.
Ramdump: Get the memory of a running process.
+LibWASM: Get a wasm object(32) in lua.
For working demos you can skip to the end of the README.
@@ -17,7 +18,7 @@ For working demos you can skip to the end of the README.
* libcapstone
* libkeystone
* python 3.5(or higher) development packages
-* LLVM/Clang(5.0,6.0 or 8.0. 7.0 not supported)
+* LLVM/Clang(5.0,6.0 or 8.0,9.0 and 10.0. 7.0 not supported)
Other dependencies(lua, [faultreiber](https://github.com/bloodstalker/faultreiber), [luatablegen](https://github.com/bloodstalker/luatablegen), [linenoise](https://github.com/antirez/linenoise)) are self-contained.
## Make @@ -68,6 +69,14 @@ If you happen to write a Lua script for bruiser that you think other people will Run `run.sh` inside bruiser's directory. This will run all the demos buirser currently has, which at the time of writng include the xobj demo, the jump table demo, the disassembly demo and the wasm object demo.
### Examples + +You can run the below piece of code to get a quick dump of a wasm object:
+```lua +libwasm=require(libwasm32) +libwasm.dump_all(my_wasm_obj.wasm) +``` + +for a quick dump of a wasm object.
First you should clone the mutator repo and run `git submodule init` and `git submodule update` to get the third-party repos that enable mutator to run.
To build bruiser you can either run the makefile in bruiser's directory, then run `make` or just run the makefile at mutator's root directory and run `make bruiser`.
After building bruiser, you can run it like any other mutator tool. So for example if you want to run bruiser on its test file run:
@@ -78,7 +87,7 @@ After building bruiser, you can run it like any other mutator tool. So for examp ``` -or if you're lazy like me just run the shellscript `run.sh` in bruiser's directory.
+or if you're short on time just run the shellscript `run.sh` in bruiser's directory.
After that you can just run your commands.
To run you commands from a lua file, you can just use `dofile()` to call your script. Bruiser has an embedded lua interpreter with the bruiser functions registered in it, so you do have full access to all lua libraries and functionalities plus the added bruiser functionality.
@@ -98,7 +107,7 @@ You can also run bruiser in non-cli mode:
``` The demo scripts, `demo1.lua` and `demo2.lua` require the file `bfd/test/test` and `bfd/test/test.so` to be built. Run make in `bfd/test/` to get `test` and `test.so`.
-Bruiser requires a compilation database to run. If you don't have a compilation database, take a look at [Bear](https://github.com/rizsotto/Bear). If you're using `cmake`, just tell it to generate a compilation database.
+Bruiser requires a compilation database to run. If you don't have a compilation database, take a look at [Bear](https://github.com/rizsotto/Bear) or [scan-build](https://github.com/rizsotto/scan-build). If you're using `cmake`, just tell it to generate a compilation database.
TLDR; now let's look at some useful example.
@@ -121,3 +130,4 @@ The ASMRewriter functionality allows you to look through the machine code and ma For working examples which demonstrate how much the implementation has improved you can run `lua-scripts/demo2.lua` and `lua-scripts/df-demo.lua`. `demo2.lua` requires `ansicolor`. `df-demo.lua` uses the dwarf fortress executable as an example so you will have to first get that and then change the path in the lua file.
For more detailed information on the modules and the methods they provide, you can look at the wiki.
+ diff --git a/bruiser/bruiser.cpp b/bruiser/bruiser.cpp index 440e72c..dcf3e30 100644 --- a/bruiser/bruiser.cpp +++ b/bruiser/bruiser.cpp @@ -897,7 +897,11 @@ public: DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics(); DE.setClient(BDCProto, false); TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); +#if __clang_major__ <= 9 return llvm::make_unique(TheRewriter); +#elif __clang_major__ >= 10 + return std::make_unique(TheRewriter); +#endif } private: @@ -919,7 +923,11 @@ class LiveActionListVars : public ASTFrontendAction { DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics(); DE.setClient(BDCProto, false); TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); +#if __clang_major__ <= 9 return llvm::make_unique(TheRewriter); +#elif __clang_major__ >= 10 + return std::make_unique(TheRewriter); +#endif } private: @@ -940,7 +948,11 @@ class LiveActionListFuncs : public ASTFrontendAction { DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics(); DE.setClient(BDCProto, false); TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); +#if __clang_major__ <= 9 return llvm::make_unique(TheRewriter); +#elif __clang_major__ >= 10 + return std::make_unique(TheRewriter); +#endif } private: @@ -961,7 +973,11 @@ class LiveActionListStructs : public ASTFrontendAction { DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics(); DE.setClient(BDCProto, false); TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); +#if __clang_major__ <= 9 return llvm::make_unique(TheRewriter); +#elif __clang_major__ >= 10 + return std::make_unique(TheRewriter); +#endif } private: @@ -982,7 +998,11 @@ class LiveActionListClasses : public ASTFrontendAction { DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics(); DE.setClient(BDCProto, false); TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); +#if __clang_major__ <= 9 return llvm::make_unique(TheRewriter); +#elif __clang_major__ >= 10 + return std::make_unique(TheRewriter); +#endif } private: @@ -1003,7 +1023,11 @@ class LiveActionListUnions : public ASTFrontendAction { DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics(); DE.setClient(BDCProto, false); TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); +#if __clang_major__ <= 9 return llvm::make_unique(TheRewriter); +#elif __clang_major__ >= 10 + return std::make_unique(TheRewriter); +#endif } private: @@ -1024,7 +1048,11 @@ class LiveActionListArrays : public ASTFrontendAction { DiagnosticsEngine &DE = CI.getPreprocessor().getDiagnostics(); DE.setClient(BDCProto, false); TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts()); +#if __clang_major__ <= 9 return llvm::make_unique(TheRewriter); +#elif __clang_major__ >= 10 + return std::make_unique(TheRewriter); +#endif } private: @@ -2290,6 +2318,7 @@ class RunLoop { } } + char* prv_command; /*cli execution loop*/ while((command = linenoise(">>>")) != NULL) { //FIXME-if the current command is the same as last command skip adding to history @@ -2297,6 +2326,7 @@ class RunLoop { linenoiseHistorySave(SHELL_HISTORY_FILE.c_str()); le.RunChunk(command); linenoiseFree(command); + //prv_commnad = command; } return 0; } diff --git a/bruiser/lua-scripts/libwasm32.lua b/bruiser/lua-scripts/libwasm32.lua new file mode 100644 index 0000000..0f7ad11 --- /dev/null +++ b/bruiser/lua-scripts/libwasm32.lua @@ -0,0 +1,265 @@ + +colors = require("ansicolors") + +local libwasm = {} + +function libwasm.dump_type_section(a) + print(colors("%{green}".."\ntype section:")) + if a["type_section"] ~= nil then + io.write(tostring("id:"..a["type_section"]:id()).."\n") + io.write(tostring("payloadlength:"..a["type_section"]:payloadlength()).."\n") + io.write(tostring("count:"..a["type_section"]:count()).."\n") + io.write("entries"..tostring(a["type_section"]:entries()).."\n") + for k, v in pairs(a["type_section"]:entries()) do + io.write(v:form().."\t") + io.write(v:param_count().."\t") + io.write(v:param_types().."\t") + io.write(v:return_count().."\t") + io.write(v:return_types().."\n") + end + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_import_section(a) + print(colors("%{green}".."\nimport section:")) + if a["import_section"] ~= nil then + io.write("id:"..tostring(a["import_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["import_section"]:payloadlength()).."\n") + io.write("count:"..tostring(a["import_section"]:count()).."\n") + io.write("entries"..tostring(a["import_section"]:entries()).."\n") + for k, v in pairs(a["import_section"]:entries()) do + io.write("module length:"..v:module_length().."\t") + io.write("module str:"..v:module_str().."\t") + io.write("field len:"..v:field_len().."\t") + io.write("field str:"..v:field_str().."\t") + io.write("kind:"..v:kind().."\t") + io.write("kind:"..tostring(v:type()).."\t") + if v:kind() == 0 then + print() + io.write("kind:"..tostring(v:type()).."\n") + elseif v:kind() == 1 then + io.write("element_type:"..v:type():element_type().."\n") + --io.write("rsz:"..v:type():resizable_limit().."\t") + --io.write("flags:"..v:type():resizable_limit():flags().."\t") + --io.write("init:"..v:type():resizable_limit():init().."\t") + --io.write("max:"..v:type():resizable_limit():maximum().."\n") + elseif v:kind() == 2 then + --io.write("rsz:"..v:type():resizable_limit().."\t") + --io.write("flags:"..v:type():resizable_limit():flags().."\t") + --io.write("init:"..v:type():resizable_limit():init().."\t") + --io.write("max:"..v:type():resizable_limit():maximum().."\n") + print() + elseif v:kind() == 3 then + io.write("value_type:"..v:type():value_type().."\t") + io.write("mutability:"..v:type():mutability().."\n") + end + end + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_function_section(a) + print(colors("%{green}".."\nfunction section:")) + if a["function_section"] ~= nil then + io.write("id:"..tostring(a["function_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["function_section"]:payloadlength()).."\n") + io.write("count:"..tostring(a["function_section"]:count()).."\n") + io.write("types:"..tostring(a["function_section"]:types()).."\n") + for k,v in pairs(a["function_section"]:types()) do + print(v) + end + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_table_section(a) + print(colors("%{green}".."\ntable section:")) + if a["table_section"] ~= nil then + io.write("id:"..tostring(a["table_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["table_section"]:payloadlength()).."\n") + io.write("count:"..tostring(a["table_section"]:count()).."\n") + io.write("entries:"..tostring(a["table_section"]:entries()).."\n") + for k, v in pairs(a["table_section"]:entries()) do + io.write(v:element_type().."\t") + io.write(tostring(v:resizable_limit()).."\t") + io.write(v:resizable_limit():flags().."\t") + io.write(v:resizable_limit():initial().."\t") + io.write(v:resizable_limit():maximum().."\n") + end + else + print(colors("%{red}".."section doesnt exist.")) + end +end + + +function libwasm.dump_memory_section(a) + print(colors("%{green}".."\nmemory section:")) + if a["memory_section"] ~= nil then + io.write("id:"..tostring(a["memory_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["memory_section"]:payloadlength()).."\n") + --for wasm v.1.0. memory section count is 1 + --io.write("count:"..tostring(a["memory_section"]:count()).."\n") + io.write("entries:"..tostring(a["memory_section"]:entries()).."\n") + io.write(a["memory_section"]:entries():resizable_limit():flags().."\t") + io.write(a["memory_section"]:entries():resizable_limit():initial().."\t") + io.write(a["memory_section"]:entries():resizable_limit():maximum().."\n") + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_global_section(a) + print(colors("%{green}".."\nglobal section:")) + if (a["global_section"] ~= nil) then + io.write("id:"..tostring(a["global_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["global_section"]:payloadlength()).."\n") + io.write("count:"..tostring(a["global_section"]:count()).."\n") + io.write("globals:"..tostring(a["global_section"]:globals()).."\n") + for k, v in pairs(a["global_section"]:globals()) do + io.write(v:global_type().."\t") + io.write(v:init().."\n") + io.write(v:init():code().."\n") + end + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_export_section(a) + print(colors("%{green}".."\nexport section:")) + if (a["export_section"] ~= nil) then + io.write("id:"..tostring(a["export_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["export_section"]:payloadlength()).."\n") + io.write("count:"..tostring(a["export_section"]:count()).."\n") + io.write("entries:"..tostring(a["export_section"]:entries()).."\n") + for k, v in pairs(a["export_section"]:entries()) do + io.write(v:field_len().."\t") + io.write(v:field_str().."\t") + io.write(v:kind().."\t") + io.write(v:index().."\n") + end + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_start_section(a) + print(colors("%{green}".."\nstart section:")) + if (a["start_section"] ~= nil) then + io.write("id:"..tostring(a["start_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["start_section"]:payloadlength()).."\n") + io.write("index:"..tostring(a["start_section"]:index()).."\n") + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_element_section(a) + print(colors("%{green}".."\nelement section:")) + if (a["element_section"] ~= nil) then + io.write("id:"..tostring(a["element_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["element_section"]:payloadlength()).."\n") + io.write("count:"..tostring(a["element_section"]:count()).."\n") + io.write(colors("%{cyan}".."entries:"..tostring(a["element_section"]:entries()).."\n")) + for k, v in pairs(a["element_section"]:entries()) do + io.write("index:"..v:index().."\t") + io.write("init:") + for i = 1, #v:init():code() do + local c = v:init():code():sub(i,i) + io.write(colors("%{red}"..string.byte(c)).." ") + end + io.write("\n") + io.write("number of elements:"..v:num_length().."\t") + io.write("elems:") + for i, j in pairs(v:elems()) do + io.write(colors("%{red}"..j.." ")) + end + io.write("\n") + end + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_code_section(a) + print(colors("%{green}".."\ncode section:")) + if (a["code_section"] ~= nil) then + io.write("id:"..tostring(a["code_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["code_section"]:payloadlength()).."\n") + io.write("count:"..tostring(a["code_section"]:count()).."\n") + io.write("bodies:"..tostring(a["code_section"]:bodies()).."\n") + for k,v in pairs(a["code_section"]:bodies()) do + io.write(colors("\n%{cyan}".."entry:\n")) + io.write("body_size:"..v:body_size().."\t") + io.write("local_count:"..v:local_count().."\t") + io.write(tostring(v:locals()).."\n") + for i, j in pairs(v:locals()) do + io.write("locals count:"..j:count().."\t") + io.write("locals type:"..j:type().."\n") + end + io.write("function body:\n") + for i,j in pairs(v:code()) do + io.write(colors("%{red}"..j.." ")) + end + io.write("\n") + end + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_data_section(a) + print(colors("%{green}".."\ndata section:")) + if (a["data_section"] ~= nil) then + io.write("id:"..tostring(a["data_section"]:id()).."\n") + io.write("payloadlength:"..tostring(a["data_section"]:payloadlength()).."\n") + io.write("count:"..tostring(a["data_section"]:count()).."\n") + io.write("entries:"..tostring(a["data_section"]:entries()).."\n") + if type(a["data_section"]:entries()) == "table" then + io.write(colors("%{cyan}".."entries:").."\n") + for k,v in pairs(a["data_section"]:entries()) do + io.write("index:"..v:index().."\n") + io.write("offset: ") + for i = 1, #v:offset():code() do + local c = v:offset():code():sub(i,i) + io.write(colors("%{red}"..string.byte(c)).." ") + end + io.write("\n") + io.write("size:"..v:size().."\n") + for i, j in pairs(v:data()) do + io.write(colors("%{blue}"..string.char(j))) + end + io.write("\n") + end + end + else + print(colors("%{red}".."section doesnt exist.")) + end +end + +function libwasm.dump_all(wasm_path) + local a = getwasmobj(wasm_path) + libwasm.dump_type_section(a) + libwasm.dump_import_section(a) + libwasm.dump_function_section(a) + libwasm.dump_table_section(a) + libwasm.dump_memory_section(a) + libwasm.dump_global_section(a) + libwasm.dump_export_section(a) + libwasm.dump_start_section(a) + libwasm.dump_element_section(a) + libwasm.dump_code_section(a) + libwasm.dump_data_section(a) +end + +function libwasm.dev(wasm_path) + local a = getwasmobj(wasm_path) + libwasm.dump_import_section(a) +end + +return libwasm + -- cgit v1.2.3