安卓APP破解利器之FRIDA

本文講的是安卓APP破解利器之FRIDA在我去年參加RadareCon大會的時候,我了解到了一個動態的二進制插樁框架——Frida。起初我覺得它似乎只有一丁點趣味,后來經過實踐才發現它原來是如此的有趣。記得游戲里的上帝模式嗎?這就是Frida操作本機應用程序的感覺。這是一篇關于專門使用Frida把玩Android應用程序的博客文章。而且,因為我們是在闡述這一點,所以我們也將在這篇文章的第二部分中進行一點Android APP的破解實戰。

什么是動態二進制插樁?

動態二進制插樁(DBI)意味著將外部代碼注入到現有的(正在運行的)二進制文件中,使它們能夠做一些以前沒有做過的事情。這個過程不是利用了漏洞,因為代碼注入并不是通過你之前必須搞清楚的一些漏洞所導致的。它也不是調試,因為你沒有將調試器附加到二進制文件上,盡管你可以做類似調試的一些事情。你能用DBI做些什么呢?這是一個很酷的東西:)

訪問進程的內存
在應用程序運行時覆蓋一些功能
從導入的類中調用函數
在堆上查找對象實例并使用這些對象實例
Hook,跟蹤和攔截函數等等

當然,你也可以使用調試器完成所有這些操作,不過使用調試器會帶來各種麻煩。例如在Android中,你必須反匯編并重新編譯應用程序以使其可用于調試。一些應用程序會檢測并嘗試阻止調試器的調試過程,你需要擺脫這些反調試邏輯。可能你會成功,但是整個過程非常麻煩。使用Frida的DBI可以讓你使用黑盒進程快速啟動Android應用程序。

FRIDA

安卓APP破解利器之FRIDA

Frida可以“將你自己的JavaScript代碼片段或代碼庫注入到Windows,MACOS,Linux, iOS,Android和QNX 的本地應用中”。這是第一款基于谷歌的V8 JavaScript引擎運行的應用程序,在Frida的第九個版本中使用的是Duktape,但它仍然允許你切換回V8引擎,如果你需要這么做的話。Frida有很多可以與二進制文件進行交互(包括在無root權限的設備上對應用程序進行插樁的可能性)的操作模式,不過我們在本文這里會使用最常見的用戶操作,并且現在我們不需要關心其內部實現。

在開始本文的破解教程之前,你需要做以下幾個事情:

1.?Frida(我在本教程中使用的9.1.16版本)

2. frida-server可以二進制發布頁面下載到( 在本文發表時為frida-server-9.1.16-android-arm.xz,frida-serve的版本應該與Frida版本一致。)

3. Android模擬器或已ROOT的安卓設備。Frida已經開發了Android 4.4 ARM對應的版本,但它應該適用于更高的版本。我在本教程中成功使用了Android 7.1.1 ARM。對于第二部分的破解,我們需要用到比Android 4.4版本更高的一些東西。

我使用linux系統作為宿主機的操作系統,如果你使用的是Windows或Mac,那你可能需要調整一些命令。

如果你想在解決OWASP Unbreakable Crackme Level 1中的問題,你可以在本系列教程的第二部分中找到破解方法,同時,你也應該下載下面的幾個程序:

1.?OWASP Unbreakable Crackme Level 1APK

2.?BytecodeViewer

3.?dex2jar

Frida提供各種API和開始破解的方法。你可以使用命令行界面或frida-trace跟蹤低級功能的工具(如libc.so中的“open”函數的調用)進行快速運行。你可以使用C,NodeJS或Python綁定更復雜的東西。在Frida內部,會更多的使用Javascript工作,你也將使用這種語言完成大部分插樁工作。所以如果你和我一樣,不喜歡使用Javascript(除了XSS功能之外),那Frida或許是讓你熟悉JavaScript的另一個原因。

如果沒有,請安裝Frida(請參閱README以獲得其他的安裝方式):

pip?install?frida
npm?install?frida

啟動你的模擬器或連接你的設備,并確保adb正在運行并列出了你的設備:

michael@sixtyseven:~$?adb?devices
List?of?devices?attached
emulator-5556???device

然后安裝frida-server。解壓文檔并將二進制文件push到設備上:

adb push /home/michael/Downloads/frida-server-9.1.16-android-arm /data/local/tmp/frida-server

使用adb打開設備上的一個shell,切換到root用戶并啟動frida-server:

adb?shell
su
cd?/data/local/tmp
chmod?755?frida-server
./frida-server

(注1:如果frida-server沒有啟動,請確保你使用的是root用戶,并且該文件已經正確push到設備中。我之前就遇到過文件傳輸損壞導致的各種奇怪的錯誤。注2:如果要啟動frida-server作為后臺進程,可以使用這個命令./frida-server &)

在另一個常規的OS shell終端中,檢查Frida是否正在運行,并列出在Android上的進程:

frida-ps?-U

參數-U代表USB,并讓Frida檢查USB設備,但它也可以與模擬器一起工作。你應該得到一個這樣的進程列表:

michael@sixtyseven:~$?frida-ps?-UPID??Name
----??--------------------------------------------------696??adbd
5828??android.ext.services
6188??android.process.acore
5210??audioserver
5211??cameraserver
8334??com.android.calendar
6685??com.android.chrome
6245??com.android.deskclock
5528??com.android.inputmethod.latin
6120??com.android.phone
6485??com.android.printspooler
8355??com.android.providers.calendar
5844??com.android.systemui
7944??com.google.android.apps.nexuslauncher
6416??com.google.android.gms
[...]

你可以看到進程標識(PID)和運行的進程(名稱)。使用Frida你現在可以Hook這些進程,并且可以篡改進程。

例如,你可以跟蹤Chrome完成的特定通話(如果Chrome未運行,請先啟動模擬器里的Chrome):

frida-trace?-i?"open"?-U?com.android.chrome

命令執行結果如下:

michael@sixtyseven:~$?frida-trace?-i?open?-U?-f?com.android.chrome
Instrumenting?functions...?????????????????????????????????????????????
open:?Loaded?handler?at?"/home/michael/__handlers__/libc.so/open.js"
Started?tracing?1?function.?Press?Ctrl+C?to?stop.??????????????????????/*?TID?0x2740?*/282?ms??open(pathname=0xa843ffc9,?flags=0x80002)/*?TID?0x2755?*/299?ms??open(pathname=0xa80d0c44,?flags=0x2)/*?TID?0x2756?*/309?ms??open(pathname=0xa80d0c44,?flags=0x2)/*?TID?0x2740?*/341?ms??open(pathname=0xa80d06f7,?flags=0x2)592?ms??open(pathname=0xa77dd3bc,?flags=0x0)596?ms??open(pathname=0xa80d06f7,?flags=0x2)699?ms??open(pathname=0xa80d105e,?flags=0x80000)717?ms??open(pathname=0x9aff0d70,?flags=0x42)742?ms??open(pathname=0x9ceffda0,?flags=0x0)758?ms??open(pathname=0xa63b04c0,?flags=0x0)

frida-trace命令會生成一些JavaScript文件,Frida會將這些JavaScript文件注入到進程中并跟蹤特定的調用。看看生成的open.js腳本文件(__handlers__/libc.so/open.js)。它Hook了libc.so中的“open”函數并輸出一些參數。這在Frida中很容易就可以實現:

[...]
onEnter:?function?(log,?args,?state)?{log("open("?+?"pathname="?+?args[0]?+?",?flags="?+?args[1]?+?")");
},
[...]

請注意,Frida可以訪問到Chrome內部調用的open函數(args [0],args [1]等等)的一些調用參數。讓我們修改一下這個腳本。如果我們明文輸出打開的文件的路徑,而不是存儲這些路徑的內存地址,這樣不是更好嗎?幸運的是,我們可以直接用Frida訪問內存。看看Frida API和Memory對象。我們可以修改腳本,將內存地址所指向的內容輸出為UTF8字符串,可以獲得更清楚明了的輸出。修改腳本后,如下所示:

onEnter:?function?(log,?args,?state)?{
log("open("?+?"pathname="?+?Memory.readUtf8String(args[0])+?",?flags="?+?args[1]?+?")");?},

(我們剛剛添加了Memory.readUtf8String函數)我們得到如下輸出結果:

michael@sixtyseven:~$?frida-trace?-i?open?-U?-f?com.android.chrome
Instrumenting?functions...?????????????????????????????????????????????
open:?Loaded?handler?at?"/home/michael/__handlers__/libc.so/open.js"
Started?tracing?1?function.?Press?Ctrl+C?to?stop.??????????????????????/*?TID?0x29bf?*/240?ms??open(pathname=/dev/binder,?flags=0x80002)/*?TID?0x29d3?*/259?ms??open(pathname=/dev/ashmem,?flags=0x2)/*?TID?0x29d4?*/269?ms??open(pathname=/dev/ashmem,?flags=0x2)/*?TID?0x29bf?*/291?ms??open(pathname=/sys/qemu_trace/process_name,?flags=0x2)453?ms??open(pathname=/dev/alarm,?flags=0x0)456?ms??open(pathname=/sys/qemu_trace/process_name,?flags=0x2)562?ms??open(pathname=/proc/self/cmdline,?flags=0x80000)576?ms??open(pathname=/data/dalvik-cache/arm/system@app@Chrome@Chrome.apk@classes.dex.flock,?flags=0x42)

Frida打印路徑名很容易,不是嗎?

另外需要注意的是,你可以先啟動一個應用程序,然后再讓Frida進行注入,或者使用-f選項,讓Frida自動生成進程。

現在我們來看看Frida的命令行界面frida-cli:

frida?-U?-f?com.android.chrome

這將啟動Frida和Chrome應用。但是,它還沒有啟動Chrome的主進程。這意味著可以在應用程序的主進程啟動之前注入Frida代碼。不幸的是,在我自己的嘗試中總是遇到一個問題——應用程序在啟動2秒鐘后自動卡死。這不是我們想要的。你可以使用這兩秒來鍵入%resume,如cli輸出的建議,讓應用程序啟動其主進程。或者你直接啟動Frida,使用–no-pause參數選擇不中斷應用程序的啟動,仍然將進程的產生留給Frida去做。

安卓APP破解利器之FRIDA

在這兩種情況下,你都可以獲得一個shell(不會被殺死),你現在可以使用其Javascript API向Frida寫入命令。按TAB鍵可以查看可用的命令。shell還支持命令自動完成。

安卓APP破解利器之FRIDA

你想做的大多數事情在文檔中都是有據可查的。對于Android,特別要檢查Javascript-API?的Java部分(我將在此討論一個“Java API”,盡管在技術上說,是一個用于訪問Java對象的Javascript封裝)。我們將重點關注Java API,因為這是使用Android應用程序更為方便的方式。我們可以直接使用Java函數和對象,而不是Hook libc中的函數。(注意:如果你對Frida的其他的Java API能做什么很感興趣,那么你可以使用frida-trace Hook Android里面的更低級的C函數,并且查看文檔里的函數部分,我不會按照文檔所述那樣在本文中進行描述。)

要開始Java API訪問,只需從Frida的命令行界面顯示正在運行的Android版本:

[USB::Android?Emulator?5556::['com.android.chrome']]->?Java.androidVersion
"7.1.1"

或列出已加載的類(警告:此處會輸出很多內容,后面我會解釋代碼的意思。):

[USB::Android?Emulator?5556::['com.android.chrome']]->?Java.perform(function(){Java.enumerateLoadedClasses({"onMatch":function(className){?console.log(className)?},"onComplete":function(){}})})
org.apache.http.HttpEntityEnclosingRequest
org.apache.http.ProtocolVersion
org.apache.http.HttpResponse
org.apache.http.impl.cookie.DateParseException
org.apache.http.HeaderIterator

我們在這里輸入了相當長的命令,一些嵌套的函數代碼的意思也很明確。請注意,我們輸入的代碼被封裝在Java.perform(function(){ … }) 中,這些代碼是調用Fridas Java API所需要的。

這是我們在Java.perform包裝器中插入的函數的主體:

Java.enumerateLoadedClasses({"onMatch":?function(className){console.log(className)},"onComplete":function(){}}
)

很簡單:我們使用Java.enumerateLoadedClassesFridas API 枚舉所有加載的類,并將每個匹配到的類使用console.log輸出到控制臺。這種回調對象的模式你會經常在Frida找到。你需要提供一個回調對象的模板。

{"onMatch":function(arg1,?...){?...?},"onComplete":function(){?...?},
}

一旦Frida匹配到你的請求,就會使用一個或多個參數調用onMatch并且當Frida完成迭代可能的匹配時,將會調用onComplete。

現在我們深入了解了Frida的魔法,并且使用Frida重寫了一個函數。此外,我們還從外部腳本加載了代碼,而不是將其輸入到cli中,這樣做更方便。將以下代碼保存到腳本文件中,例如chrome.js:

Java.perform(function?()?{var?Activity?=?Java.use("android.app.Activity");Activity.onResume.implementation?=?function?()?{console.log("[*]?onResume()?got?called!");this.onResume();};
});

該代碼重寫了android.app.Activity類的onResume函數。它調用Java.use接收此類的包裝對象并訪問implementation的onResume函數的屬性以提供新的實現。在新的函數主體內,它this.onResume()這樣的方式調用原來的onResume的實現,所以應用程序可以繼續正常運行。

打開你的模擬器,打開Chrome并用-l選項注入腳本:

frida?-U?-l?chrome.js?com.android.chrome

一旦你觸發了onResume的執行—— 例如通過在模擬器中切換到另一個應用程序并返回到Chrome后你將得到下面的輸出:

[*]?onResume()?got?called!

很好用,不是嗎?我們實際上重寫了應用程序的一個函數。這給了我們控制目標應用程序行為的很多可能性。但是我們可以做更多的事情:我們也可以在堆上查找實例化的對象Java.choose。

在我們繼續之前,我有一個警告:當你的模擬器變得有點慢的時候,Frida有時候會有時間超時的提示。為了防止這種情況,請將腳本包裝在setImmediate函數中或將其導出為rpc。RPC在Frida中默認情況下不會超時( 感謝@oleavr的這些提示)。在你修改腳本文件后,setImmediate會自動重新運行Frida腳本,這樣很方便。它也會在后臺運行你的腳本。這意味著你可以立即得到一個cli,即使Frida仍在處理你的腳本。你只需要繼續等待,不要離開cli,直到Frida向你顯示了腳本的輸出。

再次修改chrome.js:

setImmediate(function()?{console.log("[*]?Starting?script");Java.perform(function?()?{Java.choose("android.view.View",?{"onMatch":function(instance){console.log("[*]?Instance?found");},"onComplete":function()?{console.log("[*]?Finished?heap?search")}});});
});

使用frida -U -l chrome.js com.android.chrome運行它將產生以下輸出:

[*]?Starting?script
[*]?Instance?found
[*]?Instance?found
[*]?Instance?found
[*]?Instance?found
[*]?Finished?heap?search

所以我們在堆上發現了4個android.view.View對象的實例。讓我們看看我們可以做些什么。也許我們可以調用這些對象實例的方法。我們這次只添加instance.toString()到我們的console.log進行輸出(由于我們使用了setImmediate,所以我們現在可以修改我們的腳本,Frida將自動重新加載腳本文件):

setImmediate(function()?{console.log("[*]?Starting?script");Java.perform(function?()?{Java.choose("android.view.View",?{"onMatch":function(instance){console.log("[*]?Instance?found:?"?+?instance.toString());},"onComplete":function()?{console.log("[*]?Finished?heap?search")}});});
});

執行腳本會后返回如下結果:

[*]?Starting?script
[*]?Instance?found:?android.view.View{7ccea78?G.ED.....?......ID?0,0-0,0?#7f0c01fc?app:id/action_bar_black_background}
[*]?Instance?found:?android.view.View{2809551?V.ED.....?........?0,1731-0,1731?#7f0c01ff?app:id/menu_anchor_stub}
[*]?Instance?found:?android.view.View{be471b6?G.ED.....?......I.?0,0-0,0?#7f0c01f5?app:id/location_bar_verbose_status_separator}
[*]?Instance?found:?android.view.View{3ae0eb7?V.ED.....?........?0,0-1080,63?#102002f?android:id/statusBarBackground}
[*]?Finished?heap?search

Frida實際上調用了android.view.View對象實例的toString方法。很酷哦。因此,通過Frida的幫助,我們可以讀取進程內存,修改函數,查找實際的對象實例,并使用少量的幾行代碼。

現在你應該對Frida有了基本的了解了,并能夠自己深入了解其文檔和API。為了完成這篇文章,我想再談兩個主題,Frida的綁定和r2frida。但首先會有一點警告。

警告

當你嘗試使用Frida時,你會注意到有一些不穩定。首先,將外部代碼注入到另一個進程中容易導致崩潰,因為應用程序被以意想不到的方式觸發運行。第二,Frida本身仍然讓人感覺為一個實驗品。有時候它的確在正常工作,但你經常需要嘗試多種方式來獲得你所需的結果。例如,當我嘗試加載一個腳本并在命令行中執行一個命令生成一個進程時,Frida就會一直崩潰。相反,我必須首先啟動該進程,然后讓Frida去注入腳本。這就是為什么我向你展示了使用Frida的各種方法,并防止超時失敗的提示出現。你可能需要弄清楚在你的實際情況下哪個才是最有效的方法。

Python綁定

一旦了解了Frida的工作原理之后,如果你想要使用Frida更自動化的完成你的工作,你應該查看易于使用的Python,C或NodeJS 綁定。例如從Python 中注入chrome.js腳本,你可以使用Frida的Python綁定并創建一個chrome.py腳本:

#!/usr/bin/python
import?frida
#?put?your?javascript-code?here
jscode=?"""
console.log("[*]?Starting?script");
Java.perform(function()?{var?Activity?=?Java.use("android.app.Activity");Activity.onResume.implementation?=?function?()?{console.log("[*]?onResume()?got?called!");this.onResume();};
});
"""
#?startup?frida?and?attach?to?com.android.chrome?process?on?a?usb?device
session?=?frida.get_usb_device().attach("com.android.chrome")
#?create?a?script?for?frida?of?jsccode
script?=?session.create_script(jscode)
#?and?load?the?script
script.load()

如果要結束Frida會話并銷毀本次會話的腳本,可以調用session.detach()。

有關更多的例子,還是一如以往的請查看Frida的文檔。

Frida和Radare2:r2frida

如果我們也可以使用像Radare2這樣的反匯編框架來檢查我們的應用程序的內存,那不是很好嗎?在這里是r2frida。你可以使用r2frida將Radare2連接到Frida,并進行進程內存的靜態分析和反匯編。我不會在這里詳細介紹r2frida,因為它的使用本身就預先假定了使用者具備Radare2的知識(如果你沒有一定的相關知識,那非常值得一看。),但是我仍然想給你一個使用簡便的方式。

你可以使用Radare2的包管理器來安裝r2frida(假設你已經安裝了Radare2):

r2pm?install?r2frida

回到我們的frida跟蹤示例,刪除或重命名我們修改過的腳本,frida-trace會再次生成默認的腳本,并再次查看日志會有下面的輸出:

michael@sixtyseven:~$?frida-trace?-i?open?-U?-f?com.android.chrome
Instrumenting?functions...?????????????????????????????????????????????
open:?Loaded?handler?at?"/home/michael/__handlers__/libc.so/open.js"
Started?tracing?1?function.?Press?Ctrl+C?to?stop.??????????????????????/*?TID?0x2740?*/282?ms??open(pathname=0xa843ffc9,?flags=0x80002)/*?TID?0x2755?*/[...]

使用r2frida,你可以輕松的檢查顯示的內存地址并讀取路徑名(在這種情況下為/dev/binder):

root@sixtyseven:~#?r2?frida://emulator-5556/com.android.chrome--?Enhance?your?graphs?by?increasing?the?size?of?the?block?and?graph.depth?eval?variable.
[0x00000000]>?s?0xa843ffc9
[0xa843ffc9]>?px
-?offset?-???0?1??2?3??4?5??6?7??8?9??A?B??C?D??E?F??0123456789ABCDEF
0xa843ffc9??2f64?6576?2f62?696e?6465?7200?4269?6e64??/dev/binder.Bind
0xa843ffd9??6572?2069?6f63?746c?2074?6f20?6f62?7461??er?ioctl?to?obta
0xa843ffe9??696e?2076?6572?7369?6f6e?2066?6169?6c65??in?version?faile
0xa843fff9??643a?2025?7300?4269?6e64?6572?2064?7269??d:?%s.Binder?dri
[...]

訪問進程并讓r2frida執行注入的命令語句為

r2?frida://DEVICE-ID/PROCESS

還可以使用=!前綴檢查可用的r2frida命令,以及哪些可以在內存區域快速搜索指定內容或寫入任意內存地址的命令等等?

[0x00000000]>?=!?
r2frida?commands?available?via?=!
???????????????????????????Show?this?help
?V?????????????????????????Show?target?Frida?version
/[x][j]?<string|hexpairs>??Search?hex/string?pattern?in?memory?ranges?(see?search.in=?)
/w[j]?string???????????????Search?wide?string
[...]

更多

如果這讓你感到好奇,可以看看下面的內容:

?1.?Frida的項目頁面

?2. @oleavr在r2con的演講視頻 和David Weinstein對Frida簡介的演講。

?3. Frida的Twitter帳號@fridadotre

?4. Frida的Telegram頻道

?5. AppMon——基于Frida的應用程序監視和注入的GUI工具(由@dpnishant提供)

在本教程的第二部分,我們將使用Frida來輕松解決一些小問題。




原文發布時間為:2017年4月14日
本文作者:絲綢之路?
本文來自云棲社區合作伙伴嘶吼,了解相關信息可以關注嘶吼網站。
原文鏈接

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455005.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455005.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455005.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何獲取option的下標和值_數智化時代下,如何獲取企業增長密碼?

信息化時代下&#xff0c;很多企業前前后后上線了各種信息化系統&#xff0c;ERP、OA、CRM…隨著企業數字化的深入推進&#xff0c;“移動互聯網、云計算、大數據、人工智能、物聯網、區塊鏈”等技術的革新&#xff0c;這些信息化系統難以滿足企業對數智化轉型的新需求&#xf…

解決Gorm中使用Count后關聯查詢失效的問題

解決Gorm中使用Count后關聯查詢失效的問題 問題描述 當我們 在go中使用gorm進行多表join關聯查詢的時候 如果還有分頁的需求 那么可能會是這樣寫 package mainimport ("gorm.io/driver/mysql""gorm.io/gorm"ormLogger "gorm.io/gorm/logger"…

hdu1540/poj2892 線段數區間合并

HDU - 1540 POJ - 2892 題意&#xff1a;n個點&#xff0c;有3種操作D a表示摧毀a這個點&#xff0c;R 表示修復上一個點&#xff0c;Q x表示查詢x所在的區間沒被摧毀的連續最大區間 思路&#xff1a;線段樹區間合并&#xff0c;區間合并主要就是對lsum rsum 和sum的動態維護&…

基于51單片機的交通燈控制設計

課程設計任務書及成績 課程名稱 單片機課程設計 題目 交通燈控制設計 課程設計目標與任務、計劃與進度安排: 實踐教學要求與任務: 1、了解交通燈的基本工作原理&#xff1b; 2、用Proteus模擬實現交通燈控制&#xff1b; 3、用Keil C51編程實現上述功能&#xff1b; 4、…

福斯i6飛行模式設置_數據網絡卡的時候,不妨試試“開關飛行模式”?上網速度明顯變快...

相信大家都有過這種經歷&#xff0c;手機數據網速很慢的時候&#xff0c;開一下飛行模式再關閉&#xff0c;上網速度會比之前快很多&#xff0c;這就有人有了疑問&#xff0c;為什么呢&#xff1f;開飛行模式再關掉飛行模式&#xff0c;其實等于是完成了一次手動的小區重選。移…

安裝開源 ITIL 門戶 iTOP

在 CentOS 7 上部署iTOP是一個簡單的基于Web的開源IT服務管理工具。它有所有的ITIL功能&#xff0c;包括服務臺、配置管理、事件管理、問題管理、變更管理和服務管理。iTOP依賴于Apache/IIS、MySQL和PHP&#xff0c;因此它可以運行在任何支持這些軟件的操作系統中。因為iTOP是一…

基于FPGA 的8b10b編解碼電路前端電路設計

基于FPGA 的8b10b編解碼電路前端電路設計 摘 要 本設計是采用EDA技術設計的一種8B /10B 編解碼電路,實現了在高速的串行數據傳輸中的直流平衡。該編解碼電路設計大體上可以由五個模塊構成&#xff0c;分別是默認編碼模塊、差異度計算模塊、編碼校正模塊、并串轉換模塊、顯示模…

day15(mysql 的多表查詢,事務)

mysql之多表查詢 1.合并結果集 作用:合并結果集就是把兩個select語句查詢的結果連接到一起&#xff01; /*創建表t1*/ CREATE TABLE t1(a INT PRIMARY KEY ,b VARCHAR(10) ) INSERT INTO t1 VALUES(1,a); INSERT INTO t1 VALUES(2,b); INSERT INTO t1 VALUES(3,c); /*創建t2*/…

vue router傳參_新手使用vue-router傳參時注意事項

1. 使用name和params組合傳參this.$router.push({name: details, params: {id: 233}})路由配置import Vue from vueimport Router from vue-router Vue.use(Router) export default new Router({ mode: history, routes: [ { path: /details, name: details, component: resolv…

FFMpeg分析詳細分析

與其說是分析&#xff0c;不如說是學習&#xff0c;只是看在自己第一次寫系列文章的份上&#xff0c;給足自己面子&#xff0c;取個有"深度"的題目&#xff01;如有人被題目所蒙騙進來&#xff0c;還望見諒&#xff01; URLProtocol,URLContext和ByteIOContext是FFMp…

《jQuery基礎》總結

目前&#xff0c;互聯網上最好的jQuery入門教材&#xff0c;是Rebecca Murphey寫的《jQuery基礎》&#xff08;jQuery Fundamentals&#xff09;。這本書雖然是入門教材&#xff0c;但也足足有100多頁。我對它做了一個詳細的筆記&#xff0c;試圖理清jQuery的設計思想&#xff…

邏輯綜合工具DesignCompiler使用教程

邏輯綜合工具Design Compiler使用教程 圖形界面design vision操作示例 邏輯綜合主要是將HDL語言描述的電路轉換為工藝庫器件構成的網表的過程。綜合工具目前比較主流的是synopsys公司Design Compiler&#xff0c;我們在設計實踐過程中采用這一工具。Design compiler有兩種工作…

遍歷結構體_三菱ST語言編程(3)——結構體變量

上篇文章介紹了數組&#xff0c;是一組相同類型數據的列表&#xff0c;那么不同類型的數據能否組合到一起用一個標簽表示呢&#xff1f;答案當然是可以的&#xff0c;而實現這個功能的就是結構體(struct)。建立結構體在三菱結構化編程的界面中左側程序部件里可以找到結構體標簽…

關于微信小程序swiper的問題

關于小程序swiper的問題 代碼 在官方示例上給swiper添加了currentbindchangecircular添加了一個buttonbindtap用于切換下一張 index.wxml <swiper indicator-dots"{{indicatorDots}}"bindchange"swiperChange"current"{{index}}"circular&quo…

PyQt5案例匯總(完整版)

個人博客點這里 PyQt5案例匯總(完整版) 起步 PyQt5是一套綁定Qt5的應用程序框架。他在Python 2.x和3.x中都是可用的。該教程使用的是Python3.x。 Qt庫是一套最有用的GUI庫。 PyQt5是作為一套Python模塊實現的。他已經超過620個類和6000個函數與方法。他是一個運行在所有主…

中的 隱藏鼠標菜單_Mac移動隱藏刪除頂部菜單欄圖標教程

蘋果菜單欄貫穿 Mac 的屏幕頂部。左側是蘋果菜單和應用菜單&#xff0c;應用菜單一般顯示你當前使用的Mac軟件的所有功能菜單。右側通常是以圖標顯示的狀態菜單&#xff0c;幫助你快速查看Mac的狀態以及快速訪問某些Mac軟件。移動圖標位置若想要重新排列狀態菜單欄的圖標&#…

可以用什么代替平面鏡

答案是鏡面 潛望鏡是利用平面鏡來改變光路轉載于:https://www.cnblogs.com/lidepeng/p/7280593.html

[hadoop] kettle spoon 基礎使用 (txt 內容抽取到excel中)

spoon.bat 啟動kettle。 測試數據 1. 新建轉換 輸入中選擇文本文件輸入 雙擊設置文本輸入 字符集、分隔符設置 獲取對應的字段&#xff0c;預覽記錄。 拖入 excel輸出&#xff0c;設置轉換關系 設置輸出路徑 獲取字段 啟動轉換 導入的excel數據&#xff08;設置好格式,圖中ID,A…

ffmpeg提取音頻播放器總結

ffmpeg提取音頻播放器總結&#xff1b; 一&#xff1a;簡介 從編寫音頻播放器代碼到完成播放器編寫&#xff0c;測試&#xff0c;整整5天的時間&#xff0c;這時間還不算之前對 ffmpeg熟悉的時間&#xff0c;可以說是歷經千辛萬苦&#xff0c;終于搞出來了&#xff0c;雖然最…

【BZOJ 4103】 [Thu Summer Camp 2015]異或運算 可持久化01Trie

我們觀察數據&#xff1a;樹套樹 PASS 主席樹 PASS 一層一個Trie PASS 再看&#xff0c;異或&#xff01;我們就把目光暫時定在01Tire然后我們發現&#xff0c;我們可以帶著一堆點在01Trie上行走&#xff0c;因為O(n*q*30m*30)是一個可選復雜度。 我們想一下我們正常的時候…