mirror of
https://github.com/maride/barf.git
synced 2024-12-22 14:37:29 +00:00
Add chunk support
This commit is contained in:
parent
c397b3640e
commit
31ab515a01
3
barf.py
3
barf.py
@ -41,7 +41,7 @@ def main():
|
||||
|
||||
# start the bruteforcing madness ;)
|
||||
# DisableLogging()
|
||||
Bruteforce(bm, args["knownPrefix"], args["knownSuffix"])
|
||||
Bruteforce(bm, args["knownPrefix"], args["knownSuffix"], args["chunksize"])
|
||||
|
||||
# g'night, gdb
|
||||
gdb.execute("quit")
|
||||
@ -55,6 +55,7 @@ def getArguments():
|
||||
a["winAddr"] = barf_win_addr
|
||||
a["knownPrefix"] = barf_known_prefix
|
||||
a["knownSuffix"] = barf_known_suffix
|
||||
a["chunksize"] = barf_chunksize
|
||||
return a
|
||||
|
||||
|
||||
|
8
barf.sh
8
barf.sh
@ -12,6 +12,7 @@ WINADDR=""
|
||||
KNOWNPREFIX=""
|
||||
KNOWNSUFFIX=""
|
||||
BARFPATH="$(dirname $(realpath $0))/src"
|
||||
CHUNKSIZE=1
|
||||
|
||||
# getopt is kind-of unstable across distributions and versions, so we implement it on our own
|
||||
# hat-tip to https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash
|
||||
@ -43,6 +44,10 @@ while [[ $# -gt 0 ]]; do
|
||||
KNOWNSUFFIX="$2"
|
||||
shift; shift
|
||||
;;
|
||||
-c|--chunksize)
|
||||
CHUNKSIZE="$2"
|
||||
shift; shift
|
||||
;;
|
||||
*) # unknown option - we assume it is the target literal
|
||||
TARGETFILE="$key"
|
||||
shift
|
||||
@ -70,6 +75,7 @@ if [ "$SHOWHELP" == 1 ]; then
|
||||
echo " -w | --win-addr 0xDEF042 a location reached if your input is correct"
|
||||
echo " -< | --prefix CTF{ a known prefix, e.g. the prefix of your flag"
|
||||
echo " -> | --suffix } a known suffix, e.g. the suffix of your flag"
|
||||
echo " -c | --chunksize 1 amount of characters to try at once"
|
||||
echo " -h | --help a great and useful help message, you should try it!"
|
||||
echo " ./path/to/your/crackme the path to the target to be fuzzed"
|
||||
echo "Note that you need to either specify --positive-addr or --negative-addr and your target of course."
|
||||
@ -77,5 +83,5 @@ if [ "$SHOWHELP" == 1 ]; then
|
||||
fi
|
||||
|
||||
# ready for take-off
|
||||
gdb --quiet -nx --eval-command "py barf_positive_addr='$POSITIVEADDR';barf_negative_addr='$NEGATIVEADDR';barf_win_addr='$WINADDR';barf_known_prefix='$KNOWNPREFIX';barf_known_suffix='$KNOWNSUFFIX';barf_path='$BARFPATH'" --command barf.py $TARGETFILE
|
||||
gdb --quiet -nx --eval-command "py barf_positive_addr='$POSITIVEADDR';barf_negative_addr='$NEGATIVEADDR';barf_win_addr='$WINADDR';barf_known_prefix='$KNOWNPREFIX';barf_known_suffix='$KNOWNSUFFIX';barf_path='$BARFPATH';barf_chunksize=$CHUNKSIZE" --command barf.py $TARGETFILE
|
||||
|
||||
|
BIN
examples/double-trouble
Executable file
BIN
examples/double-trouble
Executable file
Binary file not shown.
53
examples/double-trouble.c
Normal file
53
examples/double-trouble.c
Normal file
@ -0,0 +1,53 @@
|
||||
// double-trouble.c
|
||||
// ----------------
|
||||
//
|
||||
// The binary reads some chars from stdin and checks it against a hard-coded flag.
|
||||
// It checks two chars at a time, this time with a positive counter :)
|
||||
// If the entered flag is correct, a corresponding message will be printed out.
|
||||
//
|
||||
// Compile with
|
||||
// gcc -o double-trouble double-trouble.c
|
||||
//
|
||||
// Quick binary analysis
|
||||
// - load into gdb
|
||||
// - execute "start", so the binary is mapped to the final position
|
||||
// - execute "disas main"
|
||||
// Look at 0x00005555555551f5 <+160>. It moves 2 to rbp-0x4, that's the correctChars += 2 below.
|
||||
// Right after that, the i value is also increased with 2, so double-check to get the right address ;)
|
||||
// Anyway, that's the right address for --positive-address
|
||||
// Finding the win function is easy as always. We need to search for the point where puts("yay, ...") is called.
|
||||
// And that is at 0x000055555555523d!
|
||||
//
|
||||
// With the addresses identified above, we call barf with:
|
||||
// ./barf.sh --positive-addr 0x5555555551f5 --win-addr 0x55555555523d --chunksize 2 ./double-trouble
|
||||
//
|
||||
// Please note that your addresses will likely differ, e.g. if you edit the source file below.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUFSIZE 32
|
||||
|
||||
int main(int argc ,char* argv[]) {
|
||||
char buf[BUFSIZE];
|
||||
char flag[BUFSIZE] = "CTF{w3_h4ck_1n_du4l1ty!}";
|
||||
|
||||
// read flag
|
||||
fgets(buf, BUFSIZE, stdin);
|
||||
|
||||
// walk flag
|
||||
int correctChars = 0;
|
||||
int i = 0;
|
||||
while(buf[i] != '\0' && flag[i] != '\0' && i < BUFSIZE) {
|
||||
if(buf[i] == flag[i] && buf[i+1] == flag[i+1]) {
|
||||
correctChars += 2;
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
|
||||
// check flag
|
||||
if(strlen(flag) == correctChars) {
|
||||
puts("yay, that's the flag! :)");
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}_!?"
|
||||
|
||||
# bruteforces a single character, sandwiched between the known parts.
|
||||
# Returns the most promising string.
|
||||
def BruteforceChar(bm, knownPrefix, knownSuffix):
|
||||
def BruteforceChar(bm, knownPrefix, knownSuffix, chunksize):
|
||||
# keyFragment is the variable were we store our found-to-be-correct chars
|
||||
keyFragment = ""
|
||||
|
||||
@ -19,11 +19,11 @@ def BruteforceChar(bm, knownPrefix, knownSuffix):
|
||||
# the resulting score is the base for the next round of guessing, hopefully with a single solution better than the score of knownPrefix + keyFragment + impossibleChar.
|
||||
# please also note that this will massively fail if the "impossible" character is part of the flag, at the very position it was tested on ... have fun detecting that
|
||||
bm.ResetBreakpoints()
|
||||
TryInput(knownPrefix + keyFragment + "^" + knownSuffix)
|
||||
TryInput(knownPrefix + keyFragment + "^" * chunksize + knownSuffix)
|
||||
refScore = bm.PopScore()
|
||||
|
||||
# iterate over every character in the charset
|
||||
for c in charset:
|
||||
for c in generateCharset(chunksize):
|
||||
# generate full input string
|
||||
inp = knownPrefix + keyFragment + c + knownSuffix
|
||||
|
||||
@ -33,7 +33,7 @@ def BruteforceChar(bm, knownPrefix, knownSuffix):
|
||||
score = bm.PopScore()
|
||||
|
||||
# yay, that's a hit
|
||||
if score > refScore:
|
||||
if score > refScore or bm.HitWin():
|
||||
keyFragment += c
|
||||
found = True
|
||||
break
|
||||
@ -45,9 +45,9 @@ def BruteforceChar(bm, knownPrefix, knownSuffix):
|
||||
# Bruteforce calls BruteforceChar until:
|
||||
# - BruteforceChar was unable to increase the score using any character in the charset, OR
|
||||
# - the "win" breakpoint is hit :)
|
||||
def Bruteforce(bm, knownPrefix, knownSuffix):
|
||||
def Bruteforce(bm, knownPrefix, knownSuffix, chunksize):
|
||||
while True:
|
||||
res = BruteforceChar(bm, knownPrefix, knownSuffix)
|
||||
res = BruteforceChar(bm, knownPrefix, knownSuffix, chunksize)
|
||||
if res is False:
|
||||
# no character from the given charset matched. :(
|
||||
EnableLogging()
|
||||
@ -78,3 +78,11 @@ def Bruteforce(bm, knownPrefix, knownSuffix):
|
||||
return knownPrefix + knownSuffix
|
||||
|
||||
|
||||
# generateCharset returns an iteratable object (string or set) to be used by the bruteforce function.
|
||||
# the chunksize is the amount of characters to stuff into an entry
|
||||
def generateCharset(chunksize):
|
||||
c = charset
|
||||
for i in range(chunksize - 1):
|
||||
c = [ a + b for a in c for b in charset ]
|
||||
return c
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user