From 2e16354693c5b0b2ea03a7824e6f9e527c0a66e9 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 9 Jun 2015 13:40:01 -0400 Subject: [PATCH] fix reveng memory bug + @iceman1001 s scripting --- client/cmdcrc.c | 245 ++++++++++++++++++++----------------------- client/cmdmain.c | 16 +-- client/reveng/cli.c | 2 +- client/scripting.c | 58 ++++++++++ client/scripts/e.lua | 69 ++++++++++++ 5 files changed, 252 insertions(+), 138 deletions(-) create mode 100644 client/scripts/e.lua diff --git a/client/cmdcrc.c b/client/cmdcrc.c index 3e68afb9..f756cde4 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -90,16 +90,11 @@ int GetModels(char *Models[], int *count, uint32_t *width){ PZERO, /* check value unused */ NULL /* no model name */ }; + int ibperhx = 8;//, obperhx = 8; int rflags = 0, uflags = 0; /* search and UI flags */ - - //unsigned long width = 0UL; - //int c, mode = 0, args, psets, pass; poly_t apoly, crc, qpoly = PZERO, *apolys = NULL, *pptr = NULL, *qptr = NULL; model_t pset = model, *candmods, *mptr; - //char *string; - - //myname = argv[0]; /* stdin must be binary */ #ifdef _WIN32 @@ -108,14 +103,10 @@ int GetModels(char *Models[], int *count, uint32_t *width){ SETBMP(); - //pos=0; - //optind=1; - int args = 0, psets, pass; int Cnt = 0; if (*width == 0) { //reveng -D *count = mcount(); - //PrintAndLog("Count: %d",*count); if(!*count) return uerr("no preset models available"); @@ -123,153 +114,149 @@ int GetModels(char *Models[], int *count, uint32_t *width){ mbynum(&model, mode); mcanon(&model); size_t size = (model.name && *model.name) ? strlen(model.name) : 6; - //PrintAndLog("Size: %d, %s",size,model.name); char *tmp = calloc(size+1, sizeof(char)); if (tmp==NULL) return uerr("out of memory?"); memcpy(tmp, model.name, size); Models[mode] = tmp; - //ufound(&model); } + mfree(&model); } else { //reveng -s - if(~model.flags & P_MULXN) - return uerr("cannot search for non-Williams compliant models"); + if(~model.flags & P_MULXN) + return uerr("cannot search for non-Williams compliant models"); - praloc(&model.spoly, *width); - praloc(&model.init, *width); - praloc(&model.xorout, *width); - if(!plen(model.spoly)) - palloc(&model.spoly, *width); - else - *width = plen(model.spoly); + praloc(&model.spoly, *width); + praloc(&model.init, *width); + praloc(&model.xorout, *width); + if(!plen(model.spoly)) + palloc(&model.spoly, *width); + else + *width = plen(model.spoly); - /* special case if qpoly is zero, search to end of range */ - if(!ptst(qpoly)) - rflags &= ~R_HAVEQ; + /* special case if qpoly is zero, search to end of range */ + if(!ptst(qpoly)) + rflags &= ~R_HAVEQ; - /* not going to be sending additional args + /* not going to be sending additional args at this time (maybe future?) - // allocate argument array - args = argc - optind; - if(!(apolys = malloc(args * sizeof(poly_t)))) - return uerr("cannot allocate memory for argument list"); + // allocate argument array + args = argc - optind; + if(!(apolys = malloc(args * sizeof(poly_t)))) + return uerr("cannot allocate memory for argument list"); - for(pptr = apolys; optind < argc; ++optind) { - if(uflags & C_INFILE) - *pptr++ = rdpoly(argv[optind], model.flags, ibperhx); - else - *pptr++ = strtop(argv[optind], model.flags, ibperhx); - } - // exit value of pptr is used hereafter! - - */ - - /* if endianness not specified, try - * little-endian then big-endian. - * NB: crossed-endian algorithms will not be - * searched. - */ - /* scan against preset models */ - if(~uflags & C_FORCE) { - pass = 0; - Cnt = 0; - do { - psets = mcount(); - //PrintAndLog("psets: %d",psets); - while(psets) { - mbynum(&pset, --psets); - - /* skip if different width, or refin or refout don't match */ - if(plen(pset.spoly) != *width || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT)) - continue; - /* skip if the preset doesn't match specified parameters */ - if(rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly)) - continue; - if(rflags & R_HAVEI && psncmp(&model.init, &pset.init)) - continue; - if(rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout)) - continue; - - apoly = pclone(pset.xorout); - if(pset.flags & P_REFOUT) - prev(&apoly); - for(qptr = apolys; qptr < pptr; ++qptr) { - crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0); - if(ptst(crc)) { - pfree(&crc); - break; - } else - pfree(&crc); - } - pfree(&apoly); - if(qptr == pptr) { - /* the selected model solved all arguments */ - mcanon(&pset); - - size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 6; - //PrintAndLog("Size: %d, %s, count: %d",size,pset.name, Cnt); - char *tmp = calloc(size+1, sizeof(char)); - if (tmp==NULL){ - PrintAndLog("out of memory?"); - return 0; - } - memcpy(tmp, pset.name, size); - Models[Cnt++] = tmp; - *count = Cnt; - //ufound(&pset); - uflags |= C_RESULT; - } - } - mfree(&pset); + for(pptr = apolys; optind < argc; ++optind) { + if(uflags & C_INFILE) + *pptr++ = rdpoly(argv[optind], model.flags, ibperhx); + else + *pptr++ = strtop(argv[optind], model.flags, ibperhx); + } + // exit value of pptr is used hereafter! + + */ - /* toggle refIn/refOut and reflect arguments */ - if(~rflags & R_HAVERI) { - model.flags ^= P_REFIN | P_REFOUT; - for(qptr = apolys; qptr < pptr; ++qptr) - prevch(qptr, ibperhx); - } - } while(~rflags & R_HAVERI && ++pass < 2); - } - if(uflags & C_RESULT) { - for(qptr = apolys; qptr < pptr; ++qptr) - pfree(qptr); - return 1; - //exit(EXIT_SUCCESS); - } - if(!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)) - return uerr("cannot search for crossed-endian models"); + /* if endianness not specified, try + * little-endian then big-endian. + * NB: crossed-endian algorithms will not be + * searched. + */ + /* scan against preset models */ + if(~uflags & C_FORCE) { pass = 0; + Cnt = 0; do { - mptr = candmods = reveng(&model, qpoly, rflags, args, apolys); - if(mptr && plen(mptr->spoly)) - uflags |= C_RESULT; - while(mptr && plen(mptr->spoly)) { - /* results were printed by the callback - * string = mtostr(mptr); - * puts(string); - * free(string); - */ - mfree(mptr++); + psets = mcount(); + //PrintAndLog("psets: %d",psets); + while(psets) { + mbynum(&pset, --psets); + + /* skip if different width, or refin or refout don't match */ + if(plen(pset.spoly) != *width || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT)) + continue; + /* skip if the preset doesn't match specified parameters */ + if(rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly)) + continue; + if(rflags & R_HAVEI && psncmp(&model.init, &pset.init)) + continue; + if(rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout)) + continue; + + //for additional args (not used yet, maybe future?) + apoly = pclone(pset.xorout); + if(pset.flags & P_REFOUT) + prev(&apoly); + + for(qptr = apolys; qptr < pptr; ++qptr) { + crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0); + if(ptst(crc)) { + pfree(&crc); + break; + } else + pfree(&crc); + } + pfree(&apoly); + if(qptr == pptr) { + + /* the selected model solved all arguments */ + + mcanon(&pset); + + size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 6; + //PrintAndLog("Size: %d, %s, count: %d",size,pset.name, Cnt); + char *tmp = calloc(size+1, sizeof(char)); + if (tmp==NULL){ + PrintAndLog("out of memory?"); + return 0; + } + memcpy(tmp, pset.name, size); + Models[Cnt++] = tmp; + *count = Cnt; + uflags |= C_RESULT; + } } - free(candmods); + mfree(&pset); + + /* toggle refIn/refOut and reflect arguments */ if(~rflags & R_HAVERI) { model.flags ^= P_REFIN | P_REFOUT; for(qptr = apolys; qptr < pptr; ++qptr) prevch(qptr, ibperhx); } } while(~rflags & R_HAVERI && ++pass < 2); + } + //got everything now free the memory... + + if(uflags & C_RESULT) { for(qptr = apolys; qptr < pptr; ++qptr) pfree(qptr); - free(apolys); - if(~uflags & C_RESULT) - return uerr("no models found"); - - + } + if(!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)) + return uerr("cannot search for crossed-endian models"); + + pass = 0; + do { + mptr = candmods = reveng(&model, qpoly, rflags, args, apolys); + if(mptr && plen(mptr->spoly)) + uflags |= C_RESULT; + while(mptr && plen(mptr->spoly)) { + mfree(mptr++); + } + free(candmods); + if(~rflags & R_HAVERI) { + model.flags ^= P_REFIN | P_REFOUT; + for(qptr = apolys; qptr < pptr; ++qptr) + prevch(qptr, ibperhx); + } + } while(~rflags & R_HAVERI && ++pass < 2); + for(qptr = apolys; qptr < pptr; ++qptr) + pfree(qptr); + free(apolys); + if(~uflags & C_RESULT) + return uerr("no models found"); + mfree(&model); } - //PrintAndLog("DONE"); return 1; } diff --git a/client/cmdmain.c b/client/cmdmain.c index 6d4d9c1f..c479e151 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -33,10 +33,10 @@ unsigned int current_command = CMD_UNKNOWN; static int CmdHelp(const char *Cmd); static int CmdQuit(const char *Cmd); static int CmdRev(const char *Cmd); -/* // for testing reveng api - cmdcrc.c + // for testing reveng api - cmdcrc.c static int CmdrevengT(const char *Cmd); static int CmdrevengC(const char *Cmd); -*/ + //For storing command that are received from the device static UsbCommand cmdBuffer[CMD_BUFFER_SIZE]; @@ -53,10 +53,10 @@ static command_t CommandTable[] = {"hw", CmdHW, 1, "{ Hardware commands... }"}, {"lf", CmdLF, 1, "{ Low Frequency commands... }"}, {"reveng",CmdRev, 1, "Crc calculations from the software reveng1-30"}, - /* // for testing reveng api - cmdcrc.c - {"revengt",CmdrevengT,1, "TEST Crc calculations from the software reveng1-30"}, - {"revengc",CmdrevengC,1, "TEST Crc calculations from the software reveng1-30"}, - */ + // for testing reveng api - cmdcrc.c + //{"revengt",CmdrevengT,1, "TEST Crc calculations from the software reveng1-30"}, + //{"revengc",CmdrevengC,1, "TEST Crc calculations from the software reveng1-30"}, + {"script",CmdScript,1, "{ Scripting commands }"}, {"quit", CmdQuit, 1, "Exit program"}, {"exit", CmdQuit, 1, "Exit program"}, @@ -84,7 +84,7 @@ int CmdRev(const char *Cmd) CmdCrc(Cmd); return 0; } -/* // for testing reveng api - cmdcrc.c + // for testing reveng api - cmdcrc.c int CmdrevengT(const char *Cmd) { return CmdrevengTest(Cmd); @@ -93,7 +93,7 @@ int CmdrevengC(const char *Cmd) { return CmdrevengTestC(Cmd); } -*/ + /** * @brief This method should be called when sending a new command to the pm3. In case any old * responses from previous commands are stored in the buffer, a call to this method should clear them. diff --git a/client/reveng/cli.c b/client/reveng/cli.c index 7b936c67..538fab19 100644 --- a/client/reveng/cli.c +++ b/client/reveng/cli.c @@ -444,7 +444,7 @@ ippx: if(uflags & C_RESULT) { for(qptr = apolys; qptr < pptr; ++qptr) pfree(qptr); - return 1; + //return 1; //exit(EXIT_SUCCESS); } if(!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){ diff --git a/client/scripting.c b/client/scripting.c index 6b26ec59..414f5315 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -22,6 +22,7 @@ #include "../common/crc64.h" #include "../common/sha1.h" #include "aes.h" +#include "cmdcrc.h" /** * The following params expected: * UsbCommand c @@ -388,6 +389,60 @@ static int l_sha1(lua_State *L) return 1; } +static int l_reveng_models(lua_State *L){ + + char *models[80]; + int count = 0; + lua_Integer in_width = luaL_checkinteger(L, 1); + + if( in_width > 89 ) return returnToLuaWithError(L,"Width cannot exceed 89, got %d", in_width); + + uint32_t width = (uint32_t)in_width; + int ans = GetModels(models, &count, &width); + if (!ans) return 0; + + lua_newtable(L); + + for (int i = 0; i < count; i++){ + lua_pushstring(L, (const char*)models[i]); + lua_rawseti(L,-2,i+1); + free(models[i]); + } + + return 1; +} + +static int l_reveng_RunModel(lua_State *L){ + //-c || -v + //inModel = valid model name string - CRC-8 + //inHexStr = input hex string to calculate crc on + //reverse = reverse calc option if true + //endian = {0 = calc default endian input and output, b = big endian input and output, B = big endian output, r = right justified + // l = little endian input and output, L = little endian output only, t = left justified} + //result = calculated crc hex string + char result[50]; + + size_t dataLen; + const char *inModel = luaL_checklstring(L, 1, &dataLen); + if ( dataLen < 4 ) return returnToLuaWithError(L,"Can't find model, got %s", inModel); + + const char *inHexStr = luaL_checklstring(L, 2, &dataLen); + if ( dataLen < 4 ) return returnToLuaWithError(L,"Hex string too short, got %d", dataLen); + + int reverse = luaL_checkinteger(L, 3); + const char endian = luaL_checklstring(L, 4, &dataLen)[0]; + + //PrintAndLog("mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse); + //int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result) + int ans = RunModel( (char *)inModel, (char *)inHexStr, (bool)reverse, endian, result); + if (!ans) + return returnToLuaWithError(L,"Reveng failed"); + + lua_pushstring(L, (const char*)result); + return 1; +} + + /** * @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be * able to do "require('foobar')" if foobar.lua is within lualibs folder. @@ -433,6 +488,9 @@ int set_pm3_libraries(lua_State *L) {"crc16", l_crc16}, {"crc64", l_crc64}, {"sha1", l_sha1}, + {"reveng_models", l_reveng_models}, + {"reveng_runmodel", l_reveng_RunModel}, + {NULL, NULL} }; diff --git a/client/scripts/e.lua b/client/scripts/e.lua new file mode 100644 index 00000000..4dd71490 --- /dev/null +++ b/client/scripts/e.lua @@ -0,0 +1,69 @@ +local getopt = require('getopt') +local utils = require('utils') + +example = "script calculates many checksums (CRC) over the provided hex input" +author = "Iceman" +desc = +[[ +This script calculates many checksums (CRS) over the provided hex input. + +Arguments: + -b data in hex + -w width of the CRC algorithm. defaults to all known CRC presets. +Examples : + script run e -b 010203040506070809 + script run e -b 010203040506070809 -w 16 +]] + +--- +-- A debug printout-function +function dbg(args) + if DEBUG then + print("###", args) + end +end +--- +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) + return nil,err +end +--- +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end +--- +-- The main entry point +function main(args) + + local data = '01020304' + local width = 0 + + -- Read the parameters + for o, a in getopt.getopt(args, 'hb:w:') do + if o == "h" then return help() end + if o == "b" then data = utils.ConvertHexToa end + if o == "w" then width = a end + end + + print('Width of CRC: '..width..' bytes: '..data) + print('') + print('Model','CRC', 'CRC_Reverse') + + local lists = core.reveng_models(width) + for _,i in pairs(lists) do + local one = core.reveng_runmodel(i, data, 0,0) + local two = core.reveng_runmodel(i, data, 1,0) + + print(i, one, two) + end + + if 1 == 1 then + return + end +end + +main(args) \ No newline at end of file -- 2.39.2