不同存储区域的数组分析
下面對放在三個不同存儲區的數組進行簡要的分析
(1)??? 對全局數組進行分析
#include <cstdio>
#include <iostream>
using namespace std;
?
int global_array[3];
?
int main()
{
??? int idx = 2;
??? global_array[0] = 10;
??? global_array[1] = 20;
??? global_array[2] = 30;
??? global_array[idx] = 40;
???
??? return 0;
}
對全局數組來說,相信大家都知道是放在靜態存儲區的,就是說在編譯時就可以獲知該數組的基址,由于基址固定,編譯器就可以計算出使用固定索引訪問的任何數組元素的固定地址,從這一點可以看出,如果要對程序做出一些保密性措施,就可能對全局變量進行一些隱藏,具體的做法我也不知道,但盡量少定義一些比較重要的全局數組還是有好處的。
這里需要注意兩點。
第一,使用常量索引訪問全局數組時,在對應的反匯編代碼清單中,對應的數組元素以全局變量的形式出現。換句話說,反匯編代碼清單基本上不提供任何數組存在的證據。
第二,使用可變索引值將帶領我們來到數組的開頭,因為在計算要訪問的數組元素的具體地址時,需要用到數組的基址加上相應的偏移量,此時基址即呈現出來。
從第一點來看好像對以全局數組可以進行隱藏,但在實際當中有可能恰恰相反,因為第二點可以看出對可變索引值進行訪問時就能夠得到數組的基址。相信大家在使用全局數組時都不會元素個數很小的,一般全局數組都是用來節省內存空間才采用的一種方法,所以說以常量索引訪問全局數組幾乎是不可能的。
.text:00401030?????????????????? ; =============== S U B R O U T I N E =======================================
.text:00401030
.text:00401030?????????????????? ; Attributes: bp-based frame
.text:00401030
.text:00401030?????????????????? _main_0 proc near???????????? ; CODE XREF: _mainj
.text:00401030
.text:00401030????? ?????????????var_44= byte ptr -44h
.text:00401030?????????????????? var_4= dword ptr -4
.text:00401030
.text:00401030 55??????????????? push??? ebp
.text:00401031 8B EC???????????? mov???? ebp, esp
.text:00401033 83 EC 44????? ????sub???? esp, 44h
.text:00401036 53??????????????? push??? ebx
.text:00401037 56??????????????? push??? esi
.text:00401038 57??????????????? push??? edi
.text:00401039 8D 7D BC????????? lea???? edi, [ebp+var_44]
.text:0040103C B9 11 00 00 00??? mov???? ecx, 11h
.text:00401041 B8 CC CC CC CC??? mov???? eax, 0CCCCCCCCh
.text:00401046 F3 AB???????????? rep stosd
.text:00401048 C7 45 FC 02 00 00+mov???? [ebp+var_4], 2? //為局部
變量idx賦值為2
.text:0040104F C7 05 0C 2E 43 00+mov???? dword_432E0C, 0Ah? //從
這里以后的三行可以看出來全局數組的地址在編譯時候就能夠確定,
此時的基址應該是0x00432E0C。紅色標記。
.text:00401059 C7 05 10 2E 43 00+mov???? dword_432E10, 14h
.text:00401063 C7 05 14 2E 43 00+mov???? dword_432E14, 1Eh
.text:0040106D 8B 45 FC????????? mov???? eax, [ebp+var_4]? //把idx存儲到eax寄存器中,用來進行偏移量計算。
.text:00401070 C7 04 85 0C 2E 43+mov???? dword_432E0C[eax*4], 28h
基址加上偏移量就可以定位數組的元素的下標。eax * 4,4表示數組元素的大小,這里千萬不能夠就認為是int型的,具體情況具體分析。
.text:0040107B 33 C0???????????? xor???? eax, eax
.text:0040107D 5F??????????????? pop???? edi
.text:0040107E 5E??????????????? pop???? esi
.text:0040107F 5B??????????????? pop???? ebx
.text:00401080 8B E5???????????? mov???? esp, ebp
.text:00401082 5D??????????????? pop???? ebp
.text:00401083 C3??????????????? retn
.text:00401083?????????????????? _main_0 endp
.text:00401083
.text:00401083?????????????????? ; ---------------------------------------------------------------------------
(2)??? 對棧分配的數組進行分析
#include <cstdio>
#include <iostream>
using namespace std;
?
int main()
{
int stack_array[3];
int idx = 2;
stack_array[0] = 10;
stack_array[1] = 20;
stack_array[2] = 30;
stack_array[idx] = 40;
???
return 0;
}
從下面的代碼我們可以看出,編譯器幾乎以完全相同的方式處理棧分配的數組和全局分配的數組。由于在編譯時候并不能夠知道棧分配數組的基址,所以在程序中并沒有像在全局數組中一樣給出第一個元素的地址,所以對于常量索引訪問數組時我們還是不能夠快速判斷程序中是否使用了數組,因為常量索引訪問數組與局部變量的使用看不出有什么區別,但這個不用過于擔心,因為常量索引訪問數組是很少的。如果數組元素才幾個,那還不如直接定義變量進行操作可能更簡單。從下面的反匯編代碼可以得到一些額外的信息,根據棧中idx的位置可以推斷出,以var_C開始的數組最多包含3個元素(否則,它將覆蓋idx),如果對緩沖區溢出有比較深刻的了解的話,可以很清楚的知道這里就可以使該數組溢出,并破壞其后的數據,到底需要在數組中填充多少數據,對于緩沖區溢出的判斷和怎么去利用我還是菜鳥,不懂得,以后有學習之后再來補充相關的知識和應用。
.text:00401030?????????????????? ; =============== S U B R O U T I N E =======================================
.text:00401030
.text:00401030?????????????????? ; Attributes: bp-based frame
.text:00401030
.text:00401030?????????????????? _main_0 proc near???????????? ; CODE XREF: _mainj
.text:00401030
.text:00401030??????????? ???????var_50= byte ptr -50h
.text:00401030?????????????????? var_10= dword ptr -10h
.text:00401030?????????????????? var_C= dword ptr -0Ch
.text:00401030?????????????????? var_8= dword ptr -8
.text:00401030?????????????????? var_4= dword ptr -4
.text:00401030
.text:00401030 55??????????????? push??? ebp
.text:00401031 8B EC???????????? mov???? ebp, esp
.text:00401033 83 EC 50????????? sub???? esp, 50h
.text:00401036 53??????????????? push??? ebx
.text:00401037 56??????????????? push??? esi
.text:00401038 57??????????????? push??? edi
.text:00401039 8D 7D B0????????? lea???? edi, [ebp+var_50]
.text:0040103C B9 14 00 00 00??? mov???? ecx, 14h
.text:00401041 B8 CC CC CC CC??? mov???? eax, 0CCCCCCCCh
.text:00401046 F3 AB???????????? rep stosd
.text:00401048 C7 45 F0 02 00 00+mov???? [ebp+var_10], 2
.text:0040104F C7 45 F4 0A 00 00+mov???? [ebp+var_C], 0Ah ?//這里只能夠用var_C來表示,并不像全局數組那樣用地址表示。
.text:00401056 C7 45 F8 14 00 00+mov???? [ebp+var_8], 14h
.text:0040105D C7 45 FC 1E 00 00+mov???? [ebp+var_4], 1Eh
.text:00401064 8B 45 F0????????? mov???? eax, [ebp+var_10]
.text:00401067 C7 44 85 F4 28 00+mov???? [ebp+eax*4+var_C], 28h
基址加上偏移量就可以定位數組的元素的下標。eax * 4,4表示數組元素的大小,這里千萬不能夠就認為是int型的,具體情況具體分析。
.text:0040106F 33 C0???????????? xor???? eax, eax
.text:00401071 5F??????? ????????pop???? edi
.text:00401072 5E??????????????? pop???? esi
.text:00401073 5B??????????????? pop???? ebx
.text:00401074 8B E5???????????? mov???? esp, ebp
.text:00401076 5D??????????????? pop???? ebp
.text:00401077 C3??????????????? retn
.text:00401077?????????????????? _main_0 endp
.text:00401077
.text:00401077?????????????????? ; ---------------------------------------------------------------------------
?
(3)??? 對堆分配的數組進行分析
#include <cstdio>
#include <iostream>
using namespace std;
?
int main()
{
??? int *heap_array = (int *)malloc(3 * sizeof(int));
??? int idx = 2;
??? heap_array[0] = 10;
??? heap_array[1] = 20;
??? heap_array[2] = 30;
??? heap_array[idx] = 40;
??? return 0;
}
堆分配的數組是使用一個動態內存分配函數(如C中的malloc(對應free)或者C++中的new(new是個運算符,并不是函數,這一點需要弄明白,對應delete)。從編譯器的角度講,處理堆分配的數組的主要區別在于,它必須根據內存分配函數返回的地址值,生成對數組的所有引用。
數組的起始地址(有EAX寄存器中的malloc返回)存儲在局部變量heap_array中。每一次訪問數組是,首先必須讀取heap_array的內容,以獲得數組的基址,然后再在它上面加上一個偏移值,計算出數組中對應元素的地址。對于堆分配的數組有一個非常有用的特點。如果能夠確定數組的總大小和每個元素的大小,則可以計算出該數組有多少個元素,對堆分配的數組而言,傳遞給內存分配函數的參數(示例中式0x0C)即表示了分配給數組的字節總數,用這個除以元素大小,即可得到數組中元素的個數。
?
.text:00401030?????????????????? ; =============== S U B R O U T I N E =======================================
.text:00401030
.text:00401030?????????????????? ; Attributes: bp-based frame
.text:00401030
.text:00401030?????????????????? _main_0 proc near???????????? ; CODE XREF: _mainj
.text:00401030
.text:00401030?????????????????? var_48= byte ptr -48h
.text:00401030?????????????????? var_8= dword ptr -8
.text:00401030?????????????????? var_4= dword ptr -4
.text:00401030
.text:00401030 55??????????????? push??? ebp
.text:00401031 8B EC???????????? mov???? ebp, esp
.text:00401033 83 EC 48????????? ?sub???? esp, 48h
.text:00401036 53??????????????? push??? ebx
.text:00401037 56??????????????? push??? esi
.text:00401038 57??????????????? push??? edi
.text:00401039 8D 7D B8????????? lea???? edi, [ebp+var_48]
.text:0040103C B9 12 00 00 00??? ?mov???? ecx, 12h
.text:00401041 B8 CC CC CC CC??? mov???? eax, 0CCCCCCCCh
.text:00401046 F3 AB???????????? rep stosd
.text:00401048 6A 0C????????? push??? 0Ch??????????????? ; Size
.text:0040104A E8 41 71 00 00??? ?call??? _malloc
.text:0040104F 83 C4 04????????? add???? esp, 4
.text:00401052 89 45 FC????????? mov???? [ebp+var_4], eax? //eax寄存器返回數組的起始地址
.text:00401055 C7 45 F8 02 00 00+? mov???? [ebp+var_8], 2
.text:0040105C 8B 45 FC????????? mov???? eax, [ebp+var_4]
.text:0040105F C7 00 0A 00 00 00 ?mov???? dword ptr [eax], 0Ah
.text:00401065 8B 4D FC????????? mov???? ecx, [ebp+var_4]
.text:00401068 C7 41 04 14 00 00+? mov???? dword ptr [ecx+4], 14h
.text:0040106F 8B 55 FC????????? mov???? edx, [ebp+var_4]
.text:00401072 C7 42 08 1E 00 00+? mov???? dword ptr [edx+8], 1Eh
.text:00401079 8B 45 F8????????? mov???? eax, [ebp+var_8]
.text:0040107C 8B 4D FC????????? mov???? ecx, [ebp+var_4]
.text:0040107F C7 04 81 28 00 00+mov???? dword ptr [ecx+eax*4], 28h
.text:00401086 33 C0???????????? xor???? eax, eax
.text:00401088 5F??????????????? pop???? edi
.text:00401089 5E??????????????? pop???? esi
.text:0040108A 5B??????????????? pop???? ebx
.text:0040108B 83 C4 48????????? add???? esp, 48h
.text:0040108E 3B EC???????????? cmp???? ebp, esp
.text:00401090 E8 8B 8F 00 00??? call??? __chkesp
.text:00401095 8B E5???????????? mov???? esp, ebp
.text:00401097 5D??????????????? pop???? ebp
.text:00401098 C3??????????????? retn
.text:00401098?????????????????? _main_0 endp
.text:00401098
.text:00401098?????????????????? ; ---------------------------------------------------------------------------
?
?
學習總結:
(1)??????????????? 關于數組的使用,通過上面的分析能夠得到唯一的確定結論是:只有當變量被用作數組的索引時,才最容易確定數組的存在。但其實我們可以反過來想,一般我們寫程序使用數組都是用變量索引來訪問數組元素的,很少有常量索引來訪問數組元素,所以我們要把握重點,對于具體問題具體分析。
(2)??????????????? 要訪問數組中的元素,首先需要用索引乘以數組元素的大小,計算出相應元素的偏移量,然后將得到的偏移量與數組的基址相加,得到數組元素的訪問地址。
對于變量索引訪問數組的我們一般可以得到數組元素的大小,這一點對于分析也有一定的幫助。轉載于:https://www.cnblogs.com/StudyRush/archive/2010/10/26/1861990.html
總結
以上是生活随笔為你收集整理的不同存储区域的数组分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ORACLE的基础用法
- 下一篇: 关于clientWidth、offset