function hook_socket(){ Java.perform(function(){ console.log("hook_socket;")
Java.use("java.net.SocketOutputStream").write.overload('[B', 'int', 'int').implementation = function(bytearry,int1,int2){ var result = this.write(bytearry,int1,int2); console.log("HTTP write result,bytearry,int1,int2=>",result,bytearry,int1,int2) var ByteString = Java.use("com.android.okhttp.okio.ByteString"); console.log("bytearray contents=>", ByteString.of(bytearry).hex()) return result; }
Java.use("java.net.SocketInputStream").read.overload('[B', 'int', 'int').implementation = function(bytearry,int1,int2){ var result = this.read(bytearry,int1,int2); console.log("HTTP read result,bytearry,int1,int2=>",result,bytearry,int1,int2) var ByteString = Java.use("com.android.okhttp.okio.ByteString"); console.log("bytearray contents=>", ByteString.of(bytearry).hex()) return result; }
}) }
function hook_SSLsocketandroid8(){ Java.perform(function(){ console.log("hook_SSLsocket") Java.use("com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLOutputStream").write.overload('[B', 'int', 'int').implementation = function(bytearry,int1,int2){ var result = this.write(bytearry,int1,int2); console.log("HTTPS write result,bytearry,int1,int2=>",result,bytearry,int1,int2) var ByteString = Java.use("com.android.okhttp.okio.ByteString"); console.log("bytearray contents=>", ByteString.of(bytearry).hex()) return result; }
Java.use("com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream").read.overload('[B', 'int', 'int').implementation = function(bytearry,int1,int2){ var result = this.read(bytearry,int1,int2); console.log("HTTPS read result,bytearry,int1,int2=>",result,bytearry,int1,int2) var ByteString = Java.use("com.android.okhttp.okio.ByteString"); console.log("bytearray contents=>", ByteString.of(bytearry).hex()) return result; }
}) }
function hook_SSLsocket2android10(){ Java.perform(function(){ console.log(" hook_SSLsocket2") var ByteString = Java.use("com.android.okhttp.okio.ByteString"); Java.use("com.android.org.conscrypt.NativeCrypto").SSL_write.implementation = function(long,NS,fd,NC,bytearray,int1,int2,int3){ var result = this .SSL_write(long,NS,fd,NC,bytearray,int1,int2,int3); console.log("SSL_write(long,NS,fd,NC,bytearray,int1,int2,int3),result=>",long,NS,fd,NC,bytearray,int1,int2,int3,result) console.log(ByteString.of(bytearray).hex()); return result; } Java.use("com.android.org.conscrypt.NativeCrypto").SSL_read.implementation = function(long,NS,fd,NC,bytearray,int1,int2,int3){ var result = this .SSL_read(long,NS,fd,NC,bytearray,int1,int2,int3); console.log("SSL_read(long,NS,fd,NC,bytearray,int1,int2,int3),result=>",long,NS,fd,NC,bytearray,int1,int2,int3,result) console.log(ByteString.of(bytearray).hex()); return result; } }) }
function main(){ console.log("Main") hook_socket(); hook_SSLsocketandroid8(); //hook_SSLsocket2android10(); } setImmediate(main)
function hook_KeyStore_load() { Java.perform(function () { var StringClass = Java.use("java.lang.String"); var KeyStore = Java.use("java.security.KeyStore"); KeyStore.load.overload('java.security.KeyStore$LoadStoreParameter').implementation = function (arg0) { console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
使用Trace based profiling,登录后停止方法剖析,搜索HttpURLConnection
趣充
adb install -r -t quchong.apk
./charles 启动charles抓包注册获取验证码,设置了no proxy防抓包
服务器校验客户端证书 : 400 No required SSL certificate was sent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
function replaceKill(){ // 替换掉崩掉时的内容,打印崩掉时的参数和pid,不执行崩掉的逻辑,让程序不要崩 console.log("Preventing from killing ...") var kill_addr = Module.findExportByName("libc.so", "kill"); // var kill = new NativeFunction(kill_addr,"int",['int','int']); Interceptor.replace(kill_addr,new NativeCallback(function(arg0,arg1){ console.log("arg0=> ",arg0) console.log("arg1=> ",arg1)
},"int",['int','int'])) }
function main(){ replaceKill() } setImmediate(main);
//过客户端校验服务器 function hook_KeyStore_load() { // hook证书 自吐证书密码和内容保存在sdcard中 Java.perform(function () { var ByteString = Java.use("com.android.okhttp.okio.ByteString"); var myArray=new Array(1024); var i = 0 for (i = 0; i myArray.length; i++) { myArray[i]= 0x0; } var buffer = Java.array('byte',myArray); var StringClass = Java.use("java.lang.String"); var KeyStore = Java.use("java.security.KeyStore"); KeyStore.load.overload('java.security.KeyStore$LoadStoreParameter').implementation = function (arg0) { console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
证书绑定校验失败:Client closed the connection before a request was made.Possibly the SSL certificate was rejected.You may need to configure your browser or application to trust the Charles Root Certificate.See SSL Proxyinf in the Help menu.
# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.
"""Decrypts and logs a process's SSL traffic. Hooks the functions SSL_read() and SSL_write() in a given process and logs the decrypted data to the console and/or to a pcap file. Typical usage example: ssl_log("wget", "log.pcap", True) Dependencies: frida (https://www.frida.re/): sudo pip install frida hexdump (https://bitbucket.org/techtonik/hexdump/) if using verbose output: sudo pip install hexdump """
def show_banner(): colors = ['bright_red', 'bright_green', 'bright_blue', 'cyan', 'magenta'] try: click.style('color test', fg='bright_red') except: colors = ['red', 'green', 'blue', 'cyan', 'magenta'] try: columns = get_terminal_size().columns if columns >= len(banner.splitlines()[1]): for line in banner.splitlines(): click.secho(line, fg=random.choice(colors)) except: pass
# ssl_session[<SSL_SESSION id>] = (<bytes sent by client>, # <bytes sent by server>) ssl_sessions = {}
def ssl_log(process, pcap=None, host=False, verbose=False, isUsb=False, ssllib="", isSpawn=True, wait=0): """Decrypts and logs a process's SSL traffic. Hooks the functions SSL_read() and SSL_write() in a given process and logs the decrypted data to the console and/or to a pcap file. Args: process: The target process's name (as a string) or process ID (as an int). pcap: The file path to which the pcap file should be written. verbose: If True, log the decrypted traffic to the console. Raises: NotImplementedError: Not running on a Linux or macOS system. """
# if platform.system() not in ("Darwin", "Linux"): # raise NotImplementedError("This function is only implemented for Linux and " # "macOS systems.")
def log_pcap(pcap_file, ssl_session_id, function, src_addr, src_port, dst_addr, dst_port, data): """Writes the captured data to a pcap file. Args: pcap_file: The opened pcap file. ssl_session_id: The SSL session ID for the communication. function: The function that was intercepted ("SSL_read" or "SSL_write"). src_addr: The source address of the logged packet. src_port: The source port of the logged packet. dst_addr: The destination address of the logged packet. dst_port: The destination port of the logged packet. data: The decrypted packet data. """ t = time.time()
if ssl_session_id not in ssl_sessions: ssl_sessions[ssl_session_id] = (random.randint(0, 0xFFFFFFFF), random.randint(0, 0xFFFFFFFF)) client_sent, server_sent = ssl_sessions[ssl_session_id]
if function == "SSL_read": seq, ack = (server_sent, client_sent) else: seq, ack = (client_sent, server_sent)
for writes in ( # PCAP record (packet) header ("=I", int(t)), # Timestamp seconds ("=I", int((t * 1000000) % 1000000)), # Timestamp microseconds ("=I", 40 + len(data)), # Number of octets saved ("=i", 40 + len(data)), # Actual length of packet # IPv4 header (">B", 0x45), # Version and Header Length (">B", 0), # Type of Service (">H", 40 + len(data)), # Total Length (">H", 0), # Identification (">H", 0x4000), # Flags and Fragment Offset (">B", 0xFF), # Time to Live (">B", 6), # Protocol (">H", 0), # Header Checksum (">I", src_addr), # Source Address (">I", dst_addr), # Destination Address # TCP header (">H", src_port), # Source Port (">H", dst_port), # Destination Port (">I", seq), # Sequence Number (">I", ack), # Acknowledgment Number (">H", 0x5018), # Header Length and Flags (">H", 0xFFFF), # Window Size (">H", 0), # Checksum (">H", 0)): # Urgent Pointer pcap_file.write(struct.pack(writes[0], writes[1])) pcap_file.write(data)
if function == "SSL_read": server_sent += len(data) else: client_sent += len(data) ssl_sessions[ssl_session_id] = (client_sent, server_sent)
def on_message(message, data): """Callback for errors and messages sent from Frida-injected JavaScript. Logs captured packet data received from JavaScript to the console and/or a pcap file. See https://www.frida.re/docs/messages/ for more detail on Frida's messages. Args: message: A dictionary containing the message "type" and other fields dependent on message type. data: The string of captured decrypted data. """ if message["type"] == "error": pprint.pprint(message) os.kill(os.getpid(), signal.SIGTERM) return if len(data) == 1: print(message["payload"]["function"]) print(message["payload"]["stack"]) return p = message["payload"] if verbose: src_addr = socket.inet_ntop(socket.AF_INET, struct.pack(">I", p["src_addr"])) dst_addr = socket.inet_ntop(socket.AF_INET, struct.pack(">I", p["dst_addr"])) print("SSL Session: " + p["ssl_session_id"]) print("[%s] %s:%d --> %s:%d" % ( p["function"], src_addr, p["src_port"], dst_addr, p["dst_port"])) hexdump.hexdump(data) print(p["stack"]) if pcap: log_pcap(pcap_file, p["ssl_session_id"], p["function"], p["src_addr"], p["src_port"], p["dst_addr"], p["dst_port"], data)
if isSpawn: pid = device.spawn([process]) time.sleep(1) session = device.attach(pid) time.sleep(1) device.resume(pid) else: print("attach") session = device.attach(process) if wait > 0: print("wait for {} seconds".format(wait)) time.sleep(wait)
# session = frida.attach(process)
# pid = device.spawn([process]) # pid = process # session = device.attach(pid) # device.resume(pid) if pcap: pcap_file = open(pcap, "wb", 0) for writes in ( ("=I", 0xa1b2c3d4), # Magic number ("=H", 2), # Major version number ("=H", 4), # Minor version number ("=i", time.timezone), # GMT to local correction ("=I", 0), # Accuracy of timestamps ("=I", 65535), # Max length of captured packets ("=I", 228)): # Data link type (LINKTYPE_IPV4) pcap_file.write(struct.pack(writes[0], writes[1]))
with open("./script.js", encoding="utf-8") as f: _FRIDA_SCRIPT = f.read() # _FRIDA_SCRIPT = session.create_script(content) # print(_FRIDA_SCRIPT) script = session.create_script(_FRIDA_SCRIPT) script.on("message", on_message) script.load()
if ssllib != "": script.exports.setssllib(ssllib)
print("Press Ctrl+C to stop logging.")
def stoplog(signum, frame): print('You have stoped logging.') session.detach() if pcap: pcap_file.flush() pcap_file.close() exit() signal.signal(signal.SIGINT, stoplog) signal.signal(signal.SIGTERM, stoplog) sys.stdin.read()
if __name__ == "__main__": show_banner() class ArgParser(argparse.ArgumentParser):
var addresses = {}; var SSL_get_fd = null; var SSL_get_session = null; var SSL_SESSION_get_id = null; var getpeername = null; var getsockname = null; var ntohs = null; var ntohl = null; var SSLstackwrite = null; var SSLstackread = null;
var libname = "*libssl*";
function uuid(len, radix) { var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); var uuid = [], i; radix = radix || chars.length;
if (len) { // Compact form for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]; } else { // rfc4122, version 4 form var r;
// Fill in random data. At i==19 set the high bits of clock sequence as // per rfc4122, sec. 4.1.5 for (i = 0; i < 36; i++) { if (!uuid[i]) { r = 0 | Math.random() * 16; uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]; } } }
return uuid.join(''); } function return_zero(args) { return 0; } function initializeGlobals() { var resolver = new ApiResolver("module"); var exps = [ [Process.platform == "darwin" ? "*libboringssl*" : "*libssl*", ["SSL_read", "SSL_write", "SSL_get_fd", "SSL_get_session", "SSL_SESSION_get_id"]], // for ios and Android [Process.platform == "darwin" ? "*libsystem*" : "*libc*", ["getpeername", "getsockname", "ntohs", "ntohl"]] ]; // console.log(exps) for (var i = 0; i < exps.length; i++) { var lib = exps[i][0]; var names = exps[i][1]; for (var j = 0; j < names.length; j++) { var name = names[j]; // console.log("exports:" + lib + "!" + name) var matches = resolver.enumerateMatchesSync("exports:" + lib + "!" + name); if (matches.length == 0) { if (name == "SSL_get_fd") { addresses["SSL_get_fd"] = 0; continue; } throw "Could not find " + lib + "!" + name; } else if (matches.length != 1) { // Sometimes Frida returns duplicates. var address = 0; var s = ""; var duplicates_only = true; for (var k = 0; k < matches.length; k++) { if (s.length != 0) { s += ", "; } s += matches[k].name + "@" + matches[k].address; if (address == 0) { address = matches[k].address; } else if (!address.equals(matches[k].address)) { duplicates_only = false; } } if (!duplicates_only) { throw "More than one match found for " + lib + "!" + name + ": " + s; } } addresses[name] = matches[0].address; } } if (addresses["SSL_get_fd"] == 0) { SSL_get_fd = return_zero; } else { SSL_get_fd = new NativeFunction(addresses["SSL_get_fd"], "int", ["pointer"]); } SSL_get_session = new NativeFunction(addresses["SSL_get_session"], "pointer", ["pointer"]); SSL_SESSION_get_id = new NativeFunction(addresses["SSL_SESSION_get_id"], "pointer", ["pointer", "pointer"]); getpeername = new NativeFunction(addresses["getpeername"], "int", ["int", "pointer", "pointer"]); getsockname = new NativeFunction(addresses["getsockname"], "int", ["int", "pointer", "pointer"]); ntohs = new NativeFunction(addresses["ntohs"], "uint16", ["uint16"]); ntohl = new NativeFunction(addresses["ntohl"], "uint32", ["uint32"]); } initializeGlobals();
function ipToNumber(ip) { var num = 0; if (ip == "") { return num; } var aNum = ip.split("."); if (aNum.length != 4) { return num; } num += parseInt(aNum[0]) << 0; num += parseInt(aNum[1]) << 8; num += parseInt(aNum[2]) << 16; num += parseInt(aNum[3]) << 24; num = num >>> 0;//这个很关键,不然可能会出现负数的情况 return num; }
/** * Returns a dictionary of a sockfd's "src_addr", "src_port", "dst_addr", and * "dst_port". * @param {int} sockfd The file descriptor of the socket to inspect. * @param {boolean} isRead If true, the context is an SSL_read call. If * false, the context is an SSL_write call. * @return {dict} Dictionary of sockfd's "src_addr", "src_port", "dst_addr", * and "dst_port". */ function getPortsAndAddresses(sockfd, isRead) { var message = {}; var src_dst = ["src", "dst"]; for (var i = 0; i < src_dst.length; i++) { if ((src_dst[i] == "src") ^ isRead) { var sockAddr = Socket.localAddress(sockfd) } else { var sockAddr = Socket.peerAddress(sockfd) } if (sockAddr == null) { // 网络超时or其他原因可能导致socket被关闭 message[src_dst[i] + "_port"] = 0 message[src_dst[i] + "_addr"] = 0 } else { message[src_dst[i] + "_port"] = (sockAddr.port & 0xFFFF) message[src_dst[i] + "_addr"] = ntohl(ipToNumber(sockAddr.ip.split(":").pop())) } } return message; } /** * Get the session_id of SSL object and return it as a hex string. * @param {!NativePointer} ssl A pointer to an SSL object. * @return {dict} A string representing the session_id of the SSL object's * SSL_SESSION. For example, * "59FD71B7B90202F359D89E66AE4E61247954E28431F6C6AC46625D472FF76336". */ function getSslSessionId(ssl) { var session = SSL_get_session(ssl); if (session == 0) { return 0; } var len = Memory.alloc(4); var p = SSL_SESSION_get_id(session, len); len = Memory.readU32(len); var session_id = ""; for (var i = 0; i < len; i++) { // Read a byte, convert it to a hex string (0xAB ==> "AB"), and append // it to session_id. session_id += ("0" + Memory.readU8(p.add(i)).toString(16).toUpperCase()).substr(-2); } return session_id; }
function LogPrint(log) { var theDate = new Date(); var hour = theDate.getHours(); var minute = theDate.getMinutes(); var second = theDate.getSeconds(); var mSecond = theDate.getMilliseconds();
212 public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException { 213 final int bytesSent; 214 final int position = buffer.position(); 215 216 if (buffer.isDirect()) { 217 bytesSent = sendtoBytes(fd, buffer, position, buffer.remaining(), flags, inetAddress, port); 218 } else { 219 bytesSent = sendtoBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining(), flags, inetAddress, port); 220 } 221 222 maybeUpdateBufferPosition(buffer, position, bytesSent); 223 return bytesSent; 224 }
1 2
232 private native int sendtoBytes(FileDescriptor fd, Object buffer, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException; 233 private native int sendtoBytes(FileDescriptor fd, Object buffer, int byteOffset, int byteCount, int flags, SocketAddress address) throws ErrnoException, SocketException;
function LogPrint(log) { var theDate = new Date(); var hour = theDate.getHours(); var minute = theDate.getMinutes(); var second = theDate.getSeconds(); var mSecond = theDate.getMilliseconds();
public int read(byte[] buf, int offset, int byteCount)
1 2 3 4
1030 public static native int SSL_read(long sslNativePointer, 1031 FileDescriptor fd, 1032 SSLHandshakeCallbacks shc, 1033 byte[] b, int off, int len, int readTimeoutMillis)
function hookssl2() { Java.perform(function () { var SSLInputStreamClass = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream'); SSLInputStreamClass.read.overload('[B','int','int').implementation = function (arg0, arg1, arg2) { // 获取内部类 var SSLInputStreamObj=this; var OpenSSLSocketImplobj = this.this.$0.value; var socketobj = OpenSSLSocketImplobj.socket.value; var size = this.SSL_read(arg0, arg1, arg2); var bytearray = Java.array('byte',arg0); var content = ""; for(var i=0;i<size;i++) { content=content+String.fromCharCode(bytearray[i]) } console.log("\naddress:"+"socketobj"+"-----[" + Process.getCurrentThreadId() +"]SSLInputStreamClass receive content:"+content); printJavaStack('SSLInputStreamClass.read') return size; } var SSLOutputStreamClass = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream'); SSLOutputStreamClass.write.overload('[B','int','int').implementation = function (arg0, arg1, arg2) { var SSLOutputStreamObj=this; var OpenSSLSocketImplobj = this.this.$0.value; var socketobj = OpenSSLSocketImplobj.socket.value; var result = this.write(arg0, arg1, arg2); var bytearray = Java.array('byte', arg0); var content = ''; for (var i = 0; i < arg2; i++) {
function LogPrint(log) { var theDate = new Date(); var hour = theDate.getHours(); var minute = theDate.getMinutes(); var second = theDate.getSeconds(); var mSecond = theDate.getMilliseconds();
function printNativeStack(context, name) { //Debug. var array = Thread.backtrace(context, Backtracer.ACCURATE); var first = DebugSymbol.fromAddress(array[0]); if (first.toString().indexOf('libopenjdk.so!NET_Send') < 0) { var trace = Thread.backtrace(context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n"); LogPrint("-----------start:" + name + "--------------"); LogPrint(trace); LogPrint("-----------end:" + name + "--------------"); }
}
function printJavaStack(name) { Java.perform(function () { var Exception = Java.use("java.lang.Exception"); var ins = Exception.$new("Exception"); var straces = ins.getStackTrace(); if (straces != undefined && straces != null) { var strace = straces.toString(); var replaceStr = strace.replace(/,/g, " \n "); LogPrint("=============================" + name + " Stack strat======================="); LogPrint(replaceStr); LogPrint("=============================" + name + " Stack end======================= \n "); Exception.$dispose(); } }); }
function isprintable(value) { if (value >= 32 && value <= 126) { return true; } return false; }
function getsocketdetail(fd) { var result = ""; var type = Socket.type(fd); if (type != null) { result = result + "type:" + type; var peer = Socket.peerAddress(fd); var local = Socket.localAddress(fd); result = result + ",address:" + JSON.stringify(peer) + ",local:" + JSON.stringify(local); } else { result = "unknown"; } return result;
}
function hooklibc() { var libcmodule = Process.getModuleByName("libc.so"); var recvfrom_addr = libcmodule.getExportByName("recvfrom"); var sendto_addr = libcmodule.getExportByName("sendto"); console.log(recvfrom_addr + "---" + sendto_addr); //ssize_t recvfrom(int fd, void *buf, size_t n, int flags, struct sockaddr *addr, socklen_t *addr_len) Interceptor.attach(recvfrom_addr, { onEnter: function (args) { this.arg0 = args[0]; this.arg1 = args[1]; this.arg2 = args[2];
LogPrint("go into libc.so->recvfom");
printNativeStack(this.context, "recvfom"); }, onLeave(retval) { var size = retval.toInt32(); if (size > 0) { var result = getsocketdetail(this.arg0.toInt32()); console.log(result + "---libc.so->recvfrom:" + hexdump(this.arg1, { length: size })); }
LogPrint("leave libc.so->recvfom"); } }); //ssize_t sendto(int fd, const void *buf, size_t n, int flags, const struct sockaddr *addr, socklen_t addr_len) Interceptor.attach(sendto_addr, { onEnter: function (args) { this.arg0 = args[0]; this.arg1 = args[1]; this.arg2 = args[2]; LogPrint("go into libc.so->sendto"); printNativeStack(this.context, "sendto"); }, onLeave(retval) { var size = ptr(this.arg2).toInt32(); if (size > 0) { var result = getsocketdetail(this.arg0.toInt32()); console.log(result + "---libc.so->sendto:" + hexdump(this.arg1, { length: size })); }
function LogPrint(log) { var theDate = new Date(); var hour = theDate.getHours(); var minute = theDate.getMinutes(); var second = theDate.getSeconds(); var mSecond = theDate.getMilliseconds();
function printNativeStack(context, name) { //Debug. var array = Thread.backtrace(context, Backtracer.ACCURATE); var first = DebugSymbol.fromAddress(array[0]); if (first.toString().indexOf('libopenjdk.so!NET_Send') < 0) { var trace = Thread.backtrace(context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n");// Backtracer.FUZZY LogPrint("-----------start:" + name + "--------------"); LogPrint(trace); LogPrint("-----------end:" + name + "--------------"); }
}
function printJavaStack(name) { Java.perform(function () { var Exception = Java.use("java.lang.Exception"); var ins = Exception.$new("Exception"); var straces = ins.getStackTrace(); if (straces != undefined && straces != null) { var strace = straces.toString(); var replaceStr = strace.replace(/,/g, " \n "); LogPrint("=============================" + name + " Stack strat======================="); LogPrint(replaceStr); LogPrint("=============================" + name + " Stack end======================= \n "); Exception.$dispose(); } }); }
function isprintable(value) { if (value >= 32 && value <= 126) { return true; } return false; }
function getsocketdetail(fd) { var result = ""; var type = Socket.type(fd); if (type != null) { result = result + "type:" + type; var peer = Socket.peerAddress(fd); var local = Socket.localAddress(fd); result = result + ",address:" + JSON.stringify(peer) + ",local:" + JSON.stringify(local); } else { result = "unknown"; } return result;
}
function getip(ip_ptr) { var result = ptr(ip_ptr).readU8() + "." + ptr(ip_ptr.add(1)).readU8() + "." + ptr(ip_ptr.add(2)).readU8() + "." + ptr(ip_ptr.add(3)).readU8() return result; }
function getudpaddr(addrptr) { var port_ptr = addrptr.add(2); var port = ptr(port_ptr).readU8() * 256 + ptr(port_ptr.add(1)).readU8(); var ip_ptr = addrptr.add(4); var ip_addr = getip(ip_ptr); return "peer:"+ip_addr+"--port:"+port; }
function hooklibc() { var libcmodule = Process.getModuleByName("libc.so"); var recvfrom_addr = libcmodule.getExportByName("recvfrom"); var sendto_addr = libcmodule.getExportByName("sendto"); console.log(recvfrom_addr + "---" + sendto_addr); //ssize_t recvfrom(int fd, void *buf, size_t n, int flags, struct sockaddr *addr, socklen_t *addr_len) Interceptor.attach(recvfrom_addr, { onEnter: function (args) { this.arg0 = args[0]; this.arg1 = args[1]; this.arg2 = args[2]; this.arg3 = args[3]; this.arg4 = args[4]; this.arg5 = args[5]; LogPrint("go into libc.so->recvfom");
printNativeStack(this.context, "recvfom"); }, onLeave(retval) { var size = retval.toInt32(); if (size > 0) { var result = getsocketdetail(this.arg0.toInt32()); if (result.indexOf('udp') >= 0) { /*75struct sockaddr_in { 76 short sin_family; 77 u_short sin_port; 78 struct in_addr sin_addr; 79 char sin_zero[8]; 80};*/ var sockaddr_in_ptr = this.arg4; var sizeofsockaddr_in = this.arg5;