find android hook

by
5 views 9cad49e5...

Description

find android hook: inline hook/got hook/java hook

How to Use

Download the script and run it with Frida CLI:

Download Script

Then run with Frida:

frida -U -f YOUR_PACKAGE_NAME -l find-android-hook.js

Replace YOUR_PACKAGE_NAME with the target app's package name.

Source Code

JavaScript
// https://codeshare.frida.re/@lichao890427/find-android-hook/edit
// Any questions submit to https://github.com/lichao890427/frida_script 

// Usage:
/*
	// Get All Modules from /proc/self/maps
	[Xiaomi MI 4LTE::com.baidu.wallet]-> getAllModules()
	{
        "path": "/data/app-lib/com.baidu.wallet-1/libbdpush_V2_7.so",
        "vmmax": "2140905472",
        "vmmin": "2140844032"
    },
    {
        "path": "/data/data/com.baidu.wallet/files/.1/dex/apkDex/1-2.4.5.dex",
        "vmmax": "2161364992",
        "vmmin": "2160836608"
    },
    {
        "path": "/data/local/tmp/re.frida.server/frida-agent-32.so",
        "vmmax": "2172952576",
        "vmmin": "2161606656"
    },
    {
        "path": "/data/data/com.baidu.wallet/files/.100015/dex/apkDex/100015-1.0.0.dex",
        "vmmax": "2189901824",
        "vmmin": "2189869056"
    }
	...................


	// Check got table hook
	[Xiaomi MI 4LTE::com.baidu.wallet]-> checkConsistency("libdvm.so", 4)
	check .got
	.got 39/349     addr:41764b28 file-mem:0-40109708 __aeabi_idiv->libc.so.__divsi3
	.got 44/349     addr:41764b3c file-mem:0-4010a2ec __aeabi_fadd->libc.so.__addsf3
	.got 45/349     addr:41764b40 file-mem:0-4010a2e8 __aeabi_fsub->libc.so.__aeabi_frsub
	.got 50/349     addr:41764b54 file-mem:0-40109864 __aeabi_dadd->libc.so.__adddf3
	.got 115/349    addr:41764c58 file-mem:1f738-40109708 __aeabi_idiv->libc.so.__divsi3
	.got 129/349    addr:41764c90 file-mem:1f738-4010a134 __aeabi_cdcmple->libc.so.__aeabi_cdcmpeq
	.got 130/349    addr:41764c94 file-mem:1f738-401521e0 __aeabi_cfcmple->libm.so.__aeabi_cfrcmple
	.got 136/349    addr:41764cac file-mem:1f738-7549c681 __android_log_print->libbaiduprotect.so.unknown
	.got 138/349    addr:41764cb4 file-mem:1f738-4013a919 _Znaj->libstdc++.so._Znwj
	.got 139/349    addr:41764cb8 file-mem:1f738-4013a927 _ZdaPv->libstdc++.so._ZdlPv
	.got 161/349    addr:41764d10 file-mem:1f738-402d461b _ZSt24__stl_throw_length_errorPKc->libstlport.so._ZSt25__stl_throw_runtime_errorPKc
	.got 190/349    addr:41764d84 file-mem:1f738-40109640 __aeabi_uidiv->libc.so.__udivsi3
	.got 228/349    addr:41764e1c file-mem:1f738-7549c691 read->libbaiduprotect.so.unknown
	.got 230/349    addr:41764e24 file-mem:1f738-71c17101 dlsym->libsechook.so._ZNK7android12SortedVectorIP6soinfoE8do_splatEPvPKvj
	.got 231/349    addr:41764e28 file-mem:1f738-71c17421 dlopen->libsechook.so._ZNK7android12SortedVectorIP6soinfoE10do_compareEPKvS5_
	.got 232/349    addr:41764e2c file-mem:1f738-400b4dad dlerror->linker._start
	.got 292/349    addr:41764f1c file-mem:1f738-71c16f05 socket->libsechook.so.__socket
	.got 334/349    addr:41764fc4 file-mem:1f738-4176ee11 _ZN4MaAcC1EiPKtib->libqc-opt.so._ZN4MaAcC2EiPKtib
	.got 338/349    addr:41764fd4 file-mem:1f738-4176ee61 _ZN4MaAcD1Ev->libqc-opt.so._ZN4MaAcD2Ev
	
	// Check inline hook
	[Xiaomi MI 4LTE::com.baidu.wallet]-> checkConsistency("libdvm.so", 2)
	check .text
	.text   addr:_Z17dvmDbgIsInterfacey+7 file-mem:14-df
	may be hook
	.text   addr:_Z18dvmDbgGetClassListPjPPy+0 file-mem:4b-f8
	may be hook
	.text   addr:_Z18dvmDbgGetClassListPjPPy+1 file-mem:15-0
	may be hook
	.text   addr:_Z18dvmDbgGetClassListPjPPy+2 file-mem:4a-f0
	may be hook
	.text   addr:_Z18dvmDbgGetClassListPjPPy+3 file-mem:7b-1
	may be hook
	.text   addr:_Z18dvmDbgGetClassListPjPPy+4 file-mem:44-73
	may be hook
	.text   addr:_Z18dvmDbgGetClassListPjPPy+5 file-mem:73-7f
	may be hook
	.text   addr:_Z18dvmDbgGetClassListPjPPy+6 file-mem:b5-7f
	may be hook
	
	// Dump elf
	[Xiaomi MI 4LTE::com.baidu.wallet]-> dumpModule("libbaiduprotect.so")
	write /sdcard/libbaiduprotect.so file->mem 2bf0->75492bf0 size:45e98
*/
var O_RDONLY = 0;
var O_WRONLY = 1;
var O_RDWR = 2;
var O_APPEND = 1024;
var O_LARGEFILE = 32768;
var O_CREAT = 64;
var S_IWUSR = 128;
var S_IRWXU = 448;
var S_IRUSR = 256;
var SEEK_SET = 0;
var SEEK_CUR = 1;
var SEEK_END = 2;

function allocStr(str) {
    return Memory.allocUtf8String(str);
}

function getStr(addr) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.readUtf8String(addr);
}

function putStr(addr, str) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.writeUtf8String(addr, str);
}

function getByteArr(addr, l) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.readByteArray(addr, l);
}

function getU8(addr) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.readU8(addr);
}

function putU8(addr, n) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.writeU8(addr, n);
}

function getU16(addr) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.readU16(addr);
}

function putU16(addr, n) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.writeU16(addr, n);
}

function getU32(addr) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.readU32(addr);
}

function putU32(addr, n) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.writeU32(addr, n);
}

function getU64(addr) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.readU64(addr);
}

function putU64(addr, n) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.writeU64(addr, n);
}

function getPt(addr) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    return Memory.readPointer(addr);
}

function putPt(addr, n) {
    if (typeof addr == "number") {
        addr = ptr(addr);
    }
    if (typeof n == "number") {
        n = ptr(n);
    }
    return Memory.writePointer(addr, n);
}

function getExportFunction(type, name, ret, args) {
    var nptr;
    nptr = Module.findExportByName(null, name);
    if (nptr === null) {
        console.log("cannot find " + name);
        return null;
    } else {
        if (type === "f") {
            var funclet = new NativeFunction(nptr, ret, args);
            if (typeof funclet === "undefined") {
                console.log("parse error " + name);
                return null;
            }
            return funclet;
        } else if (type === "d") {
            var datalet = Memory.readPointer(nptr);
            if (typeof datalet === "undefined") {
                console.log("parse error " + name);
                return null;
            }
            return datalet;
        }
    }
}

function dumpMemory(addr, length) {
    console.log(hexdump(Memory.readByteArray(addr, length), {
        offset: 0,
        length: length,
        header: true,
        ansi: true
    }));
}

wrapper_open = getExportFunction("f", "open", "int", ["pointer", "int", "int"]);
read = getExportFunction("f", "read", "int", ["int", "pointer", "int"]);
write = getExportFunction("f", "write", "int", ["int", "pointer", "int"]);
lseek = getExportFunction("f", "lseek", "int", ["int", "int", "int"]);
wrapper_errno = getExportFunction("f", "__errno", "pointer", []);
close = getExportFunction("f", "close", "int", ["int"]);
dladdr = getExportFunction("f", "dladdr", "int", ["pointer", "pointer"]);
wrapper_sscanf = getExportFunction("f", "sscanf", "int", ["pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer"]);
getpid = getExportFunction("f", "getpid", "int", []);
wrapper_popen = getExportFunction("f", "popen", "pointer", ["pointer", "pointer"]);
pclose = getExportFunction("f", "pclose", "int", ["pointer"]);
fgets = getExportFunction("f", "fgets", "pointer", ["pointer", "int", "pointer"]);

function errno() {
	return getU32(wrapper_errno());
}

function popen(command, type) {
    if (typeof command == "string") {
        command = allocStr(command);
    }
    if (typeof type == "string") {
        type = allocStr(type);
    }
    return wrapper_popen(command, type);
}

function getCommandOutput(cmd) {
    var fp = popen(cmd, "r");
    if (fp.isNull()) {
        return null;
    }
    var output = "";
    var buffer = malloc(1024);
    while (fgets(buffer, 1024, fp) > 0) {
        output += getStr(buffer);
    }
    pclose(fp);
    return output;
}

function getProcessName() {
    var fd = open("/proc/" + getpid() + "/cmdline", O_RDONLY, 0);
    if (fd == -1) {
        return "unknown";
    }
    var buffer = malloc(32);
    read(fd, buffer, 32);
    close(fd);
    return getStr(buffer);
}

function open(pathname, flags, mode) {
    if (typeof pathname == "string") {
        pathname = allocStr(pathname);
    }
    return wrapper_open(pathname, flags, mode);
}

function getFileSize(fd) {
    return lseek(fd, 0, SEEK_END);
}

function malloc(size) {
    return Memory.alloc(size);
}

function memcpy(dst, src, n) {
    return Memory.copy(dst, src, n);
}

function sscanf(buffer, format, np1, np2, np3, np4, np5, np6, np7, np8, np9, np10, np11) {
    if (typeof format == "string") {
        format = allocStr(format);
    }
    return wrapper_sscanf(buffer, format, np1, np2, np3, np4, np5, np6, np7, np8, np9, np10, np11);
}

function getSymbol(addr) {
    if (addr == 0) {
        return new Object();
    }
    var dlinfo = malloc(32);
    var npaddr = ptr(addr);
    putU64(dlinfo.add(0), 0);
    putU64(dlinfo.add(8), 0);
    putU64(dlinfo.add(16), 0);
    putU64(dlinfo.add(24), 0);
    dladdr(npaddr, dlinfo);
    var sym = new Object();
    if (Process.pointerSize == 4) {
        libnameptr = getPt(dlinfo.add(0));
        if (libnameptr.isNull()) {
            sym.libname = "unknown";
        } else {
            sym.libname = getStr(libnameptr);
        }
        funcnameptr = getPt(dlinfo.add(8));
        if (funcnameptr.isNull()) {
            sym.funcname = "unknown";
        } else {
            sym.funcname = getStr(funcnameptr);
        }
        sym.libbase = getU32(dlinfo.add(4));
        sym.funcoff = npaddr.sub(getPt(dlinfo.add(12)));
    } else {
        libnameptr = getPt(dlinfo.add(0));
        if (libnameptr.isNull()) {
            sym.libname = "unknown";
        } else {
            sym.libname = getStr(libnameptr);
        }
        funcnameptr = getPt(dlinfo.add(16));
        if (funcnameptr.isNull()) {
            sym.funcname = "unknown";
        } else {
            sym.funcname = getStr(funcnameptr);
        }
        sym.libbase = getU64(dlinfo.add(8));
        sym.funcoff = npaddr.sub(getPt(dlinfo.add(24)));
    }
    if (sym.libname == "unknown" || sym.funcname == "unknown") {
        for (var i = global_symbols.length - 1; i >= 0; i--) {
            if (addr >= global_symbols[i].address) {
                sym.libname = global_symbols[i].path;
                sym.funcname = global_symbols[i].name;
                sym.funcoff = addr - global_symbols[i].address;
                break;
            }
        }
    }
    return sym;
}

function readSmallFile(filepath) {
    var fd = open(filepath, O_RDONLY, 0);
    if (fd == -1) {
        return null;
    }
    var buffersize = 0x1000;
    var buffer = malloc(buffersize);
    lseek(fd, 0, SEEK_SET);
    var output = "";
    while (read(fd, buffer, buffersize) != 0) {
        output += getStr(buffer);
    }
    close(fd);
    return output;
}

function getAllModules() { // Some modules may hide themselves in 'solist', so we use maps instead
    var modulelines = readSmallFile("/proc/self/maps").split("\n");
    var modules = new Array();
    var buffer = malloc(512);
    for (var i = 0; i < modulelines.length; i++) {
        putStr(buffer.add(256), modulelines[i]);
        putU64(buffer.add(0), 0); // begin address
        putU64(buffer.add(8), 0); // end address
        putU64(buffer.add(16), 0); // permission
        putU64(buffer.add(24), 0); // pgoff
        putU64(buffer.add(32), 0); // major
        putU64(buffer.add(40), 0); // minor
        putU64(buffer.add(48), 0); // ino
        putU64(buffer.add(56), 0); // path
        sscanf(buffer.add(256), "%lx-%lx %c%c%c%c %llx %x:%x %lu %s", buffer.add(0), buffer.add(8), buffer.add(16), buffer.add(17), buffer.add(18), buffer.add(19), buffer.add(24), buffer.add(32), buffer.add(40), buffer.add(48), buffer.add(56));
        var vmmin = getU64(buffer.add(0));
        var vmmax = getU64(buffer.add(8));
        var path = getStr(buffer.add(56));
        if (path[0] != "/") {
            continue;
        }
        // Check exist
        var exist = false;
        for (var j = 0; j < modules.length; j++) {
            if (modules[j].path == path) {
                if (modules[j].vmmin > vmmin) {
                    modules[j].vmmin = vmmin;
                }
                if (modules[j].vmmax < vmmax) {
                    modules[j].vmmax = vmmax;
                }
                exist = true;
                break;
            }
        }
        if (!exist) {
            var module = new Object();
            module.vmmin = vmmin;
            module.vmmax = vmmax;
            module.path = path;
            modules.push(module);
        }
    }
    return modules;
}

// Export function: get all loaded module info
function checkAllModules() {
	if (modules == null) {
		modules = getAllModules();
	}
    for (var i = 0; i < modules.length; i++) {
        console.log("start:" + modules[i].vmmin.toString(16) + " end:" + modules[i].vmmax.toString(16) + " path:" + modules[i].path);
    }
}

function getModuleInfo(name) {
	if (modules == null) {
		modules = getAllModules();
	}
    for (var i = 0; i < modules.length; i++) {
        if (modules[i].path.indexOf(name) != -1) {
            console.log(i + " start:" + modules[i].vmmin.toString(16) + " end:" + modules[i].vmmax.toString(16) + " path:" + modules[i].path);
        }
    }
}

function getElfData(module) {
    if ("sections" in module) {
        return true;
    }
    var fd = open(module.path, O_RDONLY, 0);
    if (fd == -1) {
        return false;
    }
    // Read elf header
    var size_of_Elf32_Ehdr = 52;
    var off_of_Elf32_Ehdr_phoff = 28; // 4
    var off_of_Elf32_Ehdr_shoff = 32; // 4
    var off_of_Elf32_Ehdr_phentsize = 42; // 2
    var off_of_Elf32_Ehdr_phnum = 44; // 2
    var off_of_Elf32_Ehdr_shentsize = 46; // 2
    var off_of_Elf32_Ehdr_shnum = 48; // 2
    var off_of_Elf32_Ehdr_shstrndx = 50; // 2
    var size_of_Elf64_Ehdr = 64;
    var off_of_Elf64_Ehdr_phoff = 32; // 8
    var off_of_Elf64_Ehdr_shoff = 40; // 8
    var off_of_Elf64_Ehdr_phentsize = 54; // 2
    var off_of_Elf64_Ehdr_phnum = 56; // 2
    var off_of_Elf64_Ehdr_shentsize = 58; // 2
    var off_of_Elf64_Ehdr_shnum = 60; // 2
    var off_of_Elf64_Ehdr_shstrndx = 62; // 2
    // Parse Ehdr
    var ehdr = malloc(64);
    lseek(fd, 0, SEEK_SET);
    read(fd, ehdr, 64);
    var is32bit = getU8(ehdr.add(4)) != 2; // 1:32 2:64
    if (is32bit) {
        var phoff = getU32(ehdr.add(off_of_Elf32_Ehdr_phoff));
        var shoff = getU32(ehdr.add(off_of_Elf32_Ehdr_shoff));
        var phentsize = getU16(ehdr.add(off_of_Elf32_Ehdr_phentsize));
        var phnum = getU16(ehdr.add(off_of_Elf32_Ehdr_phnum));
        var shentsize = getU16(ehdr.add(off_of_Elf32_Ehdr_shentsize));
        var shnum = getU16(ehdr.add(off_of_Elf32_Ehdr_shnum));
        var shstrndx = getU16(ehdr.add(off_of_Elf32_Ehdr_shstrndx));
        var off_of_Elf_Shdr_shname = 0; // 4
        var off_of_Elf_Shdr_shaddr = 12; // 4
        var off_of_Elf_Shdr_shoffset = 16; // 4
        var off_of_Elf_Shdr_shsize = 20; // 4
    } else {
        var phoff = getU64(ehdr.add(off_of_Elf64_Ehdr_phoff));
        var shoff = getU64(ehdr.add(off_of_Elf64_Ehdr_shoff));
        var phentsize = getU16(ehdr.add(off_of_Elf64_Ehdr_phentsize));
        var phnum = getU16(ehdr.add(off_of_Elf64_Ehdr_phnum));
        var shentsize = getU16(ehdr.add(off_of_Elf64_Ehdr_shentsize));
        var shnum = getU16(ehdr.add(off_of_Elf64_Ehdr_shnum));
        var shstrndx = getU16(ehdr.add(off_of_Elf64_Ehdr_shstrndx));
        var off_of_Elf_Shdr_shname = 0; // 4
        var off_of_Elf_Shdr_shaddr = 16; // 8
        var off_of_Elf_Shdr_shoffset = 24; // 8
        var off_of_Elf_Shdr_shsize = 28; // 8
    }
    // Parse Shdr
    var shdrs = malloc(shentsize * shnum);
    lseek(fd, shoff, SEEK_SET);
    read(fd, shdrs, shentsize * shnum);
    if (is32bit) {
        shstr_offset = getU32(shdrs.add(shentsize * shstrndx + off_of_Elf_Shdr_shoffset));
        shstr_size = getU32(shdrs.add(shentsize * shstrndx + off_of_Elf_Shdr_shsize));
    } else {
        shstr_offset = getU64(shdrs.add(shentsize * shstrndx + off_of_Elf_Shdr_shoffset));
        shstr_size = getU64(shdrs.add(shentsize * shstrndx + off_of_Elf_Shdr_shsize));
    }
    var str_tbl = malloc(shstr_size);
    lseek(fd, shstr_offset, SEEK_SET);
    read(fd, str_tbl, shstr_size);
    var sections = new Array();
    for (var i = 0; i < shnum; i++) {
        if (is32bit) {
            var shname_off = getU32(shdrs.add(i * shentsize + off_of_Elf_Shdr_shname));
            var shname = getStr(str_tbl.add(shname_off));
            var shaddr = getU32(shdrs.add(i * shentsize + off_of_Elf_Shdr_shaddr));
            var shoffset = getU32(shdrs.add(i * shentsize + off_of_Elf_Shdr_shoffset));
            var shsize = getU32(shdrs.add(i * shentsize + off_of_Elf_Shdr_shsize));
        } else {
            var shname_off = getU32(shdrs.add(i * shentsize + off_of_Elf_Shdr_shname));
            var shname = getStr(str_tbl.add(shname_off));
            var shaddr = getU64(shdrs.add(i * shentsize + off_of_Elf_Shdr_shaddr));
            var shoffset = getU64(shdrs.add(i * shentsize + off_of_Elf_Shdr_shoffset));
            var shsize = getU64(shdrs.add(i * shentsize + off_of_Elf_Shdr_shsize));
        }
        if (shname == ".text" || shname == ".rodata" || shname == ".got" || shname == ".got.plt") {
            // Check item
            var section = new Object();
            section.name = shname;
            section.memaddr = shaddr + module.vmmin;
			section.memoff = shaddr;
			section.fileoff = shoffset;
            section.size = shsize;
            section.data = malloc(shsize);
            lseek(fd, shoffset, SEEK_SET);
            read(fd, section.data, shsize);
            sections.push(section);
        }
        if (shname == ".dynsym" || shname == ".dynstr" || shname == ".rel.dyn" || shname == ".rel.plt") {
            var section = new Object();
            section.size = shsize;
            section.memaddr = shaddr + module.vmmin;
			section.memoff = shaddr;
			section.fileoff = shoffset;
            module[shname] = section;
        }
    }
    if (Process.pointerSize == 4) {
        var sym_2_str = [];
        if ((".dynsym" in module) && (".dynstr" in module)) {
            for (var i = 0; i < module[".dynsym"].size / 16; i++) {
                sym_2_str.push(getStr(module[".dynstr"].memaddr + getU32(module[".dynsym"].memaddr + 16 * i)));
            }
        }
		module.sym_2_str = sym_2_str;
		var relmap = {};
        if (".rel.dyn" in module) {
			var shsize = module[".rel.dyn"].size;
			var memaddr = module[".rel.dyn"].memaddr;
			for (var j = 0; j < shsize / 8; j++) {
				var key = getU32(memaddr + j * 8);
				var val = getU32(memaddr + j * 8 + 4) >> 8;
				if (key != 0 && val != 0) {
					relmap[key] = val;
				}
			}
        }
		if (".rel.plt" in module) {
			var shsize = module[".rel.plt"].size;
			var memaddr = module[".rel.plt"].memaddr;
			for (var j = 0; j < shsize / 8; j++) {
				var key = getU32(memaddr + j * 8);
				var val = getU32(memaddr + j * 8 + 4) >> 8;
				if (key != 0 && val != 0) {
					relmap[key] = val;
				}
			}
		}
		module.dyn_2_name = relmap;
    }
    module.sections = sections;
    return true;
}

function compareMemory(module, mask) {
    for (var i = 0; i < module.sections.length; i++) {
        section = module.sections[i];
        if (section.name == ".rodata" && (mask & 1) != 0) {
            // Compare directly
            console.log("check .rodata");
            var filedata = new Uint8Array(getByteArr(section.data, section.size));
            var memdata = new Uint8Array(getByteArr(ptr(section.memaddr), section.size));
            for (var j = 0; j < section.size; j++) {
                if (filedata[j] != memdata[j]) {
                    console.log(".rodata\taddr:" + (section.memaddr + j).toString(16) + " file-mem:" + filedata[j].toString(16) + "-" + memdata[j].toString(16));
                }
            }
        } else if (section.name == ".text" && (mask & 2) != 0) {
            // Compare and get symbol
            console.log("check .text");
            var filedata = new Uint8Array(getByteArr(section.data, section.size));
            var memdata = new Uint8Array(getByteArr(ptr(section.memaddr), section.size));
            for (var j = 0; j < section.size; j++) {
                if (filedata[j] != memdata[j]) {
                    sym = getSymbol(section.memaddr + j);
                    console.log(".text\taddr:" + sym.funcname + "+" + sym.funcoff.toString(16) + " file-mem:" + filedata[j].toString(16) + "-" + memdata[j].toString(16));
                    if ((memdata[j] == 0x01 && memdata[j + 1] == 0x00 && memdata[j + 2] == 0x9f && memdata[j + 3] == 0xef) || (memdata[j] == 0xf0 && memdata[j + 1] == 0x01 && memdata[j + 2] == 0xf0 && memdata[j + 3] == 0xe7) || (memdata[j] == 0x01 && memdata[j + 1] == 0xde) || (memdata[j] == 0xf0 && memdata[j + 1] == 0xf7 && memdata[j + 2] == 0x00 && memdata[j + 3] == 0xa0) || (memdata[j] == 0x0d && memdata[j + 1] == 0x00 && memdata[j + 2] == 0x05 && memdata[j + 3] == 0x00) || (memdata[j] == 0x00 && memdata[j + 1] == 0x00 && memdata[j + 2] == 0x20 && memdata[j + 3] == 0xd4) || memdata[j] == 0xcc) {
                        console.log("software breakpoint detected!!!");
                        j = j + 4;
                    } else {
                        console.log("may be hook");
                    }
                }
            }
        } else if (section.name == ".got" && (mask & 4) != 0) {
            console.log("check .got");
            if (Process.pointerSize == 4) {
                var filedata = new Uint32Array(getByteArr(section.data, section.size));
                var memdata = new Uint32Array(getByteArr(ptr(section.memaddr), section.size));
                for (var j = 0; j < section.size / 4; j++) {
					var F = filedata[j];
					var M = memdata[j];
                    if (F + module.vmmin != M && F != M) {
                        var msym = getSymbol(M);
						var fsym = module.sym_2_str[module.dyn_2_name[section.memoff + j * 4]];
						if (msym.funcname != fsym) {
							console.log(".got " + j + "/" + section.size / 4 + "\taddr:" + (section.memaddr + j * 4).toString(16) + " file-mem:" + F.toString(16) + "-" + M.toString(16) + " " + fsym + "->" + msym.libname + "." + msym.funcname + "+" + msym.funcoff);
						}
                    }
                }
            } else {
                var filedata = new Uint32Array(getByteArr(section.data, section.size));
                var memdata = new Uint32Array(getByteArr(ptr(section.memaddr), section.size));
                for (var j = 0; j < section.size / 8; j++) {
                    var F = filedata[j * 2] * 0x100000000 + filedata[j * 2 + 1];
                    var M = memdata[j * 2] * 0x100000000 + memdata[j * 2 + 1];
                    if (F + module.vmmin != M && F != M) {
                        var msym = getSymbol(M);
						var fsym = module.sym_2_str[module.dyn_2_name[section.memoff + j * 4]];
						if (msym.funcname != fsym) {
							console.log(".got " + j + "/" + section.size / 8 + "\taddr:" + (section.memaddr + j * 8).toString(16) + " file-mem:" + F.toString(16) + "-" + M.toString(16) + " " + fsym + "->" + msym.libname + "." + msym.funcname + "+" + msym.funcoff);
						}
                    }
                }
            }
        } else if (section.name == ".got.plt" && (mask & 8) != 0) {
            console.log("check .got.plt");
            if (Process.pointerSize == 4) {
                var filedata = new Uint32Array(getByteArr(section.data, section.size));
                var memdata = new Uint32Array(getByteArr(ptr(section.memaddr), section.size));
                for (var j = 3; j < section.size / 4; j++) { // First 3 is special
					var F = filedata[j];
					var M = memdata[j];
                    if (F + module.vmmin != M && F != M) {
                        var msym = getSymbol(M);
						var fsym = module.sym_2_str[module.dyn_2_name[section.memoff + j * 4]];
						if (msym.funcname != fsym) {
							console.log(".got.plt " + j + "/" + section.size / 4 + "\taddr:" + (section.memaddr + j * 4).toString(16) + " file-mem:" + F.toString(16) + "-" + M.toString(16) + " " + fsym + "->" + msym.libname + "." + msym.funcname + "+" + msym.funcoff);
						}
                    }
                }
            } else {
                var filedata = new Uint32Array(getByteArr(section.data, section.size));
                var memdata = new Uint32Array(getByteArr(ptr(section.memaddr), section.size));
                for (var j = 0; j < section.size / 8; j++) {
                    var F = filedata[j * 2] * 0x100000000 + filedata[j * 2 + 1];
                    var M = memdata[j * 2] * 0x100000000 + memdata[j * 2 + 1];
                    if (F + module.vmmin != M && F != M) {
                        var msym = getSymbol(M);
						var fsym = module.sym_2_str[module.dyn_2_name[section.memoff + j * 4]];
						if (msym.funcname != fsym) {
							console.log(".got " + j + "/" + section.size / 8 + "\taddr:" + (section.memaddr + j * 8).toString(16) + " file-mem:" + F.toString(16) + "-" + M.toString(16) + " " + fsym + "->" + msym.libname + "." + msym.funcname + "+" + msym.funcoff);
						}
                    }
                }
            }
        }
    }
}

// Export function: check all loaded module consistence with file
/**
	nfilter : null for all modules, "libc.so" for libc.so
	mask : 0x1 for .rodata,  0x2 for .text,  0x4 for .got,  0x8 for .plt.got
*/
var global_symbols = new Array();
var modules = null;

function checkConsistency(nfilter, mask) {
    if (modules == null) {
        modules = getAllModules();
    }
    if (global_symbols.length == 0) {
        for (var i = 0; i < modules.length; i++) {
            // modules address/name/type
            var tp = modules[i].path.split("/");
            var path = tp[tp.length - 1];
            var modsym = Module.enumerateExportsSync(path);
            var modbase = new Object();
            modbase.address = modules[i].vmmin;
            modbase.name = "unknown";
            modbase.type = "modbase";
            modsym.push(modbase);
            modsym.sort(function(v1, v2) {
                return v1.address - v2.address;
            });
            for (var j = 0; j < modsym.length; j++) {
                modsym[j].path = path;
            }
            global_symbols = global_symbols.concat(modsym);
        }
    }

    for (var i = 0; i < modules.length; i++) {
        if (nfilter == null || modules[i].path.indexOf(nfilter) != -1) {
            if (getElfData(modules[i])) {
                compareMemory(modules[i], mask);
            }
        }
    }
}

function dumpModule(name) {
	if (modules == null) {
		modules = getAllModules();
	}
	var modindx = -1;
    for (var i = 0; i < modules.length; i++) {
        if (modules[i].path.indexOf(name) != -1) {
			// Get file name
			modindx = i;
			break;
        }
    }
	if (modindx != -1) {
		var filepath = modules[modindx].path;
		var tp = filepath.split("/");
		var filename = tp[tp.length - 1];
		var textindx = -1;
		var sections = null;	
		if (getElfData(modules[modindx])) {
			// Recover .text section
			sections = modules[modindx].sections;
			for (var j = 0; j < sections.length; j++) {
				if (sections[j].name == ".text") {
					textindx = j;
					break;
				}
			}
		}
		var newpath = "/sdcard/" + filename;
		getCommandOutput("cp " + filepath + " " + newpath);
		var fmodule = open(newpath, O_WRONLY, 0);
		if (textindx != -1 && fmodule != -1) {
			console.log("write " + newpath + " file->mem " + sections[textindx].fileoff.toString(16) + "->" + sections[textindx].memaddr.toString(16) + " size:" + sections[textindx].size.toString(16));
			lseek(fmodule, sections[textindx].fileoff, SEEK_SET); 
			write(fmodule, ptr(sections[textindx].memaddr), sections[textindx].size);
			close(fmodule);
		}	
	}
}


Share this script:
Twitter LinkedIn

Comments

Login or Sign up to leave a comment.
Loading comments...