现有抓包方式总结
可能有读者并不清楚TCP/IP四层模型,这里做个非常精简的介绍,一般而言:
我们在谈论MAC地址/ARP的时候,我们聊的就是链路层;
我们在谈论IP地址/路由器的时候,我们聊的就是网络层;
我们在谈论连接某个端口的时候,我们聊的就是传输层;
我们在谈论发送数据的内容的时候,我们聊的就是应用层;
应用层/Application:基于中间人的HTTP(S)抓包
传输层/Transport:App使用纯Socket通信
网络层/Network:一般而言鲜有App可以更改设备的IP地址
应用层抓包通杀脚本
1. App在开发过程中,以App自己的权限,可以用代码实现到的最底层为传输层,也就用Socket接口,进行纯二进制的收发包,此处包括Java层和Native层。
2. 除了少数开发实力雄厚甚至过剩的大厂,掌握着纯二进制收发包的传输层创新、或者自定义协议的技术之外,占绝对数量**绝大多数**的App厂商采用的还是传统的HTTP/SSL方案。
[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"]]
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)
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)
if (Java.available) {
Java.perform(function () {
Java.use("java.net.SocketOutputStream").socketWrite0.overload('java.io.FileDescriptor', '[B', 'int', 'int').implementation = function (fd, bytearry, offset, byteCount) {
var result = this.socketWrite0(fd, bytearry, offset, byteCount);
var message = {};
message["function"] = "HTTP_send";
message["ssl_session_id"] = "";
message["src_addr"] = ntohl(ipToNumber((this.socket.value.getLocalAddress().toString().split(":")[0]).split("/").pop()));
message["src_port"] = parseInt(this.socket.value.getLocalPort().toString());
message["dst_addr"] = ntohl(ipToNumber((this.socket.value.getRemoteSocketAddress().toString().split(":")[0]).split("/").pop()));
message["dst_port"] = parseInt(this.socket.value.getRemoteSocketAddress().toString().split(":").pop());
var ptr = Memory.alloc(byteCount);
for (var i = 0; i < byteCount; ++i)
Memory.writeS8(ptr.add(i), bytearry[offset + i]);
send(message, Memory.readByteArray(ptr, byteCount))
return result;
}
Java.use("java.net.SocketInputStream").socketRead0.overload('java.io.FileDescriptor', '[B', 'int', 'int', 'int').implementation = function (fd, bytearry, offset, byteCount, timeout) {
var result = this.socketRead0(fd, bytearry, offset, byteCount, timeout);
var message = {};
message["function"] = "HTTP_recv";
message["ssl_session_id"] = "";
message["src_addr"] = ntohl(ipToNumber((this.socket.value.getRemoteSocketAddress().toString().split(":")[0]).split("/").pop()));
message["src_port"] = parseInt(this.socket.value.getRemoteSocketAddress().toString().split(":").pop());
message["dst_addr"] = ntohl(ipToNumber((this.socket.value.getLocalAddress().toString().split(":")[0]).split("/").pop()));
message["dst_port"] = parseInt(this.socket.value.getLocalPort());
if (result > 0) {
var ptr = Memory.alloc(result);
for (var i = 0; i < result; ++i)
Memory.writeS8(ptr.add(i), bytearry[offset + i]);
send(message, Memory.readByteArray(ptr, result))
}
return result;
}
})
}
int NET_Read(int s, void* buf, size_t len) {
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
}
int NET_ReadV(int s, const struct iovec * vector, int count) {
BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
}
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
struct sockaddr *from, int *fromlen) {
socklen_t socklen = *fromlen;
BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) );
*fromlen = socklen;
}
int NET_Send(int s, void *msg, int len, unsigned int flags) {
BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
}
int NET_WriteV(int s, const struct iovec * vector, int count) {
BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
}
int NET_SendTo(int s, const void *msg, int len, unsigned int
flags, const struct sockaddr *to, int tolen) {
BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
}
int NET_Accept(int s, struct sockaddr *addr, int *addrlen) {
socklen_t socklen = *addrlen;
BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) );
*addrlen = socklen;
}
int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
}
#ifndef USE_SELECT
int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
}
#else
int NET_Select(int s, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout) {
BLOCKING_IO_RETURN_INT( s-1,
select(s, readfds, writefds, exceptfds, timeout) );
}
-
仅限安卓平台,测试安卓7、8、9、10 可用 ;
-
无视所有证书校验或绑定,不用考虑任何证书的事情;
-
通杀TCP/IP四层模型中的应用层中的全部协议;
-
通杀协议包括:Http,WebSocket,Ftp,Xmpp,Imap,Smtp,Protobuf等等、以及它们的SSL版本;
-
通杀所有应用层框架,包括HttpUrlConnection、Okhttp1/3/4、Retrofit/Volley等等;
-
Spawn 模式:
$ python3 r0capture.py -U -f com.qiyi.video
-
Attach 模式,抓包内容保存成pcap文件供后续分析:
$ python3 r0capture.py -U com.qiyi.video -p iqiyi.pcap
# 八月
# 七月
# 六月
从三道题目入手入门frida
单纯使用Frida书写类抽取脱壳工具的一些心路历程和实践
某聊天app的音视频通话逆向
# 五月
初试IDA&FRIDA联合调试简单ollvm保护的加密函数源码
# 四月
某抽取壳的原理简析
frida辅助脱壳
# 三月
《安卓高级研修班(网课)》
3月班开始招生!
课 程 内 容
2021 3月班
服 务 对 象
服 务 内 容
开 班 时 间
开班时间:2021年3月开班(202103期)
培 训 价 格
-
就业班附带包就业服务(须达到合同规定的毕业标准),签合同保证就业及薪资,达不到退全款;
-
就业班有入学考核,缴费成功后进入考核流程,考核不通过退全款;
-
考核流程会包括简历筛选、班主任和老师(电话)面试等环节;
-
强化班仅去除包就业服务,并且无入学考核,其余与就业班完全相同;
-
就业班与强化班一起授课,合计35人一个班,教学上不做任何区分。
-
《安卓高级研修班》全系列无任何金融计划,纯预付;无任何金融套路。
-
网络课程为虚拟商品,购买之前可以观看下述试看内容,购买成功之后不接受退款。
报 名 地 址
网课月薪三万计划:
https://www.kanxue.com/book-brief-84.htm
扫码立即报名!
试看地址:
3W:《ida trace分析非标准算法》
3W:《Fart&frida》
扫码免费试看
扫码免费试看
联 系 我 们
课程顾问微信: r0ysue (备注“安卓高研网课”)
免责条款
以上所有宣传稿件内容均不作为服务承诺,最终以实际签订培训合同为准。
课程大纲与细目会根据教学反馈不断优化、调整与更新,实际授课可能与宣传主题略有不同;
常见Q&A及预习指南
-
一部pixel手机(sailfish)(安卓8脱壳镜像)
-
安卓源码开发编译调试环境SSD移动硬盘500G
A:月薪三万计划的内容与线下班的内容是一样的,我们在线下班沉淀大家的切实的需求和疑问,重新编排和制作内容作为网课与大家分享。月薪两万计划的内容由三万计划的讲师全新制作,充分体现工作场景一线的需求,更加贴近实战、实用,有用、好用。
Q:网课内容与线下班内容一样么?
A:目前针对ollvm和vmp,任何所谓的自动化,都是带很多前提和条件限制的;目前最快的还原ollvm或vmp的方法,还是手动分析,一般快则两三日、慢则一两周,基本上可以还原出来。
A:月薪两万计划推荐至少有实际安卓安全岗位工作经验一年以上为宜。初学者可以先看我们安卓版主非虫大佬的《Android软件安全权威指南》等安卓安全书籍进行入门,在看雪论坛看帖发帖提升自身水平,本套课程建议有工作经验的老手前来充电学习。
月薪三万计划视大家实际需求而定,一般看得懂目录及想要学习的人自己就懂,大家不用盲目跟风。如果看不懂目录及不理解目录的具体含义及意义,建议先从两万计划学起,多积累技术和经验。
A:不需要,互相独立的。月薪两万计划的定位更加偏向工作岗位一线逆向需求,月薪三万计划则更加偏向于高级调试技巧,二者互为补充,相辅相成。有非常多地大佬两个计划一起报名了,我们也会确保直播时间不会冲突。
A:其实推荐两个班一起报,有好几位大佬就是两个班全报的。因为首先价格真心不贵,其实我们会将直播的时间错开,方便大家同时进修三万和两万计划,学习自己想要学习的、心仪的知识。
A:每一场直播都有回放,在看雪课程中可以观看。
A:就业班是需要考核的。考核流程是先缴费报名,然后开始。会经过简历、(远程)一面和二面。通过之后补差价,不通过退全款。
球分享
球点赞
球在看
点击“阅读原文”,了解更多!
本文始发于微信公众号(看雪学院):安卓应用层抓包通杀脚本发布!《高研班》2021年3月班开始招生!
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论