From d00be623ca75f2d5ffa7a6ef1de83a761e99571a Mon Sep 17 00:00:00 2001 From: c Date: Fri, 28 May 2021 14:58:59 -0400 Subject: [PATCH 1/7] Fix findmem for Python 3 --- lldbinit.py | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/lldbinit.py b/lldbinit.py index 326f576..24baa7f 100644 --- a/lldbinit.py +++ b/lldbinit.py @@ -89,7 +89,7 @@ pass VERSION = "2.0" -BUILD = "204" +BUILD = "205" # # User configurable options @@ -1239,7 +1239,7 @@ def cmd_LoadBreakPointsRva(debugger, command, result, dict): line = line.rstrip() if not line: break - debugger.HandleCommand("breakpoint set -a " + hex(loadaddr + long(line, 16))) + debugger.HandleCommand("breakpoint set -a " + hex(loadaddr + int(line, 16))) f.close() @@ -1955,37 +1955,41 @@ def cmd_findmem(debugger, command, result, dict): process = get_process() pid = process.GetProcessID() output_data = subprocess.check_output(["/usr/bin/vmmap", "%d" % pid]) - lines = output_data.split("\n") + #print(output_data) + lines = output_data.split(b"\n") #print(lines); - #this relies on output from /usr/bin/vmmap so code is dependant on that - #only reason why it's used is for better description of regions, which is - #nice to have. If they change vmmap in the future, I'll use my version - #and that output is much easier to parse... + # this relies on output from /usr/bin/vmmap so code is dependant on that + # only reason why it's used is for better description of regions, which is + # nice to have. If they change vmmap in the future, I'll use my version + # and that output is much easier to parse... newlines = [] for x in lines: - p = re.compile("([\S\s]+)\s([\da-fA-F]{16}-[\da-fA-F]{16}|[\da-fA-F]{8}-[\da-fA-F]{8})") + #p = re.compile(b"([\S\s]+)\s([\da-fA-F]{16}-[\da-fA-F]{16}|[\da-fA-F]{8}-[\da-fA-F]{8})") + p = re.compile(b"^(\S+)\s+([\da-fA-F]{8,16}-[\da-fA-F]{8,16})") m = p.search(x) if not m: continue tmp = [] mem_name = m.group(1) mem_range = m.group(2) - #0x000000-0x000000 - mem_start = long(mem_range.split("-")[0], 16) - mem_end = long(mem_range.split("-")[1], 16) + mem_start = int(mem_range.split(b"-")[0], 16) + mem_end = int(mem_range.split(b"-")[1], 16) tmp.append(mem_name) tmp.append(mem_start) tmp.append(mem_end) newlines.append(tmp) lines = sorted(newlines, key=lambda sortnewlines: sortnewlines[1]) - #move line extraction a bit up, thus we can latter sort it, as vmmap gives - #readable pages only, and then writable pages, so it looks ugly a bit :) + # move line extraction a bit up, thus we can latter sort it, as vmmap gives + # readable pages only, and then writable pages, so it looks ugly a bit :) newlines = [] for x in lines: mem_name = x[0] mem_start= x[1] mem_end = x[2] mem_size = mem_end - mem_start + + #print ("%s %s %s" % (mem_name, mem_start, mem_end)) + #continue err = lldb.SBError() @@ -2000,7 +2004,7 @@ def cmd_findmem(debugger, command, result, dict): while True: if count == 0: return - idx = membuff.find(search_string) + idx = membuff.find(search_string.encode('utf-8')) if idx == -1: break if count != -1: @@ -2031,7 +2035,7 @@ def cmd_findmem(debugger, command, result, dict): output(" " * 8) else: output(" " * 16) - #well if somebody allocated 4GB of course offset will be to small to fit here + #well if somebody allocated 4GB of course offset will be too small to fit here #but who cares... output(" off : %.08X %s" % (off, mem_name)) print("".join(GlobalListOutput)) @@ -2077,7 +2081,7 @@ def cmd_datawin(debugger, command, result, dict): # ---------------------------------------------------------- def get_arch(): - return lldb.debugger.GetSelectedTarget().triple.split('-')[0] + return lldb.debugger.GetSelectedTarget().triple.split(b'-')[0] #return frame for stopped thread... there should be one at least... def get_frame(): @@ -2163,7 +2167,7 @@ def is_arm(): return False def get_pointer_size(): - poisz = evaluate("sizeof(long)") + poisz = evaluate("sizeof(int)") return poisz # from https://github.com/facebook/chisel/blob/master/fblldbobjcruntimehelpers.py From 8196566eef3d301bdc06b4ba2bee72c253e5463f Mon Sep 17 00:00:00 2001 From: c Date: Fri, 28 May 2021 16:46:18 -0400 Subject: [PATCH 2/7] Add max-range for findmem --- lldbinit.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lldbinit.py b/lldbinit.py index 24baa7f..917984d 100644 --- a/lldbinit.py +++ b/lldbinit.py @@ -11,6 +11,7 @@ (c) Deroko 2014, 2015, 2016 (c) fG! 2017-2020 - reverser@put.as - https://reverse.put.as +(c) unix-ninja 2021 - https://www.unix-ninja.com Available at https://github.com/gdbinit/lldbinit @@ -89,7 +90,7 @@ pass VERSION = "2.0" -BUILD = "205" +BUILD = "206" # # User configurable options @@ -174,6 +175,10 @@ crack_cmds_noret = [] modules_list = [] +# function to normalize integers for base 10 and 16 +def auto_int(x): + return int(x, 0) + def __lldb_init_module(debugger, internal_dict): ''' we can execute commands using debugger.HandleCommand which makes all output to default lldb console. With GetCommandinterpreter().HandleCommand() we can consume all output @@ -1911,6 +1916,7 @@ def cmd_findmem(debugger, command, result, dict): parser.add_argument("-q", "--qword", help="Find qword (native packing)") parser.add_argument("-f", "--file" , help="Load find pattern from file") parser.add_argument("-c", "--count", help="How many occurances to find, default is all") + parser.add_argument("--max-range", help="Do not search memory regions which start passed this range", type=auto_int) parser = parser.parse_args(arg.split()) @@ -1969,10 +1975,20 @@ def cmd_findmem(debugger, command, result, dict): m = p.search(x) if not m: continue tmp = [] + # grab our variables mem_name = m.group(1) mem_range = m.group(2) mem_start = int(mem_range.split(b"-")[0], 16) mem_end = int(mem_range.split(b"-")[1], 16) + + # make sure we are within expected search range + if parser.max_range is not None: + if mem_start > parser.max_range: + continue + if mem_end > parser.max_range: + mem_end = parser.max_range + + # store our results tmp.append(mem_name) tmp.append(mem_start) tmp.append(mem_end) From e69dece80eff8da2a17a5648e02797da2db4cfa7 Mon Sep 17 00:00:00 2001 From: c Date: Fri, 28 May 2021 16:49:43 -0400 Subject: [PATCH 3/7] Fix regression in get_arch() --- lldbinit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldbinit.py b/lldbinit.py index 917984d..dc2b085 100644 --- a/lldbinit.py +++ b/lldbinit.py @@ -2097,7 +2097,7 @@ def cmd_datawin(debugger, command, result, dict): # ---------------------------------------------------------- def get_arch(): - return lldb.debugger.GetSelectedTarget().triple.split(b'-')[0] + return lldb.debugger.GetSelectedTarget().triple.split('-')[0] #return frame for stopped thread... there should be one at least... def get_frame(): From d0378bb70c3ad225a1ee3dba730a9bb8542fe13e Mon Sep 17 00:00:00 2001 From: c Date: Sun, 30 May 2021 14:20:22 -0400 Subject: [PATCH 4/7] Fix binary pattern search and remove separate unicode switch --- lldbinit.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lldbinit.py b/lldbinit.py index dc2b085..8614b4c 100644 --- a/lldbinit.py +++ b/lldbinit.py @@ -1909,8 +1909,7 @@ def cmd_findmem(debugger, command, result, dict): arg = str(command) parser = argparse.ArgumentParser(prog="lldb") - parser.add_argument("-s", "--string", help="Search string") - parser.add_argument("-u", "--unicode", help="Search unicode string") + parser.add_argument("-s", "--string", help="Search unicode string") parser.add_argument("-b", "--binary", help="Serach binary string") parser.add_argument("-d", "--dword", help="Find dword (native packing)") parser.add_argument("-q", "--qword", help="Find qword (native packing)") @@ -1921,11 +1920,11 @@ def cmd_findmem(debugger, command, result, dict): parser = parser.parse_args(arg.split()) if parser.string is not None: - search_string = parser.string - elif parser.unicode is not None: - search_string = unicode(parser.unicode) + search_string = parser.string.encode('utf-8') elif parser.binary is not None: - search_string = parser.binary.decode("hex") + if parser.binary[0:2] == "0x": + parser.binary = parser.binary[2:] + search_string = bytes.fromhex(parser.binary) elif parser.dword is not None: dword = evaluate(parser.dword) if dword is None: @@ -2020,7 +2019,7 @@ def cmd_findmem(debugger, command, result, dict): while True: if count == 0: return - idx = membuff.find(search_string.encode('utf-8')) + idx = membuff.find(search_string) if idx == -1: break if count != -1: From 8a818649be4d7a9a6afb5b1c828fa68ee93446c2 Mon Sep 17 00:00:00 2001 From: c Date: Sun, 30 May 2021 14:37:13 -0400 Subject: [PATCH 5/7] Cleanup some comments --- lldbinit.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lldbinit.py b/lldbinit.py index 8614b4c..b190d5d 100644 --- a/lldbinit.py +++ b/lldbinit.py @@ -1960,16 +1960,16 @@ def cmd_findmem(debugger, command, result, dict): process = get_process() pid = process.GetProcessID() output_data = subprocess.check_output(["/usr/bin/vmmap", "%d" % pid]) - #print(output_data) lines = output_data.split(b"\n") - #print(lines); # this relies on output from /usr/bin/vmmap so code is dependant on that # only reason why it's used is for better description of regions, which is # nice to have. If they change vmmap in the future, I'll use my version # and that output is much easier to parse... newlines = [] for x in lines: - #p = re.compile(b"([\S\s]+)\s([\da-fA-F]{16}-[\da-fA-F]{16}|[\da-fA-F]{8}-[\da-fA-F]{8})") + # this regex creates 2 capture groups + # the first will find the first non-whitespace sequence in the row + # the second will grab any hex ranges, each between 8 and 16 characters long p = re.compile(b"^(\S+)\s+([\da-fA-F]{8,16}-[\da-fA-F]{8,16})") m = p.search(x) if not m: continue @@ -2010,8 +2010,6 @@ def cmd_findmem(debugger, command, result, dict): membuff = process.ReadMemory(mem_start, mem_size, err) if err.Success() == False: - #output(str(err)); - #result.PutCString("".join(GlobalListOutput)); continue off = 0 base_displayed = 0 @@ -2050,8 +2048,8 @@ def cmd_findmem(debugger, command, result, dict): output(" " * 8) else: output(" " * 16) - #well if somebody allocated 4GB of course offset will be too small to fit here - #but who cares... + # well if somebody allocated 4GB of course offset will be too small to fit here + # but who cares... output(" off : %.08X %s" % (off, mem_name)) print("".join(GlobalListOutput)) membuff = membuff[idx+len(search_string):] From 1228bc814bd99c85308f332e498909d9d9643050 Mon Sep 17 00:00:00 2001 From: c Date: Sun, 30 May 2021 14:39:25 -0400 Subject: [PATCH 6/7] More comment cleanup --- lldbinit.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lldbinit.py b/lldbinit.py index b190d5d..c87f272 100644 --- a/lldbinit.py +++ b/lldbinit.py @@ -2002,9 +2002,6 @@ def cmd_findmem(debugger, command, result, dict): mem_start= x[1] mem_end = x[2] mem_size = mem_end - mem_start - - #print ("%s %s %s" % (mem_name, mem_start, mem_end)) - #continue err = lldb.SBError() From d1189a34a04ba2e63b01ad95a90d48bf4e76f287 Mon Sep 17 00:00:00 2001 From: c Date: Sun, 30 May 2021 14:48:37 -0400 Subject: [PATCH 7/7] Add min-range to findmem --- lldbinit.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lldbinit.py b/lldbinit.py index c87f272..ee745e6 100644 --- a/lldbinit.py +++ b/lldbinit.py @@ -90,7 +90,7 @@ pass VERSION = "2.0" -BUILD = "206" +BUILD = "207" # # User configurable options @@ -1915,6 +1915,7 @@ def cmd_findmem(debugger, command, result, dict): parser.add_argument("-q", "--qword", help="Find qword (native packing)") parser.add_argument("-f", "--file" , help="Load find pattern from file") parser.add_argument("-c", "--count", help="How many occurances to find, default is all") + parser.add_argument("--min-range", help="Do not search memory regions which start before this range", type=auto_int) parser.add_argument("--max-range", help="Do not search memory regions which start passed this range", type=auto_int) parser = parser.parse_args(arg.split()) @@ -1981,6 +1982,11 @@ def cmd_findmem(debugger, command, result, dict): mem_end = int(mem_range.split(b"-")[1], 16) # make sure we are within expected search range + if parser.min_range is not None: + if mem_end < parser.min_range: + continue + if mem_start < parser.min_range: + mem_start = parser.min_range if parser.max_range is not None: if mem_start > parser.max_range: continue