mirror of
				https://github.com/maride/barf.git
				synced 2025-10-10 19:06:51 +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 ;) |     # start the bruteforcing madness ;) | ||||||
|     # DisableLogging() |     # DisableLogging() | ||||||
|     Bruteforce(bm, args["knownPrefix"], args["knownSuffix"]) |     Bruteforce(bm, args["knownPrefix"], args["knownSuffix"], args["chunksize"]) | ||||||
| 
 | 
 | ||||||
|     # g'night, gdb |     # g'night, gdb | ||||||
|     gdb.execute("quit") |     gdb.execute("quit") | ||||||
| @ -55,6 +55,7 @@ def getArguments(): | |||||||
|     a["winAddr"] = barf_win_addr |     a["winAddr"] = barf_win_addr | ||||||
|     a["knownPrefix"] = barf_known_prefix |     a["knownPrefix"] = barf_known_prefix | ||||||
|     a["knownSuffix"] = barf_known_suffix |     a["knownSuffix"] = barf_known_suffix | ||||||
|  |     a["chunksize"] = barf_chunksize | ||||||
|     return a |     return a | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								barf.sh
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								barf.sh
									
									
									
									
									
								
							| @ -12,6 +12,7 @@ WINADDR="" | |||||||
| KNOWNPREFIX="" | KNOWNPREFIX="" | ||||||
| KNOWNSUFFIX="" | KNOWNSUFFIX="" | ||||||
| BARFPATH="$(dirname $(realpath $0))/src" | BARFPATH="$(dirname $(realpath $0))/src" | ||||||
|  | CHUNKSIZE=1 | ||||||
| 
 | 
 | ||||||
| # getopt is kind-of unstable across distributions and versions, so we implement it on our own | # 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 | # 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" | 		KNOWNSUFFIX="$2" | ||||||
| 		shift; shift | 		shift; shift | ||||||
| 		;; | 		;; | ||||||
|  | 		-c|--chunksize) | ||||||
|  | 		CHUNKSIZE="$2" | ||||||
|  | 		shift; shift | ||||||
|  | 		;; | ||||||
| 		*) # unknown option - we assume it is the target literal | 		*) # unknown option - we assume it is the target literal | ||||||
| 		TARGETFILE="$key" | 		TARGETFILE="$key" | ||||||
| 		shift | 		shift | ||||||
| @ -70,6 +75,7 @@ if [ "$SHOWHELP" == 1 ]; then | |||||||
| 	echo "		-w | --win-addr      0xDEF042	a location reached if your input is correct" | 	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 "		-< | --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 "		-> | --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 "		-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 "		./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." | 	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 | fi | ||||||
| 
 | 
 | ||||||
| # ready for take-off | # 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. | # bruteforces a single character, sandwiched between the known parts. | ||||||
| # Returns the most promising string. | # 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 is the variable were we store our found-to-be-correct chars | ||||||
|     keyFragment = "" |     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. |     # 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 |     # 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() |     bm.ResetBreakpoints() | ||||||
|     TryInput(knownPrefix + keyFragment + "^" + knownSuffix) |     TryInput(knownPrefix + keyFragment + "^" * chunksize + knownSuffix) | ||||||
|     refScore = bm.PopScore() |     refScore = bm.PopScore() | ||||||
| 
 | 
 | ||||||
|     # iterate over every character in the charset |     # iterate over every character in the charset | ||||||
|     for c in charset: |     for c in generateCharset(chunksize): | ||||||
|         # generate full input string |         # generate full input string | ||||||
|         inp = knownPrefix + keyFragment + c + knownSuffix |         inp = knownPrefix + keyFragment + c + knownSuffix | ||||||
| 
 | 
 | ||||||
| @ -33,7 +33,7 @@ def BruteforceChar(bm, knownPrefix, knownSuffix): | |||||||
|         score = bm.PopScore() |         score = bm.PopScore() | ||||||
|          |          | ||||||
|         # yay, that's a hit |         # yay, that's a hit | ||||||
|         if score > refScore: |         if score > refScore or bm.HitWin(): | ||||||
|             keyFragment += c |             keyFragment += c | ||||||
|             found = True |             found = True | ||||||
|             break |             break | ||||||
| @ -45,9 +45,9 @@ def BruteforceChar(bm, knownPrefix, knownSuffix): | |||||||
| # Bruteforce calls BruteforceChar until: | # Bruteforce calls BruteforceChar until: | ||||||
| # - BruteforceChar was unable to increase the score using any character in the charset, OR | # - BruteforceChar was unable to increase the score using any character in the charset, OR | ||||||
| # - the "win" breakpoint is hit :) | # - the "win" breakpoint is hit :) | ||||||
| def Bruteforce(bm, knownPrefix, knownSuffix): | def Bruteforce(bm, knownPrefix, knownSuffix, chunksize): | ||||||
|     while True: |     while True: | ||||||
|         res = BruteforceChar(bm, knownPrefix, knownSuffix) |         res = BruteforceChar(bm, knownPrefix, knownSuffix, chunksize) | ||||||
|         if res is False: |         if res is False: | ||||||
|             # no character from the given charset matched. :( |             # no character from the given charset matched. :( | ||||||
|             EnableLogging() |             EnableLogging() | ||||||
| @ -78,3 +78,11 @@ def Bruteforce(bm, knownPrefix, knownSuffix): | |||||||
|                 return 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user