編寫 c 語言**時,指標無處不在。我們可以稍微額外利用指標,在它們內部暗中儲存一些額外資訊。為實現這一技巧,我們利用了資料在記憶體中的自然對齊特性。
記憶體中的資料並非儲存在任意位址。處理器通常按照其字大小相同的塊讀取記憶體資料;那麼考慮到效率因素,編譯器會按照塊大小的整數倍對記憶體中的實體進行位址對齊。因此在 32 位的處理器上,乙個 4 位元組整型資料肯定存放在記憶體位址能被4整除的地方。
下面,假設系統中整型資料和指標大小均為4位元組。
現在有乙個指向整型的指標。如上所述,整型資料可以存放在記憶體位址 0x1000 或者 0x1004 或者 0x1008,但是決不會存放在 0x1001 或者0x1002 或者 0x1003 或者其他不能被4整除的任何位址。所有是4整數倍的二進位制數都是以 00 結尾。實際上,這意味著對於所有指向整型的指標,它的最後兩位總是 0。
那麼有 2 位元沒有承載任何資訊。此處的技巧是將我們的資料放置到這兩個位元中,在需要時使用,並在通過指標解引用來訪問記憶體前刪除它們。
由於 c 標準對指標位操作的支援不是很好,所以我們將指標儲存為乙個無符號整型資料。
下面是一段簡短的簡單**片段。完整的**檢視 github **倉庫中的hide-data-in-ptr。?1
2345
6789
1011
1213
1415
1617
1819
2021
2223
2425
2627
2829
3031
3233
3435
3637
3839
4041
4243
4445
4647
4849
5051
5253
5455
5657
5859
6061
6263
6465
6667
6869
void
put_data(
int
*p, unsigned
int
data)
unsigned
int
get_data(unsigned
int
p)
void
cleanse_pointer(
int
*p)
int
main(
void
)
**輸出如下:?1
2345
6789
original ptr:
3216722220
ptr with data:
3216722223
data stored in ptr:
3
cleansed ptr:
3216722220
dereferencing cleansed ptr:
701
我們可以在指標中儲存任何可以用兩個位元位表示的資料。使用 put_data() 函式,設定指標的最低兩位為要儲存的資料。該資料可以使用get_data() 函式獲取。此處除了最後兩位所有的位都被覆蓋為零,於是我們隱藏的資料就顯示出來。
cleanse_pointer() 函式將最低兩位置零,保證指標安全地解引用。注意雖然有些 cpu(像 intel 允許我們訪問未對齊記憶體位址,但其餘 cpu(像 arm)會出現訪問錯誤。所以,要牢記在解引用前保證指標指向已對齊記憶體位址。
這在實際中有應用嗎?
是的,有應用。檢視 linux 核心中紅黑樹的實現(鏈結)。
樹的結點定義如下:?1
2345
6789
struct rb_node __attribute__((aligned(sizeof(
long
))));
此處 unsigned long __rb_parent_color 儲存了如下資訊:
(1)父節點的位址
(2)結點的顏色
(3)色彩的表示用 0 代表紅色,1 代表黑色。
和前面的例子一樣,該資料隱藏在父指標「無用的」位元位中。
下面看一下父指標和色彩資訊是如何獲取的:?1
23/* in rbtree.h */
#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~
3
))
?1
2345
/* in rbtree_augmented.h */
#define __rb_color(pc) ((pc) &
1
)
#define rb_color(rb) __rb_color((rb)->__rb_parent_color)
記憶體中每一位元都很珍貴,咱們永遠不要浪費。——(本文作者)
FAQ 如何在 中獲得 的指標 MFC
問 請問如何在乙個全域性函式中,獲得它檢視類,文件類得指標啊?問 如何在乙個對話方塊中,獲得它檢視類,文件類得指標啊?舉例來說,如果檢視的成員函式需要建立乙個對話方塊,而對話方塊需要訪問文件,那麼可以在對話方塊類中宣告乙個文件指標,檢視的成員函式建立對話方塊之後把對話方塊中的文件指標變數的值設定為和...
PHP 如何在Linux伺服器中隱藏PHP版本
通常,大多數預設設定安裝的web伺服器存在資訊洩露,這其中之一就是php。php 是如今流行的服務端html嵌入式語言 之一?在如今這個充滿挑戰的時代,有許多攻擊者會嘗試發現你服務端的漏洞。因此,我會簡單描述如何在linux伺服器中隱藏php資訊。預設上expose php預設是開的。關閉 expo...
如何在網際網路中隱藏自己
隨著網際網路的普及,人們對網路的依賴越來越大的同時,個人隱私洩露的風險也越來越高。不管是黑客,還是白客,灰客,抑或是普通的上網者,都希望在網際網路上保護洩漏,防止自己的隱私被他人窺竊,有的甚至希望在網際網路上隱藏自己的存在。本文就列舉幾種常用的方法 現在不管是辦理寬頻,還是辦理手機卡都需要實名制,這...