'Search for substrings of a given string/number in memory
Args:
- start: start address (Int)
- end: end address (Int)
- search: string to search for (String)
- mem: cached memory (raw bytes)
Returns:
- list of tuple (substr(String), address(Int))'

def search_substr(self, start, end, search, mem=None):

    def substr(s1, s2):
        'Search    for    a    string    in    another    string'
        s1 = to_binary_string(s1)
        s2 = to_binary_string(s2)
        i = 1
        found = 0
        while (i <= len(s1)):
            if (s2.find(s1[:i]) != (-1)):
                found = 1
                i += 1
                if (s1[:(i - 1)][(-1):] == '\x00'):
                    break
            else:
                break
        if (found == 1):
            return (i - 1)
        else:
            return (-1)
    result = []
    if (end < start):
        (start, end) = (end, start)
    if (mem is None):
        mem = self.dumpmem(start, end)
    if (search[:2] == '0x'):
        search = search[2:]
        if ((len(search) % 2) != 0):
            search = ('0' + search)
        search = codecs.decode(search, 'hex')[::(-1)]
    search = to_binary_string(decode_string_escape(search))
    while search:
        l = len(search)
        i = substr(search, mem)
        if (i != (-1)):
            sub = search[:i]
            addr = (start + mem.find(sub))
            if (not check_badchars(addr)):
                result.append((sub, addr))
        else:
            result.append((search, (-1)))
            return result
        search = search[i:]
    return result
