![]() |
|
[Lua] LMC - MD5 cracker - Printable Version +- Sinisterly (https://sinister.li) +-- Forum: Coding (https://sinister.li/Forum-Coding) +--- Forum: Coding (https://sinister.li/Forum-Coding--71) +--- Thread: [Lua] LMC - MD5 cracker (/Thread-Lua-LMC-MD5-cracker) Pages:
1
2
|
[Lua] LMC - MD5 cracker - noize - 08-07-2013 LMC - Lua MD5 Cracker Latest version: 2.4 (stable) Latest stable: 2.4 Supports: Code: [*] wordlist-based attacks
[*] bruteforcing (supports hash files, timeout for single hash, custom alphabets and word length (also ranges))
[*] hash/checksum generation
[*] list (line-by-line) encryption
[*] stdout + outfile
[*] web crawling based password cracking (tries each word found on the web pages)
[*] IP bruteforcing (for web crawling)
[*] wordlist-based DNS forcing (for web crawling)See --help or --about for more information. Please, report/post any bug, suggestion or comment. Code: --------------------------------------------------------------------------------
-- LMC 2.4 --
-- (( Lua MD5 Cracker )) --
--------------------------------------------------------------------------------
-- You're allowed to edit and/or give away for free this code as whole or in --
-- part as long as you give credits. --
--------------------------------------------------------------------------------
-- LMC · coded by noize · 2013 --
--------------------------------------------------------------------------------
require("strbuf")
require("list")
require("md5")
print("")
local tried = {}
--------------------------------------------------------------------------------
-- define error functions
--------------------------------------------------------------------------------
local err = {}
function err.few_args()
print("not enough arguments.")
os.exit(2)
end
function err.readf(file)
print("error: failed to read " .. file .. "file.")
os.exit(1)
end
function err.unknown_arg(argx,n)
print("argument #" .. n .. " '" .. argx .. "' not recognized.")
os.exit(2)
end
function err.wordlen_nan()
print("error: word length must be a number.")
os.exit(2)
end
function err.unexp_dash_in_len()
print("error: unexpected dash in word length declaration.")
os.exit(2)
end
--------------------------------------------------------------------------------
-- define handling functions
--------------------------------------------------------------------------------
function rand(f,c)
math.randomseed(os.time())
math.randomseed(math.random(os.clock(),os.time()))
return math.random(f,c)
end
function generator(alphabet,length)
local gen = {}
if length then
gen.length = length
else
gen.length = "4-12"
end
if gen.length:find("%-") then
local splt = string.split(gen.length,"%-")
if not splt[2] or splt[3] then
err.unexp_dash_in_len()
else
gen.length = rand(splt[1],splt[2])
end
end
gen.length = tonumber(gen.length)
if alphabet then
gen.alphabet = {}
for w in alphabet:gmatch("%S+") do
table.insert(gen.alphabet,w)
end
else
gen.alphabet = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","1","2","3","4","5","6","7","8","9","0","!","&","-","_","."}
end
gen.pass = ""
for s = 1, gen.length do
gen.alphabet = shuffle(gen.alphabet)
gen.pass = gen.pass .. gen.alphabet[rand(1,#gen.alphabet)]
end
while tried[gen.pass] do
gen.pass = ""
for s = 1, gen.length do
gen.alphabet = shuffle(gen.alphabet)
gen.pass = gen.pass .. gen.alphabet[rand(1,#gen.alphabet)]
end
end
return gen.pass
end
function shuffle(array)
local order, res = {}, {}
for i = 1, #array do
math.randomseed(os.time() / math.random())
math.randomseed(os.time() / math.random() * os.clock())
math.randomseed(os.clock() * math.random() / os.time())
order[i] = {
rnd = math.random(),
idx = i
}
end
local f = array[1]
table.insert(array,f)
local r = math.random(1,#array)
local t = array[r]
table.remove(array,r)
table.sort(order, function(a,b) return a.rnd < b.rnd end)
table.insert(array,t)
table.remove(array,1)
for i = 1, #array do
res[i] = array[order[i].idx]
end
return res
end
function force(hash,hashfile,timeout,outfile,alphabet,length)
local t = os.clock()
function try(str,hash)
local len = {}
len.max = (tonumber(length) or length)
if type(len.max) ~= "number" then
local split = len.max:split("%-")
len.min = tonumber(split[1])
len.max = tonumber(split[2])
if not len.min or not len.max then
err.wordlen_nan()
end
end
if str:len() >= len.min and str:len() <= len.max then
print("trying: " .. hash .. ":" .. str)
if (md5.sumhexa(str) == hash) then
if outfile then
local f = io.open(outfile,"a")
f:write(hash .. ":" .. str .. "\n")
f:close()
end
return hash, str
end
end
end
while (os.clock() < t + (timeout or os.clock())) do
local str = generator(alphabet,length)
tried[str] = true
tried[#tried + 1] = true
if hashfile then
for hash in io.lines(hash) do
if wordtweak() then
tweak(str,hash)
else
try(str,hash)
end
end
else
if wordtweak() then
tweak(str,hash)
else
try(str,hash)
end
end
end
return hash, false
end
function checkf(file,error)
local f = io.open(file,"r")
if f then
f:close()
else
err.readf(error)
end
end
--------------------------------------------------------------------------------
-- define main functions
--------------------------------------------------------------------------------
function usage()
print(" ***********************************************\n")
print(" *** LMC cracker by noize ***\n")
print(" ***********************************************\n")
print(" usage: lua lmc.lua [-c | -b | -h | -f | -l | -w | --help | --about]")
print(" [wordlist | hash | -f hashfile [-t timeout] [-a alphabet]")
print(" [-l length] | string | file | list | -b | -l wordlist]")
print(" [-s hash | -f hashfile | -m | -o outfile]\n")
print(" -c cracking mode")
print(" wordlist password file to read passwords from")
print(" -m enable word mangling")
print(" -s single hash")
print(" hash hash to crack")
print(" -f read hashes from hashfile")
print(" hashfile file to read hashes to crack from")
print(" -o write cracked passwords to outfile (if omitted stdout is used)")
print(" -b bruteforcing mode")
print(" hash hash to crack")
print(" -f read hashes from hashfile")
print(" hashfile file to read hashes to crack from")
print(" -t set timeout in seconds per hash")
print(" timeout go to next hash in case the hash wasn't cracked in time")
print(" -a use custom alphabet (default is \"a b c d e f g h i j k l m n")
print(" o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 0 ! & - _ .\")")
print(" alphabet alphabet to use (characters are separated with whitespaces)")
print(" -l custom password length (default is 4-12)")
print(" length length for the password (ranges are allowed as above shown)")
print(" -m enable word mangling")
print(" -o write cracked passwords to outfile")
print(" -h hashing mode")
print(" string string to encrypt (enclosed in quotes for more words)")
print(" -f file checksum mode")
print(" file file to hash")
print(" -o write checksum to outfile (if omitted stdout is used)")
print(" -l list encryption mode")
print(" list hash file line by line")
print(" -o write output to outfile (if omitted stdout is used)")
print(" -w web spider mode")
print(" -b IP bruteforcing mode (see --about for more)")
print(" hash hash to crack")
print(" -f hashes file")
print(" hashfile file to read hashes to crack from")
print(" -o write cracked passwords to outfile (if omitted stdout is used)")
print(" -l wordlist wordlist-based DNS forcing mode (see --about for more)")
print(" hash hash to crack")
print(" -f hashes file")
print(" hashfile file to read hashes to crack from")
print(" -o write cracked passwords to outfile (if omitted stdout is used)")
print(" outfile output file (only with -o)")
print("\n examples:\n")
print(" lua lmc.lua -c wordlist.txt -s d41d8cd98f00b204e9800998ecf8427e")
print(" lua lmc.lua -c password.lst -f hashes.txt")
print(" lua lmc.lua -c wordlist.txt -f db_passwords -o success.txt")
print(" lua lmc.lua -b 9dd8b2a63b2aae4a2633d04b14141294")
print(" lua lmc.lua -b -f hashfile.txt")
print(" lua lmc.lua -b -f hash.lst -l 3 -o psw.lst")
print(" lua lmc.lua -b -f hashes.txt -t 60000 -o cracked.txt")
print(" lua lmc.lua -b -f hashes.txt -o out.txt -a \"a b c 1 2 3\" -l 2-6")
print(" lua lmc.lua -h \"a backslash escapes \\\"quotes\\\"\"")
print(" lua lmc.lua -f exeimage")
print(" lua lmc.lua -f pe.exe -o checksum.txt")
print(" lua lmc.lua -l password.lst -o hashes.lst")
print(" lua lmc.lua -w -b -f hashfile.lst")
print(" lua lmc.lua -w -l sitenames.txt 9dd8b2a63b2aae4a2633d04b14141294")
print(" lua lmc.lua -w -l wordlist.txt -f hashes.txt -o cracked.psw")
end
function about()
print("=====================\n")
print("LMC (Lua MD5 Cracker)\n")
print("=====================\n")
print("Program version: 2.4")
print("Lua version: 5.1")
print("\n=====================")
print("\nLMC offers more than just usual hash cracking:")
print("its options include:\n")
print(" [ OK ] hash generation")
print(" [ OK ] checksum generation")
print(" [ OK ] list encryption")
print(" [ OK ] bruteforcing")
print(" [ OK ] word tweaking (see notes)")
print(" [ OK ] web crawling based password cracking (see notes)")
print("\n=====================")
print("\nsupported algorithms:\n")
print("=====================\n")
print(" [ OK ] MD5")
print("\n=====================")
print("\nsupported attacks:\n")
print("=====================\n")
print(" [ OK ] bruteforce")
print(" [ OK ] wordlist-based")
print(" [ OK ] spider-based")
print("\n=====================")
print("\nnotes:\n")
print("=====================\n")
print(" - cracked passwords are output as well as saved to file when -o is used")
print(" - in web spider mode, LMC crawls through the Internet and tries all the words")
print(" it finds once (it won't try the same word more times)")
print(" the DNS names it uses on the run are generated randomly (DNS bruteforcing)")
print(" this tecnique is inspired to Deque's WikiCrawler wordlist generator")
print(" I don't believe, though, that this kind of tecnique has ever been used for")
print(" password cracking this way before")
print(" - if you use the -w option with the -f option, you'll need to manually stop")
print(" the program, 'cause it'll theorically run endlessly")
print(" - you can enable word mangling (\"-m\" option) only with a cracking option.")
print(" the following cracking methods support word mangling:")
print(" [ OK ] bruteforcing")
print(" [ OK ] wordlist cracking")
print(" [ ] web-based cracking (will come)")
print(" an example of a word picked from a list:")
print(" password")
print(" if word mangling is enabled, some of the words that will be tried include:")
print(" Password")
print(" PASSWORD")
print(" password0")
print(" password1234")
print(" password123456")
print(" p455w0rd")
print(" passwordPASSWORD")
print(" passwordpasswordpassword")
print("\n=====================")
print("\nknown bugs:\n")
print("=====================\n")
print(" - a known issue with the bruteforcing version of the mangling algorithm, is")
print(" that it does not respect the defined word-length")
print(" - for some still unknown to me reason it looks like sometimes, the")
print(" bruteforcing algorithm throws in a \"ú\" character even when it is not")
print(" present in the defined alphabet")
print(" if you've got any idea why this is happening, please, let me know")
print("\n=====================")
print("\nLMC - coded by noize\n")
print("=====================")
end
function checksum()
checkf(arg[2],"")
local f = io.open(arg[2],"r")
if arg[4] then local o = io.open(arg[4],"w") end
local checksum = md5.sumhexa(f:read("*a"))
print(checksum)
if arg[3] == "-o" then
o:write(checksum)
end
f:close()
end
function listf() -- to avoid conflicts with the required list() function
checkf(arg[2],"")
local f = io.open(arg[2],"r")
if not arg[3] == "-o" then
for l in io.lines(arg[2]) do
print(md5.sumhexa(l))
end
else
os.remove(arg[4])
local f = io.open(arg[4],"a")
for l in io.lines(arg[2]) do
f:write(md5.sumhexa(l) .. "\n")
end
end
end
function wordtweak()
for i = 2, 15 do
if arg[i] == "-m" then
return true
end
end
return false
end
function tweak(word,hash)
function mangle(m)
try(word .. m,hash)
end
mangle("")
mangle(word)
mangle(word .. word)
mangle("00")
mangle("007")
mangle("0010")
mangle("000")
mangle("0001")
mangle("12345")
mangle("123456")
for i = 0, 100 do
mangle(i)
end
for i = 1900, 2100 do
mangle(i)
end
mangle("123456")
mangle(word:lower())
mangle(word:upper())
try(word:lower(),hash)
try(word:upper(),hash)
try(word:lower() .. word:upper(),hash)
for c in word:gmatch("[^%s]") do
mangle(c)
try(c .. word,hash)
try(c:upper() .. word:ltrim(c),hash)
for i = 0, 100 do
mangle(c .. i)
mangle(c:upper() .. i)
end
break
end
local alph = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"}
local leet = {"4","8","<","d","3","f","9","|-|","!","j","k","1","m","|\|","0","p","q","r","5","7","|_|","\/","w","><","y","2"}
local chars = {}
for c in word:gmatch(".") do
table.insert(chars,c)
end
local trans = {}
for i = 1, #chars do
for j = 1, #alph do
local split = chars[i]:gsub(alph[j],leet[j])
table.insert(trans,i,split)
end
end
try(table.concat(trans),hash)
mangle(table.concat(trans))
local new = {}
new.s = trans[1]
for i = 2, #chars do
new.s = new.s .. chars[i]
end
try(new.s,hash)
try(new.s:upper(),hash)
new.s = ""
for i = 1, #trans, 2 do
new.s = new.s .. trans[i]
if chars[i+1] then
new.s = new.s .. chars[i+1]
end
end
try(new.s,hash)
try(new.s:upper(),hash)
end
function cracker()
local list = arg[2]
checkf(list,"wordlist ")
local hash = arg[4]
if arg[3] == "-s" then
function try(word,hash)
print("trying: " .. word)
if md5.sumhexa(word) == hash then
print("match found: " .. word)
os.exit()
end
end
for l in io.lines(list) do
if wordtweak() then
tweak(l,hash)
else
try(l,hash)
end
end
elseif arg[3] == "-f" then
function try(word,hash)
print("trying: " .. hash .. ":" .. l)
if md5.sumhexa(l) == hash then
if arg[5] == "-o" and not io.open(outfile,"r") then
local o = io.open(outfile,"w")
o:write("hash:string\n")
o:close()
end
print("match found: " .. hash .. ":" .. l)
if arg[6] == "-o" then
o:write(hash .. ":" .. l .. "\n")
end
end
end
local hashfile = arg[4]
checkf(hashfile,"hashes ")
local outfile = arg[6]
local o = io.open(outfile,"a")
for hash in io.lines(hashfile) do
for l in io.lines(list) do
if wordtweak() then
tweak(l,hash)
else
try(l,hash)
end
end
end
else
err.unknown_arg(arg[3],"3 (hash cracking mode)")
end
end
function brute()
local brute = {}
function brute.argc(argx,key)
for i = 3, 20 do
if arg[i] == argx then
brute[key] = arg[i+1]
end
end
end
brute.argc("-t","timeout")
brute.argc("-o","outfile")
brute.argc("-a","alphabet")
brute.argc("-l","length")
if arg[2] == "-f" then
checkf(arg[3],"hashes ")
if brute.outfile then
local f = io.open(brute.outfile,"w")
f:write("hash:string\n")
f:close()
end
local cracks = {}
cracks.done = 0
cracks.failed = 0
for l in io.lines(arg[3]) do
local hash, cracked = force(arg[3],true,brute.timeout,brute.outfile,brute.alphabet,brute.length)
if cracked then
print("\nmatch found: " .. hash .. ":" .. cracked)
print("hashes cracked: " .. cracks.done)
print("failed cracks: " .. cracks.failed)
print("words tried: " .. #tried .. "\n")
cracks.done = cracks.done + 1
else
print("\nfailed to crack " .. hash .. "\n")
cracks.failed = cracks.failed + 1
end
end
elseif arg[2] then
local hash, cracked = force(arg[2],brute.timeout,brute.outfile,brute.alphabet,brute.length)
if cracked then
print("\nmatch found: " .. cracked)
print("words tried: " .. #tried)
else
print("\ncracking failed.")
end
else
err.few_args()
end
end
function crawler()
if (not arg[3]) or (arg[3] == "-f" and not arg[4]) or (arg[4] == "-f" and not arg[5]) or (arg[2] == "-l" and not arg[4]) then
err.few_args()
elseif arg[3] == "-f" then
checkf(arg[4],"hashes ")
elseif arg[4] == "-f" then
checkf(arg[5],"hashes ")
end
if arg[5] then
local o = io.open(arg[5],"a")
end
if arg[4] == "-o" then
os.remove(arg[5])
end
if arg[2] == "-b" then
function gen()
local w = rand(1,255)
local x = rand(1,255)
local y = rand(1,255)
local z = rand(1,255)
local ip = w .. "." .. x .. "." .. y .. "." .. z
return ip
end
elseif arg[2] == "-l" then
checkf(arg[3],arg[3] .. " ")
local host = {}
if arg[4] == "-d" then
host.domain = arg[5]
else
host.domain = ".com"
end
local rout = coroutine.create(
function()
for l in io.lines(arg[3]) do
local hostname = l .. host.domain
coroutine.yield(hostname)
end
return nil
end
)
function gen()
local bool, hostname = coroutine.resume(rout)
return hostname
end
else
err.unknown_arg(arg[2],"2 (web crawling mode)")
end
if arg[3] ~= "-f" and arg[4] ~= "-f" then
function try(w)
if md5.sumhexa(w) == arg[3] then
print("match found: " .. w)
print("hostnames tried: " .. #tried.host)
print("words tried: " .. #tried.word)
os.exit(0)
end
end
else
if arg[3] == "-f" then
checkf(arg[4],"hashes ")
elseif arg[4] == "-f" then
checkf(arg[5],"hashes ")
end
function try(w)
for l in io.lines(arg[3]) do
if md5.sumhexa(w) == l then
print("match found: " .. w)
print("hostnames tried so far: " .. #tried.host)
print("words tried so far: " .. #tried.word .. "\n")
if arg[4] == "-o" then
o:write(l .. ":" .. w .. "\n")
end
end
end
end
end
require("socket")
tried.host = {}
tried.word = {}
while true do
tried.tmp = gen()
while tried.host[tried.tmp] do tried.tmp = gen() end
local host = tried.tmp
if not host then
print("no matches found.")
print("hostnames tried: " .. #tried.host)
print("words tried: " .. #tried.word)
os.exit(0)
end
local s = socket.connect(host,80)
if s then
s:settimeout(0)
s:send("GET / HTTP/1.0\r\n\r\n")
while true do
local data, stat, part = s:receive(1024)
for w in (data or part):gmatch("%S+") do
if not tried.word[w] then
try(w)
tried.word[w] = true
tried.word[#tried.word + 1] = true
end
end
if stat == "closed" then break end
end
s:close()
tried.host[host] = true
tried.host[#tried.host + 1] = true
end
end
end
--------------------------------------------------------------------------------
-- main structure
--------------------------------------------------------------------------------
if not arg[1] or arg[1] == "--help" then
usage()
else
if arg[1] == "--about" then
about()
elseif arg[1] == "-c" then
if not arg[4] or not arg[2] then
err.few_args()
else
cracker()
end
elseif arg[1] == "-b" then
brute()
elseif arg[1] == "-h" then
print(md5.sumhexa(arg[2]))
elseif arg[1] == "-f" then
checksum()
elseif arg[1] == "-l" then
listf()
elseif arg[1] == "-w" then
crawler()
else
err.unknown_arg(arg[1],"1")
end
end[Lua] LMC - MD5 cracker - noize - 08-07-2013 LMC - Lua MD5 Cracker Latest version: 2.4 (stable) Latest stable: 2.4 Supports: Code: [*] wordlist-based attacks
[*] bruteforcing (supports hash files, timeout for single hash, custom alphabets and word length (also ranges))
[*] hash/checksum generation
[*] list (line-by-line) encryption
[*] stdout + outfile
[*] web crawling based password cracking (tries each word found on the web pages)
[*] IP bruteforcing (for web crawling)
[*] wordlist-based DNS forcing (for web crawling)See --help or --about for more information. Please, report/post any bug, suggestion or comment. Code: --------------------------------------------------------------------------------
-- LMC 2.4 --
-- (( Lua MD5 Cracker )) --
--------------------------------------------------------------------------------
-- You're allowed to edit and/or give away for free this code as whole or in --
-- part as long as you give credits. --
--------------------------------------------------------------------------------
-- LMC · coded by noize · 2013 --
--------------------------------------------------------------------------------
require("strbuf")
require("list")
require("md5")
print("")
local tried = {}
--------------------------------------------------------------------------------
-- define error functions
--------------------------------------------------------------------------------
local err = {}
function err.few_args()
print("not enough arguments.")
os.exit(2)
end
function err.readf(file)
print("error: failed to read " .. file .. "file.")
os.exit(1)
end
function err.unknown_arg(argx,n)
print("argument #" .. n .. " '" .. argx .. "' not recognized.")
os.exit(2)
end
function err.wordlen_nan()
print("error: word length must be a number.")
os.exit(2)
end
function err.unexp_dash_in_len()
print("error: unexpected dash in word length declaration.")
os.exit(2)
end
--------------------------------------------------------------------------------
-- define handling functions
--------------------------------------------------------------------------------
function rand(f,c)
math.randomseed(os.time())
math.randomseed(math.random(os.clock(),os.time()))
return math.random(f,c)
end
function generator(alphabet,length)
local gen = {}
if length then
gen.length = length
else
gen.length = "4-12"
end
if gen.length:find("%-") then
local splt = string.split(gen.length,"%-")
if not splt[2] or splt[3] then
err.unexp_dash_in_len()
else
gen.length = rand(splt[1],splt[2])
end
end
gen.length = tonumber(gen.length)
if alphabet then
gen.alphabet = {}
for w in alphabet:gmatch("%S+") do
table.insert(gen.alphabet,w)
end
else
gen.alphabet = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","1","2","3","4","5","6","7","8","9","0","!","&","-","_","."}
end
gen.pass = ""
for s = 1, gen.length do
gen.alphabet = shuffle(gen.alphabet)
gen.pass = gen.pass .. gen.alphabet[rand(1,#gen.alphabet)]
end
while tried[gen.pass] do
gen.pass = ""
for s = 1, gen.length do
gen.alphabet = shuffle(gen.alphabet)
gen.pass = gen.pass .. gen.alphabet[rand(1,#gen.alphabet)]
end
end
return gen.pass
end
function shuffle(array)
local order, res = {}, {}
for i = 1, #array do
math.randomseed(os.time() / math.random())
math.randomseed(os.time() / math.random() * os.clock())
math.randomseed(os.clock() * math.random() / os.time())
order[i] = {
rnd = math.random(),
idx = i
}
end
local f = array[1]
table.insert(array,f)
local r = math.random(1,#array)
local t = array[r]
table.remove(array,r)
table.sort(order, function(a,b) return a.rnd < b.rnd end)
table.insert(array,t)
table.remove(array,1)
for i = 1, #array do
res[i] = array[order[i].idx]
end
return res
end
function force(hash,hashfile,timeout,outfile,alphabet,length)
local t = os.clock()
function try(str,hash)
local len = {}
len.max = (tonumber(length) or length)
if type(len.max) ~= "number" then
local split = len.max:split("%-")
len.min = tonumber(split[1])
len.max = tonumber(split[2])
if not len.min or not len.max then
err.wordlen_nan()
end
end
if str:len() >= len.min and str:len() <= len.max then
print("trying: " .. hash .. ":" .. str)
if (md5.sumhexa(str) == hash) then
if outfile then
local f = io.open(outfile,"a")
f:write(hash .. ":" .. str .. "\n")
f:close()
end
return hash, str
end
end
end
while (os.clock() < t + (timeout or os.clock())) do
local str = generator(alphabet,length)
tried[str] = true
tried[#tried + 1] = true
if hashfile then
for hash in io.lines(hash) do
if wordtweak() then
tweak(str,hash)
else
try(str,hash)
end
end
else
if wordtweak() then
tweak(str,hash)
else
try(str,hash)
end
end
end
return hash, false
end
function checkf(file,error)
local f = io.open(file,"r")
if f then
f:close()
else
err.readf(error)
end
end
--------------------------------------------------------------------------------
-- define main functions
--------------------------------------------------------------------------------
function usage()
print(" ***********************************************\n")
print(" *** LMC cracker by noize ***\n")
print(" ***********************************************\n")
print(" usage: lua lmc.lua [-c | -b | -h | -f | -l | -w | --help | --about]")
print(" [wordlist | hash | -f hashfile [-t timeout] [-a alphabet]")
print(" [-l length] | string | file | list | -b | -l wordlist]")
print(" [-s hash | -f hashfile | -m | -o outfile]\n")
print(" -c cracking mode")
print(" wordlist password file to read passwords from")
print(" -m enable word mangling")
print(" -s single hash")
print(" hash hash to crack")
print(" -f read hashes from hashfile")
print(" hashfile file to read hashes to crack from")
print(" -o write cracked passwords to outfile (if omitted stdout is used)")
print(" -b bruteforcing mode")
print(" hash hash to crack")
print(" -f read hashes from hashfile")
print(" hashfile file to read hashes to crack from")
print(" -t set timeout in seconds per hash")
print(" timeout go to next hash in case the hash wasn't cracked in time")
print(" -a use custom alphabet (default is \"a b c d e f g h i j k l m n")
print(" o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 0 ! & - _ .\")")
print(" alphabet alphabet to use (characters are separated with whitespaces)")
print(" -l custom password length (default is 4-12)")
print(" length length for the password (ranges are allowed as above shown)")
print(" -m enable word mangling")
print(" -o write cracked passwords to outfile")
print(" -h hashing mode")
print(" string string to encrypt (enclosed in quotes for more words)")
print(" -f file checksum mode")
print(" file file to hash")
print(" -o write checksum to outfile (if omitted stdout is used)")
print(" -l list encryption mode")
print(" list hash file line by line")
print(" -o write output to outfile (if omitted stdout is used)")
print(" -w web spider mode")
print(" -b IP bruteforcing mode (see --about for more)")
print(" hash hash to crack")
print(" -f hashes file")
print(" hashfile file to read hashes to crack from")
print(" -o write cracked passwords to outfile (if omitted stdout is used)")
print(" -l wordlist wordlist-based DNS forcing mode (see --about for more)")
print(" hash hash to crack")
print(" -f hashes file")
print(" hashfile file to read hashes to crack from")
print(" -o write cracked passwords to outfile (if omitted stdout is used)")
print(" outfile output file (only with -o)")
print("\n examples:\n")
print(" lua lmc.lua -c wordlist.txt -s d41d8cd98f00b204e9800998ecf8427e")
print(" lua lmc.lua -c password.lst -f hashes.txt")
print(" lua lmc.lua -c wordlist.txt -f db_passwords -o success.txt")
print(" lua lmc.lua -b 9dd8b2a63b2aae4a2633d04b14141294")
print(" lua lmc.lua -b -f hashfile.txt")
print(" lua lmc.lua -b -f hash.lst -l 3 -o psw.lst")
print(" lua lmc.lua -b -f hashes.txt -t 60000 -o cracked.txt")
print(" lua lmc.lua -b -f hashes.txt -o out.txt -a \"a b c 1 2 3\" -l 2-6")
print(" lua lmc.lua -h \"a backslash escapes \\\"quotes\\\"\"")
print(" lua lmc.lua -f exeimage")
print(" lua lmc.lua -f pe.exe -o checksum.txt")
print(" lua lmc.lua -l password.lst -o hashes.lst")
print(" lua lmc.lua -w -b -f hashfile.lst")
print(" lua lmc.lua -w -l sitenames.txt 9dd8b2a63b2aae4a2633d04b14141294")
print(" lua lmc.lua -w -l wordlist.txt -f hashes.txt -o cracked.psw")
end
function about()
print("=====================\n")
print("LMC (Lua MD5 Cracker)\n")
print("=====================\n")
print("Program version: 2.4")
print("Lua version: 5.1")
print("\n=====================")
print("\nLMC offers more than just usual hash cracking:")
print("its options include:\n")
print(" [ OK ] hash generation")
print(" [ OK ] checksum generation")
print(" [ OK ] list encryption")
print(" [ OK ] bruteforcing")
print(" [ OK ] word tweaking (see notes)")
print(" [ OK ] web crawling based password cracking (see notes)")
print("\n=====================")
print("\nsupported algorithms:\n")
print("=====================\n")
print(" [ OK ] MD5")
print("\n=====================")
print("\nsupported attacks:\n")
print("=====================\n")
print(" [ OK ] bruteforce")
print(" [ OK ] wordlist-based")
print(" [ OK ] spider-based")
print("\n=====================")
print("\nnotes:\n")
print("=====================\n")
print(" - cracked passwords are output as well as saved to file when -o is used")
print(" - in web spider mode, LMC crawls through the Internet and tries all the words")
print(" it finds once (it won't try the same word more times)")
print(" the DNS names it uses on the run are generated randomly (DNS bruteforcing)")
print(" this tecnique is inspired to Deque's WikiCrawler wordlist generator")
print(" I don't believe, though, that this kind of tecnique has ever been used for")
print(" password cracking this way before")
print(" - if you use the -w option with the -f option, you'll need to manually stop")
print(" the program, 'cause it'll theorically run endlessly")
print(" - you can enable word mangling (\"-m\" option) only with a cracking option.")
print(" the following cracking methods support word mangling:")
print(" [ OK ] bruteforcing")
print(" [ OK ] wordlist cracking")
print(" [ ] web-based cracking (will come)")
print(" an example of a word picked from a list:")
print(" password")
print(" if word mangling is enabled, some of the words that will be tried include:")
print(" Password")
print(" PASSWORD")
print(" password0")
print(" password1234")
print(" password123456")
print(" p455w0rd")
print(" passwordPASSWORD")
print(" passwordpasswordpassword")
print("\n=====================")
print("\nknown bugs:\n")
print("=====================\n")
print(" - a known issue with the bruteforcing version of the mangling algorithm, is")
print(" that it does not respect the defined word-length")
print(" - for some still unknown to me reason it looks like sometimes, the")
print(" bruteforcing algorithm throws in a \"ú\" character even when it is not")
print(" present in the defined alphabet")
print(" if you've got any idea why this is happening, please, let me know")
print("\n=====================")
print("\nLMC - coded by noize\n")
print("=====================")
end
function checksum()
checkf(arg[2],"")
local f = io.open(arg[2],"r")
if arg[4] then local o = io.open(arg[4],"w") end
local checksum = md5.sumhexa(f:read("*a"))
print(checksum)
if arg[3] == "-o" then
o:write(checksum)
end
f:close()
end
function listf() -- to avoid conflicts with the required list() function
checkf(arg[2],"")
local f = io.open(arg[2],"r")
if not arg[3] == "-o" then
for l in io.lines(arg[2]) do
print(md5.sumhexa(l))
end
else
os.remove(arg[4])
local f = io.open(arg[4],"a")
for l in io.lines(arg[2]) do
f:write(md5.sumhexa(l) .. "\n")
end
end
end
function wordtweak()
for i = 2, 15 do
if arg[i] == "-m" then
return true
end
end
return false
end
function tweak(word,hash)
function mangle(m)
try(word .. m,hash)
end
mangle("")
mangle(word)
mangle(word .. word)
mangle("00")
mangle("007")
mangle("0010")
mangle("000")
mangle("0001")
mangle("12345")
mangle("123456")
for i = 0, 100 do
mangle(i)
end
for i = 1900, 2100 do
mangle(i)
end
mangle("123456")
mangle(word:lower())
mangle(word:upper())
try(word:lower(),hash)
try(word:upper(),hash)
try(word:lower() .. word:upper(),hash)
for c in word:gmatch("[^%s]") do
mangle(c)
try(c .. word,hash)
try(c:upper() .. word:ltrim(c),hash)
for i = 0, 100 do
mangle(c .. i)
mangle(c:upper() .. i)
end
break
end
local alph = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"}
local leet = {"4","8","<","d","3","f","9","|-|","!","j","k","1","m","|\|","0","p","q","r","5","7","|_|","\/","w","><","y","2"}
local chars = {}
for c in word:gmatch(".") do
table.insert(chars,c)
end
local trans = {}
for i = 1, #chars do
for j = 1, #alph do
local split = chars[i]:gsub(alph[j],leet[j])
table.insert(trans,i,split)
end
end
try(table.concat(trans),hash)
mangle(table.concat(trans))
local new = {}
new.s = trans[1]
for i = 2, #chars do
new.s = new.s .. chars[i]
end
try(new.s,hash)
try(new.s:upper(),hash)
new.s = ""
for i = 1, #trans, 2 do
new.s = new.s .. trans[i]
if chars[i+1] then
new.s = new.s .. chars[i+1]
end
end
try(new.s,hash)
try(new.s:upper(),hash)
end
function cracker()
local list = arg[2]
checkf(list,"wordlist ")
local hash = arg[4]
if arg[3] == "-s" then
function try(word,hash)
print("trying: " .. word)
if md5.sumhexa(word) == hash then
print("match found: " .. word)
os.exit()
end
end
for l in io.lines(list) do
if wordtweak() then
tweak(l,hash)
else
try(l,hash)
end
end
elseif arg[3] == "-f" then
function try(word,hash)
print("trying: " .. hash .. ":" .. l)
if md5.sumhexa(l) == hash then
if arg[5] == "-o" and not io.open(outfile,"r") then
local o = io.open(outfile,"w")
o:write("hash:string\n")
o:close()
end
print("match found: " .. hash .. ":" .. l)
if arg[6] == "-o" then
o:write(hash .. ":" .. l .. "\n")
end
end
end
local hashfile = arg[4]
checkf(hashfile,"hashes ")
local outfile = arg[6]
local o = io.open(outfile,"a")
for hash in io.lines(hashfile) do
for l in io.lines(list) do
if wordtweak() then
tweak(l,hash)
else
try(l,hash)
end
end
end
else
err.unknown_arg(arg[3],"3 (hash cracking mode)")
end
end
function brute()
local brute = {}
function brute.argc(argx,key)
for i = 3, 20 do
if arg[i] == argx then
brute[key] = arg[i+1]
end
end
end
brute.argc("-t","timeout")
brute.argc("-o","outfile")
brute.argc("-a","alphabet")
brute.argc("-l","length")
if arg[2] == "-f" then
checkf(arg[3],"hashes ")
if brute.outfile then
local f = io.open(brute.outfile,"w")
f:write("hash:string\n")
f:close()
end
local cracks = {}
cracks.done = 0
cracks.failed = 0
for l in io.lines(arg[3]) do
local hash, cracked = force(arg[3],true,brute.timeout,brute.outfile,brute.alphabet,brute.length)
if cracked then
print("\nmatch found: " .. hash .. ":" .. cracked)
print("hashes cracked: " .. cracks.done)
print("failed cracks: " .. cracks.failed)
print("words tried: " .. #tried .. "\n")
cracks.done = cracks.done + 1
else
print("\nfailed to crack " .. hash .. "\n")
cracks.failed = cracks.failed + 1
end
end
elseif arg[2] then
local hash, cracked = force(arg[2],brute.timeout,brute.outfile,brute.alphabet,brute.length)
if cracked then
print("\nmatch found: " .. cracked)
print("words tried: " .. #tried)
else
print("\ncracking failed.")
end
else
err.few_args()
end
end
function crawler()
if (not arg[3]) or (arg[3] == "-f" and not arg[4]) or (arg[4] == "-f" and not arg[5]) or (arg[2] == "-l" and not arg[4]) then
err.few_args()
elseif arg[3] == "-f" then
checkf(arg[4],"hashes ")
elseif arg[4] == "-f" then
checkf(arg[5],"hashes ")
end
if arg[5] then
local o = io.open(arg[5],"a")
end
if arg[4] == "-o" then
os.remove(arg[5])
end
if arg[2] == "-b" then
function gen()
local w = rand(1,255)
local x = rand(1,255)
local y = rand(1,255)
local z = rand(1,255)
local ip = w .. "." .. x .. "." .. y .. "." .. z
return ip
end
elseif arg[2] == "-l" then
checkf(arg[3],arg[3] .. " ")
local host = {}
if arg[4] == "-d" then
host.domain = arg[5]
else
host.domain = ".com"
end
local rout = coroutine.create(
function()
for l in io.lines(arg[3]) do
local hostname = l .. host.domain
coroutine.yield(hostname)
end
return nil
end
)
function gen()
local bool, hostname = coroutine.resume(rout)
return hostname
end
else
err.unknown_arg(arg[2],"2 (web crawling mode)")
end
if arg[3] ~= "-f" and arg[4] ~= "-f" then
function try(w)
if md5.sumhexa(w) == arg[3] then
print("match found: " .. w)
print("hostnames tried: " .. #tried.host)
print("words tried: " .. #tried.word)
os.exit(0)
end
end
else
if arg[3] == "-f" then
checkf(arg[4],"hashes ")
elseif arg[4] == "-f" then
checkf(arg[5],"hashes ")
end
function try(w)
for l in io.lines(arg[3]) do
if md5.sumhexa(w) == l then
print("match found: " .. w)
print("hostnames tried so far: " .. #tried.host)
print("words tried so far: " .. #tried.word .. "\n")
if arg[4] == "-o" then
o:write(l .. ":" .. w .. "\n")
end
end
end
end
end
require("socket")
tried.host = {}
tried.word = {}
while true do
tried.tmp = gen()
while tried.host[tried.tmp] do tried.tmp = gen() end
local host = tried.tmp
if not host then
print("no matches found.")
print("hostnames tried: " .. #tried.host)
print("words tried: " .. #tried.word)
os.exit(0)
end
local s = socket.connect(host,80)
if s then
s:settimeout(0)
s:send("GET / HTTP/1.0\r\n\r\n")
while true do
local data, stat, part = s:receive(1024)
for w in (data or part):gmatch("%S+") do
if not tried.word[w] then
try(w)
tried.word[w] = true
tried.word[#tried.word + 1] = true
end
end
if stat == "closed" then break end
end
s:close()
tried.host[host] = true
tried.host[#tried.host + 1] = true
end
end
end
--------------------------------------------------------------------------------
-- main structure
--------------------------------------------------------------------------------
if not arg[1] or arg[1] == "--help" then
usage()
else
if arg[1] == "--about" then
about()
elseif arg[1] == "-c" then
if not arg[4] or not arg[2] then
err.few_args()
else
cracker()
end
elseif arg[1] == "-b" then
brute()
elseif arg[1] == "-h" then
print(md5.sumhexa(arg[2]))
elseif arg[1] == "-f" then
checksum()
elseif arg[1] == "-l" then
listf()
elseif arg[1] == "-w" then
crawler()
else
err.unknown_arg(arg[1],"1")
end
endRE: [Lua] LMC - MD5 cracker - noize - 08-10-2013 update: version 2.0 out now. RE: [Lua] LMC - MD5 cracker - noize - 08-10-2013 update: version 2.0 out now. RE: [Lua] LMC - MD5 cracker - Deque - 08-10-2013 Nice tool and lots of useful features. But it needs polishing. A huge if-else-if pile of code is always a sign of bad smelling code. I recommend to use some functions for structuring your code and encapsulating reusable parts. RE: [Lua] LMC - MD5 cracker - Deque - 08-10-2013 Nice tool and lots of useful features. But it needs polishing. A huge if-else-if pile of code is always a sign of bad smelling code. I recommend to use some functions for structuring your code and encapsulating reusable parts. RE: [Lua] LMC - MD5 cracker - noize - 08-10-2013 (08-10-2013, 09:36 AM)Deque Wrote: Nice tool and lots of useful features. But it needs polishing. Will be done, just as I'll add the bruteforcing function, in 2.1. update: version 2.1 out now. RE: [Lua] LMC - MD5 cracker - noize - 08-10-2013 (08-10-2013, 09:36 AM)Deque Wrote: Nice tool and lots of useful features. But it needs polishing. Will be done, just as I'll add the bruteforcing function, in 2.1. update: version 2.1 out now. RE: [Lua] LMC - MD5 cracker - noize - 10-19-2013 update: 2.3 out now. RE: [Lua] LMC - MD5 cracker - noize - 10-19-2013 update: 2.3 out now. |