欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4175|回復: 0
打印 上一主題 下一主題
收起左側

從單片機指針說到黑客程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:51472 發表于 2013-7-9 03:16 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
2004年7月的一天,在電子BBS討論區上溜達,看到一個有趣的帖子,整個帖子內容如下:

純C51復位功能函數:一個大三學生,讓人又愛又怕

現單列復位部分如下:

main()

{

   unsigned char code rst[]={0xe4,0xc0,0xe0,0xc0,0xe0,0x32};  // 復位代碼

   (*((void (*)())(rst)))();  // 執行上一行代碼,將rst數組當函數調用

}

本來我告訴他嵌入如下代碼:

clr a

push acc

push acc

reti

結果他卻玩了前面哪一段,而數組rst[]中的內容恰恰是上面的匯編機器碼,他的做法是將rst數組的數據當作代碼保存,然后采用絕對地址方式指向該數組,將該數組中的代碼當作函數來運行。居然通過了!

我覺得有問題,我說即使如此,那絕對地址調用也應該寫成(*((void (*)())(&rst)))() 才對呀,結果他反駁說,那樣的話,rst的地址就會當成參數傳遞給這個絕對地址函數,而實際LJMP調用的地址并非rst的地址,而是一個不確定的地址。于是我按照自己的說法嘗試了一下,看看匯編結果,還真的是將rst的地址傳遞給了R1 R2,而絕對函數最終LJMP到了一個莫名其妙的地址上去了,死翹!

看來C真是一匹不容易駕馭的野馬,這個大三學生理解力在我之上,我30多歲的人了,干了這么多年還沒他的境界呢,唉,人家才學了幾天啊,翻了幾天書就這么厲害了,服了!

l         首先分析帖子的C語言代碼

第一句定義一個數組rst[],數組內數據就是完成復位功能的匯編機器碼,具體對應關系為:clr a == 0xe4、push acc == 0xc0,0xe0、reti ==0x32

第二句是一個函數指針的用法,函數指針用法稍微有點復雜,可參看本人著的書,:),以下為快速入門講解。

定義一個返回值是空函數指針的定義形式如下:

void (*p) ( )

當把函數指針賦值后,就能通過函數指針調用函數,調用形式如下,

      (*p) ( );

或等價的簡化形式:

p ( );

假設rst就是函數指針,則如下調用形式就可以令單片機復位再起。

(*rst ) ( );  

但可惜,rst不是函數指針,而是數組名,雖然兩者都是地址,但不可直接調用數組名。

如同把char型變量a賦值給int型變量b,(int) 表示強制類型轉換:

b = (int) a

函數指針的強制類型轉換公式如下(C語言的哲學是定義形式和使用一致):

(  (void (*)()  ) rst

這樣經過轉換后的rst就可以當作函數指針使用了,簡單的調用形式如下:

#define  K     (  (void (*)( )  ) rst

(*K) ( )

或:

(     * (  void (*)( )  )rst      ) ( );

這樣的語句就完成復位再啟功能了。類型轉換符()的優先級跟指針運算符*的優先級相同,二者的結合方向是自右至左,所以上述語句就能完成復位功能了。保險起見有些程序員常常喜歡再加個括號:

#define  K     (   (  (void (*)( )  ) rst   )

(*K) ( )



(     *(   (  void (*)( )  )rst   )    ) ( );



由于沒有輸入參數,上述復位代碼更嚴謹的寫法是:

#define  K     (   (  (void (*)(void )  ) rst   )

(*K) ( )



(     *(   (  void (*)(void )  )rst   )    ) ( );


l         關于帖子作者的解釋

千萬不要犯“&rst”形式的錯誤,對于一維數組而言,數組名rst就代表地址。以下二者等
價,更常用的是等式左邊的形式:

rst == &rst[0]

整個函數指針無所謂參數傳遞,只是把rst當作程序執行地址調用而已,那個學生的解釋也有問題。

還有一點必須提及,不是說能通過編譯,甚至生成正確代碼,就表示某語句一定是對的。對很復雜的語句,要考慮到編譯器不嚴格甚至出錯的可能性。

l         哈佛結構和一個蠕蟲病毒

請注意,定義數組rst[]時用了關鍵字code,這是C51特有的關鍵字,意味著把數組定義到程序空間。標準C是沒有關鍵字code的。

哈佛結構和普林斯頓結構:

哈佛結構——程序空間和存儲空間分開的。C51算是不太嚴格的哈佛結構——雖地址線分開,但數據線沒有分開。DSP是增強的哈佛結構。

PC電腦上奔騰CPU是普林斯頓結構——數據空間和程序空間統一編址。

如果數組rst[]數據的匯編機器碼是刪除文件的機器碼,這算不算是病毒?

曾經流行過一種蠕蟲病毒,其發作機理采取的就是將惡意代碼保存成文本文件,然后通過指針調用執行這個文本,很多殺毒程序也不會查詢文本文件。

程序也罷,數據也罷都是二進制形式,如果數據空間和程序空間是統一編碼的, 數據當然可以當作程序運行。

在這一點上,相對而言,哈佛結構的CPU安全性會好一點點。但嵌入式應用少有病毒,一般不用關心。



l         單片機復位的更好方法

帖子中匯編語言解釋如下:

clr a                      //清除ACC=0

push acc               //壓0到堆棧——8位

push acc               //再壓0到堆!8位

reti                        //返回到0地址,從而執行。

帖子作者的這種復位方法比較麻煩,更加簡單的復位寫法是(摘自《C缺陷與陷阱》):

(     * (  void (*)( )  )0      ) ( );

本句的分析方法同上,但更加精煉,沒有多余的匯編語句。

上述復位的方法可稱為軟件復位。

軟件復位跟真正上電復位有很大差別:上電復位時大部分寄存器都有確定的復位值;軟件復位則只相當于從0地址開始執行而已,寄存器不會變為確定的復位值。
如果用戶要編程實現上電復位這種情況,在程序中不要踢看門狗即可。大部分單片機都有看門狗吧。

l         附錄

筆者精于DSP C24xx,但不太懂C51;讀者應能從函數指針的定義和引用中看出來,C語言的設計哲學是使用形式和定義形式一致,雖然這一點飽受質疑。

如果你覺得雞蛋好吃時,不必認識那只母雞;但如果你覺得本文不錯,請來筆者網站坐坐。

可來信免費轉載本文,請保持整篇文章的完整性,包括本句。            
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂1 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表