Android Native逆向?qū)崙?zhàn):Frida+JNItrace定位B站Sign算法
1. 項目概述從零到一逆向B站Sign算法的完整旅程最近在折騰Android Native層的逆向分析目標(biāo)直指B站客戶端的Sign簽名算法。對于很多剛接觸Native逆向的朋友來說這就像面對一堵高墻Java層的逆向工具和思路相對成熟一旦邏輯下沉到so庫用C/C編寫傳統(tǒng)的靜態(tài)分析工具就顯得力不從心動態(tài)調(diào)試的門檻也陡然增高。這次實戰(zhàn)我選擇用Frida和JNItrace這兩件“神器”組合出擊完整地走通了定位、分析、還原算法的全過程。整個過程充滿了“踩坑”與“頓悟”非常適合像我一樣從Java層逆向轉(zhuǎn)向Native層探索的新手參考。如果你也好奇B站App的請求是如何被加上那一串神秘簽名的或者想學(xué)習(xí)一套通用的Native層Hook與分析方法那么這篇筆記或許能給你帶來不少啟發(fā)。簡單來說我們的目標(biāo)就是搞清楚B站App在發(fā)起網(wǎng)絡(luò)請求時那個關(guān)鍵的sign參數(shù)是如何生成的。這個參數(shù)通常用于驗證請求的合法性防止篡改和重放是客戶端與服務(wù)器通信的重要“暗號”。算法核心邏輯往往被編譯進so動態(tài)鏈接庫中以提高安全性。因此這次逆向的核心戰(zhàn)場就在這些so文件里我們需要一套能夠深入Native層函數(shù)調(diào)用、監(jiān)控JNI交互的方法。2. 逆向環(huán)境與工具鏈的精心搭建工欲善其事必先利其器。一個穩(wěn)定、高效的逆向環(huán)境是成功的一半。這次實戰(zhàn)主要依賴兩大工具Frida和JNItrace。前者是動態(tài)插樁的瑞士軍刀后者則是透視JNI調(diào)用的“X光機”。它們的組合能讓我們在不太深入?yún)R編指令的情況下依然清晰地看到函數(shù)調(diào)用流和數(shù)據(jù)變化。2.1 Frida環(huán)境部署從PC到手機的貫通Frida的安裝看似簡單但版本兼容性是個大坑。我的環(huán)境是Windows 11主機一部已Root的Android 10測試機以及目標(biāo)B站App版本號7.xx.xx具體版本建議選擇稍舊一些的穩(wěn)定版新版本可能加固更強。PC端安裝直接在命令行使用pip安裝是最快的方式。但務(wù)必注意frida和frida-tools的版本需要匹配且最好與手機端運行的frida-server版本一致。pip install frida15.2.2 frida-tools12.0.0這里我選擇了15.2.2這個相對穩(wěn)定的版本。安裝完成后用frida --version驗證。手機端部署根據(jù)手機CPU架構(gòu)通常是arm64-v8a去Frida的GitHub Releases頁面下載對應(yīng)版本的frida-server-15.2.2-android-arm64.xz。解壓得到二進制文件通過adb推送到手機并賦予執(zhí)行權(quán)限adb push frida-server-15.2.2-android-arm64 /data/local/tmp/ adb shell su cd /data/local/tmp chmod 755 frida-server-15.2.2-android-arm64在手機端后臺運行frida-server./frida-server-15.2.2-android-arm64 。更穩(wěn)妥的方法是使用nohup或創(chuàng)建一個init.d腳本確保進程穩(wěn)定。連接測試在PC端執(zhí)行frida-ps -U如果能看到手機上的進程列表恭喜你環(huán)境打通了。注意很多加固或風(fēng)控方案會檢測Frida。如果遇到App閃退或frida-ps看不到目標(biāo)進程可能是觸發(fā)了反調(diào)試。此時可以嘗試更換Frida版本如使用較舊的14.x版本、使用定制化的frida-server修改默認(rèn)端口、名稱、或者借助其他工具如objection先繞過一些簡單的檢測。本次分析的B站版本在常規(guī)環(huán)境下可直接附加。2.2 JNItrace工具集成照亮JNI調(diào)用的迷霧JNItrace是一個基于Frida的腳本它能打印出所有JNI函數(shù)的調(diào)用及其參數(shù)、返回值對于定位Java與Native代碼的交互點至關(guān)重要。安裝非常簡單pip install jnitrace安裝后我們就可以通過jnitrace命令來啟動對目標(biāo)App的監(jiān)控。它的輸出日志非常詳細(xì)是后續(xù)分析的關(guān)鍵入口。2.3 輔助工具準(zhǔn)備IDA Pro/Ghidra用于so文件的靜態(tài)分析。當(dāng)通過動態(tài)追蹤定位到關(guān)鍵函數(shù)后需要反編譯查看其偽代碼邏輯。adb 抓包工具Charles/Fiddler用于捕獲B站App的網(wǎng)絡(luò)請求確認(rèn)sign參數(shù)的存在和格式。抓包需要配置好手機代理和SSL證書解密B站用了SSL Pinning可能需要額外工具如JustTrustMe模塊配合Frida繞過。一臺Root過的Android測試機這是運行frida-server和進行深度Hook的前提。模擬器如雷電也可以但部分反調(diào)試方案在模擬器上行為可能不同且Frida對模擬器的支持有時需要特殊配置。3. 核心思路與逆向策略拆解面對一個龐大的App直接扎進海量的so文件里無疑是盲人摸象。我的逆向策略遵循了“由外而內(nèi)、由動至靜”的原則層層遞進。3.1 策略總覽從網(wǎng)絡(luò)抓包到代碼定位行為觀察抓包首先通過抓包工具清晰地看到哪個API請求攜帶了sign參數(shù)它的值長什么樣通常是32位或64位的十六進制字符串以及它和哪些請求參數(shù)如時間戳、請求體可能有關(guān)聯(lián)。記錄下幾個典型的請求。入口定位JNI監(jiān)控使用JNItrace大面積掃描尋找所有計算或生成sign字符串可能的JNI調(diào)用路徑。Sign的生成最終很可能由Java層某個方法觸發(fā)調(diào)用Native方法完成。關(guān)鍵函數(shù)HookFrida根據(jù)JNItrace的線索用Frida編寫精確的Hook腳本針對特定的Native函數(shù)或Java方法打印其輸入、輸出及關(guān)鍵中間變量。邏輯分析與還原靜態(tài)分析將Hook得到的核心函數(shù)地址在IDA Pro中定位閱讀其反編譯的C/C偽代碼結(jié)合動態(tài)觀察到的數(shù)據(jù)流理解并最終還原出算法邏輯。算法復(fù)現(xiàn)與驗證使用Python或Java將逆向出來的算法邏輯重新實現(xiàn)并用抓包到的原始數(shù)據(jù)測試看能否生成一致的sign值。3.2 為什么選擇FridaJNItrace組合對于Native逆向新手這個組合的優(yōu)勢在于降低了起步門檻。Frida提供了在運行時動態(tài)修改內(nèi)存、攔截函數(shù)的能力。你不需要一開始就理解復(fù)雜的匯編指令可以先通過Hook觀察函數(shù)行為。JNItraceJNIJava Native Interface是Java代碼和Native代碼通信的橋梁。Sign算法的入口極有可能是一個native聲明的Java方法。JNItrace能自動追蹤所有這些橋梁上的“車輛”調(diào)用告訴我們什么時候、哪個Java方法調(diào)用了哪個so里的哪個函數(shù)傳遞了什么參數(shù)。這相當(dāng)于給了我們一張清晰的“地圖”直接標(biāo)出了可疑地點避免了在數(shù)百萬條匯編指令中大海撈針。4. 實戰(zhàn)第一步捕獲目標(biāo)與定位入口理論說得再多不如動手操作。我們正式開始。4.1 網(wǎng)絡(luò)請求抓包與特征分析配置好抓包工具和SSL繞過后打開B站App進行一些能觸發(fā)網(wǎng)絡(luò)請求的操作比如刷新首頁、搜索視頻。在Charles中你會發(fā)現(xiàn)類似api.bilibili.com域名的請求其URL或Form Data里包含一個名為sign的參數(shù)。例如一個搜索請求可能看起來像https://api.bilibili.com/xxx/search?keywordtestts1648888888signabcdef1234567890abcdef1234567890初步觀察點sign值通常是32位或64位的十六進制字符串。除了sign請求中通常還有ts時間戳等參數(shù)。嘗試重復(fù)發(fā)送相同參數(shù)的請求sign值會變化說明它可能和ts甚至一個隨機數(shù)有關(guān)。嘗試修改keyword再發(fā)送sign也變了說明它和請求參數(shù)內(nèi)容有關(guān)。這個階段我們假設(shè)sign是對“請求參數(shù)密鑰時間戳”等元素通過某種哈希算法如MD5、SHA256或HMAC計算得出的。我們的任務(wù)就是找到這個計算發(fā)生的地方。4.2 啟動JNItrace進行全景掃描這是最關(guān)鍵的一步。我們需要在App啟動時就開始監(jiān)控因為Sign計算可能發(fā)生在App初始化或早期。jnitrace -l libbili*.so -m com.bilibili.app com.bilibili.app.in-l libbili*.so只跟蹤B站相關(guān)so庫的JNI調(diào)用減少無關(guān)日志。你可以先不加這個參數(shù)跑一遍看看有哪些so再針對性過濾。-m指定啟動的Activity。com.bilibili.app是主進程有時核心邏輯在子進程如com.bilibili.app.in需要分別嘗試。命令執(zhí)行后JNItrace會啟動B站App并輸出海量的日志。這時我們在手機上操作觸發(fā)之前抓包看到的那個帶sign的搜索請求。4.3 在日志海洋中尋找“Sign”的蛛絲馬跡JNItrace的日志輸出到控制臺。我們需要仔細(xì)搜索。重點關(guān)注以下幾類調(diào)用FindClass/GetMethodID/CallStaticObjectMethod等這些可能是在Native層主動調(diào)用Java類方法。也許Native算法需要獲取一些Android系統(tǒng)參數(shù)如設(shè)備ID。NewStringUTFNative層創(chuàng)建了一個Java字符串。一個計算好的sign最終很可能要通過NewStringUTF返回給Java層。涉及加密哈希相關(guān)的函數(shù)名雖然JNI函數(shù)名本身不直接顯示業(yè)務(wù)邏輯但我們可以搜索日志中的字符串字面量。在觸發(fā)請求的時間點附近用文本編輯器的查找功能搜索“sign”、“md5”、“sha”、“hmac”、“encrypt”等關(guān)鍵詞。一個典型的發(fā)現(xiàn)過程可能是 在觸發(fā)搜索請求的瞬間日志中突然出現(xiàn)一連串密集的JNI調(diào)用。你可能會看到類似下面的片段這是簡化后的示意[] Call Stack 0: com.bilibili.lib.security.SignUtils - nativeGenerateSign (Ljava/lang/String; Ljava/lang/String; J)Ljava/lang/String; libbilibili_crypto.so!0x7d6c (Java_com_bilibili_lib_security_SignUtils_nativeGenerateSign)這行日志告訴我們Java類com.bilibili.lib.security.SignUtils中的nativeGenerateSign方法被調(diào)用了它實現(xiàn)在libbilibili_crypto.so中對應(yīng)的Native函數(shù)地址是0x7d6c偏移量。這就是我們夢寐以求的入口點此外在調(diào)用nativeGenerateSign之前或之后可能會看到GetStringUTFChars獲取Java字符串參數(shù)和NewStringUTF返回結(jié)果的調(diào)用這進一步驗證了我們的猜想。5. 深入核心Frida精準(zhǔn)Hook與參數(shù)追蹤找到疑似入口后需要用Frida進行更精確的偵查和驗證。我們將編寫一個Frida腳本。5.1 編寫Frida Hook腳本創(chuàng)建一個名為hook_sign.js的文件內(nèi)容如下Java.perform(function () { // 1. Hook Java層的入口方法如果確認(rèn)了的話 var SignUtils Java.use(com.bilibili.lib.security.SignUtils); SignUtils.nativeGenerateSign.implementation function (param1, param2, timestamp) { console.log(\n[] Java層 nativeGenerateSign 被調(diào)用); console.log( param1: param1); console.log( param2: param2); console.log( timestamp: timestamp); var result this.nativeGenerateSign(param1, param2, timestamp); // 調(diào)用原函數(shù) console.log( [] 返回值: result); return result; }; // 2. Hook Native層的函數(shù)通過地址 Interceptor.attach(Module.findBaseAddress(libbilibili_crypto.so).add(0x7d6c), { onEnter: function (args) { console.log(\n[] Native函數(shù) Java_com_bilibili_..._nativeGenerateSign 進入); // args[0] 是JNIEnv*, args[1] 是jclass/jobject, args[2], args[3]... 是參數(shù) // 讀取Java字符串參數(shù)需要調(diào)用JNI函數(shù)這里簡化通常更復(fù)雜 console.log( 函數(shù)地址: this.returnAddress); // 可以在這里打印內(nèi)存但需要更多操作 }, onLeave: function (retval) { console.log([] Native函數(shù)離開); // retval 是返回的jstring可以嘗試讀取 // var jniEnv Java.vm.getEnv(); // var resultStr jniEnv.getStringUtfChars(retval, null); // console.log( 返回的字符串: resultStr.readCString()); } }); // 3. Hook通用的加密函數(shù)如果知道用了什么庫 // 例如Hook OpenSSL的MD5_Init/Update/Final var md5_init_addr Module.findExportByName(libcrypto.so, MD5_Init); if (md5_init_addr) { Interceptor.attach(md5_init_addr, { onEnter: function (args) { console.log(\n[] MD5_Init 被調(diào)用上下文: this.context.pc); } }); } });這個腳本做了三件事Hook Java層的Native方法聲明處打印傳入的參數(shù)和最終結(jié)果。直接Hook我們通過JNItrace找到的Native函數(shù)地址嘗試在進入和離開時打印信息。嘗試Hook底層的加密庫函數(shù)如OpenSSL作為輔助驗證。5.2 運行腳本并分析輸出通過Frida加載腳本frida -U -f com.bilibili.app -l hook_sign.js --no-pause再次在App中觸發(fā)搜索請求。觀察控制臺輸出。理想情況下你會看到清晰的調(diào)用鏈[] Java層 nativeGenerateSign 被調(diào)用 param1: “keywordtestts1648888888” param2: “another_fixed_string” timestamp: 1648888888000 [] Native函數(shù) Java_com_bilibili_..._nativeGenerateSign 進入 [] MD5_Init 被調(diào)用上下文: 0x7a1b3c4d [] MD5_Update 被調(diào)用... [] MD5_Final 被調(diào)用... [] Native函數(shù)離開 [] 返回值: “abcdef1234567890abcdef1234567890”通過對比抓包得到的原始請求參數(shù)和這里param1的內(nèi)容你就能確定Native函數(shù)接收的輸入是否就是構(gòu)建簽名的原始字符串。返回值與網(wǎng)絡(luò)請求中的sign一致則完全證實了這個函數(shù)就是我們要找的目標(biāo)。5.3 參數(shù)構(gòu)造邏輯的逆向現(xiàn)在我們知道nativeGenerateSign接收三個參數(shù)。但網(wǎng)絡(luò)請求有很多參數(shù)它們是如何被拼接成param1的呢這可能需要我們向上追溯。我們可以Hook調(diào)用nativeGenerateSign的Java方法可能是一個叫g(shù)etSign的Java方法看它內(nèi)部是如何收集請求參數(shù)如keyword,ts,其它固定參數(shù)并按照什么規(guī)則如按字母排序、URL鍵值對拼接組裝成字符串然后傳遞給Native層的。這部分工作可能需要反復(fù)嘗試和猜測。例如你可能會發(fā)現(xiàn)最終的參數(shù)字符串是“keywordtestts1648888888appkeyxxxxxxappsecyyyyyy”其中appkey和appsec可能是內(nèi)置的固定值。而param2可能是一個鹽值salt或版本標(biāo)識。6. 靜態(tài)分析與算法還原有了明確的函數(shù)地址libbilibili_crypto.so0x7d6c和輸入輸出樣本就可以進行靜態(tài)分析了。6.1 使用IDA Pro加載so文件將手機中的libbilibili_crypto.so文件pull到電腦上用IDA Pro打開。等待自動分析完成后按G鍵跳轉(zhuǎn)到地址0x7d6c注意這是文件偏移在IDA中可能需要根據(jù)so加載基址換算。更簡單的方法是在Hex View中搜索函數(shù)名Java_com_bilibili_lib_security_SignUtils_nativeGenerateSign的字符串直接定位函數(shù)。6.2 分析偽代碼邏輯定位到函數(shù)后按F5反編譯成偽代碼。你會看到類似下面的結(jié)構(gòu)極度簡化和抽象jstring __fastcall Java_com_bilibili_lib_security_SignUtils_nativeGenerateSign(JNIEnv *env, jclass clazz, jstring param1, jstring param2, jlong timestamp) { const char *v5; // 輸入字符串param1 const char *v6; // 輸入字符串param2 char concatenated_str[512]; char timestamp_str[32]; unsigned char md5_result[16]; char final_sign[33]; v5 (*env)-GetStringUTFChars(env, param1, 0); v6 (*env)-GetStringUTFChars(env, param2, 0); // 1. 將時間戳轉(zhuǎn)換為字符串 sprintf(timestamp_str, %lld, timestamp); // 2. 拼接字符串 param1 param2 timestamp_str (或其它順序) strcpy(concatenated_str, v5); strcat(concatenated_str, v6); strcat(concatenated_str, timestamp_str); // 3. 計算MD5 MD5_Init(ctx); MD5_Update(ctx, concatenated_str, strlen(concatenated_str)); MD5_Final(md5_result, ctx); // 4. 將16字節(jié)MD5結(jié)果轉(zhuǎn)為32位十六進制字符串 for ( i 0; i 16; i ) sprintf(final_sign[2 * i], %02x, (unsigned int)md5_result[i]); final_sign[32] 0; // 5. 可能還有二次處理如取部分字符、大小寫轉(zhuǎn)換等 // to_upper(final_sign); // 6. 創(chuàng)建Java字符串并返回 result (*env)-NewStringUTF(env, final_sign); (*env)-ReleaseStringUTFChars(env, param1, v5); (*env)-ReleaseStringUTFChars(env, param2, v6); return result; }通過閱讀偽代碼算法的核心步驟就清晰了字符串拼接 - MD5哈希 - 十六進制格式化。你需要仔細(xì)核對拼接的順序、是否包含其他固定字符串、時間戳的格式等細(xì)節(jié)。這些細(xì)節(jié)必須與動態(tài)Hook時觀察到的數(shù)據(jù)完全吻合。6.3 算法復(fù)現(xiàn)與驗證最后一步用Python將算法還原import hashlib import time def generate_sign(param1, param2, timestamp): # 1. 拼接字符串 (根據(jù)靜態(tài)分析確定的順序) raw_str param1 param2 str(timestamp) # 2. 計算MD5 m hashlib.md5() m.update(raw_str.encode(utf-8)) md5_bytes m.digest() # 3. 轉(zhuǎn)為十六進制字符串 sign md5_bytes.hex() # 4. 可能的后續(xù)處理如轉(zhuǎn)大寫 sign sign.upper() return sign # 使用抓包和Hook得到的數(shù)據(jù)進行測試 test_param1 keywordtestts1648888888 test_param2 a_fixed_salt test_ts 1648888888000 calculated_sign generate_sign(test_param1, test_param2, test_ts) print(f計算得到的sign: {calculated_sign}) # 與你抓包中真實的sign對比如果計算結(jié)果與真實請求中的sign一致那么恭喜你逆向成功7. 常見問題、踩坑記錄與進階技巧逆向過程很少一帆風(fēng)順以下是我在這次和以往項目中總結(jié)的一些典型問題和解決思路。7.1 Frida相關(guān)的問題與排查問題1Frida無法附加進程提示“Failed to attach: process not found”或進程崩潰。可能原因App有反Frida檢測。排查與解決檢查進程名使用frida-ps -U確認(rèn)進程名是否正確。Android App可能有主進程、子進程、多開進程等。嘗試延遲注入使用-fspawn模式啟動App但加上--no-pause然后盡快在腳本中用setTimeout延遲Hook關(guān)鍵函數(shù)避免在啟動初期就被檢測。更換Frida版本/配置嘗試?yán)习姹綟rida如12.x。修改frida-server的文件名和端口通過-l參數(shù)指定。使用繞過工具結(jié)合使用objection的android anti-root-detection disable等命令或使用其他隱藏Frida的腳本。問題2Hook Native函數(shù)時Module.findBaseAddress返回null或地址不對??赡茉騭o文件尚未加載或者加載的基址每次運行都不同ASLR。解決// 等待so加載 function hookAfterSoLoad() { var baseAddr Module.findBaseAddress(libbilibili_crypto.so); if (baseAddr) { var targetAddr baseAddr.add(0x7d6c); Interceptor.attach(targetAddr, { ... }); } else { setTimeout(hookAfterSoLoad, 500); // 遞歸等待 } } setTimeout(hookAfterSoLoad, 0);7.2 JNItrace使用技巧與日志分析問題JNItrace日志太多刷屏太快找不到有用信息。解決嚴(yán)格過濾使用-l參數(shù)只跟蹤目標(biāo)so使用-i參數(shù)只跟蹤特定函數(shù)如NewStringUTF。輸出到文件使用-o trace.log將日志輸出到文件然后用文本編輯器如VSCode的強大搜索功能支持正則表達(dá)式進行分析。搜索sign、md5、encrypt等關(guān)鍵詞。關(guān)注調(diào)用棧JNItrace會打印調(diào)用棧Call Stack這是理解函數(shù)調(diào)用關(guān)系的黃金信息。重點關(guān)注那些在觸發(fā)網(wǎng)絡(luò)請求時刻出現(xiàn)的、棧底是Java用戶代碼的JNI調(diào)用。7.3 靜態(tài)分析中的難點問題IDA Pro反編譯的偽代碼可讀性差有很多混淆的變量名和間接調(diào)用。解決重命名變量根據(jù)上下文和動態(tài)Hook時獲得的信息給關(guān)鍵變量起有意義的名稱如v5改為input_param1_str。識別加密常量MD5、SHA256等算法的初始化向量IV是固定的常量。在IDA的Hex View中搜索這些常量如MD5的A、B、C、D初始值可以快速定位加密函數(shù)。動態(tài)調(diào)試輔助如果條件允許可以使用IDA Pro或Ghidra的遠(yuǎn)程調(diào)試功能配合adb和android_server在真機或模擬器上進行源碼級調(diào)試單步跟蹤驗證猜想。7.4 算法還原的驗證與邊界情況問題自己實現(xiàn)的算法大部分情況正確但偶爾生成的sign對不上。排查編碼問題確保拼接字符串時的編碼與Native層一致通常是UTF-8。特別是中文字符需要確認(rèn)。隱藏參數(shù)是否有一些隱式的參數(shù)被加入了計算比如設(shè)備信息、版本號可能在Native層通過JNI調(diào)用Java方法獲取然后參與計算?;仡橨NItrace日志看Native函數(shù)是否在計算前調(diào)用了CallObjectMethod等獲取了其他數(shù)據(jù)。時間戳精度Native層使用的時間戳精度秒、毫秒、微秒是否與你的生成一致算法變種是否是標(biāo)準(zhǔn)MD5有沒有自定義的變換如循環(huán)左移、額外異或仔細(xì)對比你的MD5結(jié)果和Hook到的Native函數(shù)中間變量如果能在MD5_Final之前Hook到ctx狀態(tài)并導(dǎo)出將是終極驗證手段。逆向工程就像偵探破案需要耐心、細(xì)致的觀察和合理的推理。Frida和JNItrace的組合為Android Native逆向提供了一套強大的動態(tài)分析工具鏈極大地降低了入門難度。這次對B站Sign算法的逆向不僅讓我獲得了一個可用的算法更重要的是熟悉了從動態(tài)追蹤到靜態(tài)分析再到算法還原的完整方法論。記住每個App的防護強度不同思路可以復(fù)用但具體的繞過和定位技巧需要隨機應(yīng)變。希望這篇詳細(xì)的實戰(zhàn)筆記能為你打開Native逆向世界的大門。

相關(guān)新聞

cd的基礎(chǔ)用法

cd的基礎(chǔ)用法

一、基礎(chǔ)介紹 cd Change Directory,作用:切換工作目錄 ?? cd 屬于 Shell內(nèi)置命令,不是獨立程序 語法:cd [選項] [目錄路徑] 二、基礎(chǔ)常用語法 cd 不帶參數(shù),直接進入當(dāng)前用戶家目錄 等價:cd ~ 、cd $HOME…

2026/8/3 7:38:37 閱讀更多
從火影到國風(fēng)少女:用ControlNet精準(zhǔn)控構(gòu)漫畫分鏡的6種高階姿勢,附可復(fù)用ControlNet權(quán)重包

從火影到國風(fēng)少女:用ControlNet精準(zhǔn)控構(gòu)漫畫分鏡的6種高階姿勢,附可復(fù)用ControlNet權(quán)重包

更多請點擊: https://intelliparadigm.com 第一章:從火影到國風(fēng)少女:ControlNet漫畫分鏡生成全景導(dǎo)覽 ControlNet 作為 Stable Diffusion 生態(tài)中關(guān)鍵的條件控制模塊,正深刻重塑二次元內(nèi)容創(chuàng)作范式——它不再僅依賴文本提示&#…

2026/8/3 14:28:51 閱讀更多
為什么92%的AI設(shè)計師接不到單?3個致命認(rèn)知偏差+5分鐘自檢表(限前200名領(lǐng)取診斷工具)

為什么92%的AI設(shè)計師接不到單?3個致命認(rèn)知偏差+5分鐘自檢表(限前200名領(lǐng)取診斷工具)

更多請點擊: https://kaifayun.com 第一章:AI設(shè)計接單的底層邏輯與行業(yè)真相 AI設(shè)計接單并非單純的技術(shù)交付,而是技術(shù)能力、商業(yè)認(rèn)知與用戶心理的三維耦合。其底層邏輯根植于“需求可建模性”——即客戶提出的問題是否能被結(jié)構(gòu)化為提示工程、…

2026/8/3 14:28:51 閱讀更多
ESP32網(wǎng)頁控制與實時數(shù)據(jù)顯示:從HTTP到WebSocket的物聯(lián)網(wǎng)實踐

ESP32網(wǎng)頁控制與實時數(shù)據(jù)顯示:從HTTP到WebSocket的物聯(lián)網(wǎng)實踐

1. 從零到一:為什么ESP32是網(wǎng)頁控制顯示的“天選之子” 如果你玩過Arduino,想給項目加個屏幕顯示數(shù)據(jù),大概率會經(jīng)歷一番折騰:要么屏幕引腳不夠用,要么刷新率上不去,要么想遠(yuǎn)程看看數(shù)據(jù)還得額外接個Wi-Fi模塊…

2026/8/3 14:28:51 閱讀更多
云計算如何革新數(shù)據(jù)科學(xué)工作流

云計算如何革新數(shù)據(jù)科學(xué)工作流

1. 為什么數(shù)據(jù)科學(xué)需要擁抱云計算? 十年前我剛?cè)胄袛?shù)據(jù)科學(xué)時,團隊還在用單機跑Python腳本處理幾十GB的數(shù)據(jù)。記得有次跑一個推薦算法模型,我的ThinkPad筆記本連續(xù)運轉(zhuǎn)了72小時后終于藍(lán)屏崩潰,一周的工作成果全部付諸東流。這種痛…

2026/8/3 14:18:51 閱讀更多
全球僅7家廠商通過ISO/IEC 27001認(rèn)證的名片AI引擎,我們逆向拆解了它的字段置信度熔斷機制

全球僅7家廠商通過ISO/IEC 27001認(rèn)證的名片AI引擎,我們逆向拆解了它的字段置信度熔斷機制

更多請點擊: https://kaifayun.com 第一章:全球僅7家廠商通過ISO/IEC 27001認(rèn)證的名片AI引擎概覽 名片AI引擎是企業(yè)級智能文檔處理的核心組件,專注于高精度OCR、語義結(jié)構(gòu)化提取與跨語言實體對齊。截至2024年第三季度,全球范圍內(nèi)僅…

2026/8/3 0:07:47 閱讀更多
3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南

3分鐘搞定!QQ空間歷史說說完整備份終極指南 【免費下載鏈接】GetQzonehistory 獲取QQ空間發(fā)布的歷史說說 項目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾想過,那些年發(fā)過的QQ空間說說,那些記錄青春的文字…

2026/8/3 12:53:38 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號分配電路板。該型號(0100-02186)的核心特點如下:專用于Endura等半導(dǎo)體工藝腔室。集成信號路由與分配功能。連接控制…

2026/8/2 2:51:21 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機,適用于自動化設(shè)備及通用機械驅(qū)動。該型號(FFMN-32L-10-T0 40AX)的核心特點如下:三相交流異步電動機。額定…

2026/8/2 2:52:49 閱讀更多