【黑客免殺攻防】讀書筆記12 - 指針與數組
阿新 • • 發佈:2018-01-15
就是 process rcp 使用 運算 邏輯 內存 2.3 [1]
1、指針與數組
C源碼
前兩組printf()函數是以指針方式訪問數組nArray中的數據的,而後兩組printf()函數則是使用數組下標的方式訪問數組nArray中的數據的。
int _tmain(int argc, _TCHAR* argv[]) { // 數組賦值 int nArray[3] = {0x10,0x20,0x300}; // 數組地址賦值給指針 int *pPtr = nArray; // 輸出指針中地址 printf("%x %x %x\r\n", pPtr+0, pPtr+1, pPtr+2); // 輸出指針指向的值 printf("%x %x %x\r\n", *(pPtr+0), *(pPtr+1), *(pPtr+2)); // 輸出數組中的地址 printf("%x %x %x\r\n", &nArray[0], &nArray[1], &nArray[2]); // 輸出數組中的值 printf("%x %x %x\r\n", nArray[0], nArray[1], nArray[2]); return 0; }
Debug匯編
對比指針訪問和數組訪問的匯編,發現用指針訪問是向後移動長度為一個int大小的距離,也就是4字節。
至於加8是因為指針的運算時以指針類型為依據的。
003CC55E mov [local.4],0x10 003CC565 mov [local.3],0x20 003CC56C mov [local.2],0x300 003CC573 lea eax,[local.4] 003CC576 mov [local.7],eax 003CC579 mov eax,[local.7] 003CC57C add eax,0x8 ; pPtr+2 003CC57C ; C語言中,指針的運算是以指針類型為依據的 003CC57C ; 一個int型指針加1,就是將其指向的地址向後移動長度為一個 003CC57C ; int大小的距離,也就是4字節。如果是Word型,那就向後移動2字節。 003CC57F push eax 003CC580 mov ecx,[local.7] 003CC583 add ecx,0x4 ; pPtr+1 003CC586 push ecx 003CC587 mov edx,[local.7] 003CC58A push edx ; pPtr+0 003CC58B push 9-44.00420C6C ; ASCII "%x %x %x\r\n" 003CC590 call 9-44.003CB0B3 003CC595 add esp,0x10 003CC598 mov eax,[local.7] ; *(pPtr+2) 003CC59B mov ecx,dword ptr ds:[eax+0x8] 003CC59E push ecx 003CC59F mov edx,[local.7] ; *(pPtr+1) 003CC5A2 mov eax,dword ptr ds:[edx+0x4] 003CC5A5 push eax 003CC5A6 mov ecx,[local.7] 003CC5A9 mov edx,dword ptr ds:[ecx] 003CC5AB push edx 003CC5AC push 9-44.00420C6C ; ASCII "%x %x %x\r\n" 003CC5B1 call 9-44.003CB0B3 003CC5B6 add esp,0x10 003CC5B9 lea eax,[local.2] ; &nArray[2] 003CC5BC push eax 003CC5BD lea ecx,[local.3] ; &nArray[1] 003CC5C0 push ecx 003CC5C1 lea edx,[local.4] ; &nArray[0] 003CC5C4 push edx 003CC5C5 push 9-44.00420C6C ; ASCII "%x %x %x\r\n" 003CC5CA call 9-44.003CB0B3 003CC5CF add esp,0x10 003CC5D2 mov eax,[local.2] ; nArray[2] 003CC5D5 push eax 003CC5D6 mov ecx,[local.3] ; nArray[1] 003CC5D9 push ecx 003CC5DA mov edx,[local.4] ; nArray[0] 003CC5DD push edx 003CC5DE push 9-44.00420C6C ; ASCII "%x %x %x\r\n" 003CC5E3 call 9-44.003CB0B3 003CC5E8 add esp,0x10 003CC5EB xor eax,eax
Release匯編
發布版的的匯編指令和debug版本相比會做一些優化的操作。
使用指針取數據和數組取數據的反匯編代碼是完全相同的。
011D1000 sub esp,0xC 011D1003 lea eax,dword ptr ss:[esp+0x8] ; pPtr+2 011D1007 push eax 011D1008 lea ecx,dword ptr ss:[esp+0x8] ; pPtr+1 011D100C push ecx 011D100D lea edx,dword ptr ss:[esp+0x8] ; pPtr+0 011D1011 push edx 011D1012 push 9-44.011DB384 ; ASCII 25,"x %x %x\r\n" 011D1017 mov dword ptr ss:[esp+0x10],0x10 ; 存放值 011D101F mov dword ptr ss:[esp+0x14],0x20 011D1027 mov dword ptr ss:[esp+0x18],0x300 011D102F call 9-44.printfc_crttProcess4lockonFilt> 011D1034 mov eax,dword ptr ss:[esp+0x18] ; *(pPtr+2) 011D1038 mov ecx,dword ptr ss:[esp+0x14] ; *(pPtr+1) 011D103C mov edx,dword ptr ss:[esp+0x10] ; *(pPtr+0) 011D1040 push eax 011D1041 push ecx 011D1042 push edx 011D1043 push 9-44.011DB384 ; ASCII 25,"x %x %x\r\n" 011D1048 call 9-44.printfc_crttProcess4lockonFilt> 011D104D lea eax,dword ptr ss:[esp+0x28] ; &nArray[2] 011D1051 push eax 011D1052 lea ecx,dword ptr ss:[esp+0x28] ; &nArray[1] 011D1056 push ecx 011D1057 lea edx,dword ptr ss:[esp+0x28] ; &nArray[0] 011D105B push edx 011D105C push 9-44.011DB384 ; ASCII 25,"x %x %x\r\n" 011D1061 call 9-44.printfc_crttProcess4lockonFilt> 011D1066 mov eax,dword ptr ss:[esp+0x38] ; nArray[2] 011D106A mov ecx,dword ptr ss:[esp+0x34] ; nArray[1] 011D106E mov edx,dword ptr ss:[esp+0x30] ; nArray[0] 011D1072 push eax 011D1073 push ecx 011D1074 push edx 011D1075 push 9-44.011DB384 ; ASCII 25,"x %x %x\r\n" 011D107A call 9-44.printfc_crttProcess4lockonFilt>
1.1 數組的不同表達方式
數組在反匯編中的表達方式一般分為一維數組、二維數組、多維數組這三種,其中一維數組和多維數組是比較難以區分的,但是可以從代碼結構和邏輯著手,進而分析出這是一個幾維數組。
在數組面對循環訪問的情況下,負責控制訪問數組成員偏移的功能由一個寄存器作為選擇子來代替。
數組的訪問會遵循以下公式:
數組成員地址 = 數組起始地址 + sizeof(數組類型) X 數組成員下標
2 數組與結構體
數組與結構體存放數據的原則都是一樣的,它們都是在一段連續的空間中存放若幹數據,唯一的不同之處在於數組存放的數據都是同一類型的,而結構體則有可能存放多種類型的數據。
C源代碼
int _tmain(int argc, _TCHAR* argv[])
{
struct _TEST
{
int nNum;
double dFloat;
char szStr[0x10];
}stcTEST;
stcTEST.nNum = 0xAAAA;
stcTEST.dFloat = 12.345;
strcpy_s(stcTEST.szStr,"Hello World!");
printf("%X %f %s",stcTEST.nNum,stcTEST.dFloat,stcTEST.szStr);
return 0;
}
這裏的代碼沒看明白
movsd xmm0, ds:qword_416490 ; 將12.345保存到浮點寄存器中
lea eax, [esp+44h+var_18]
add esp, 4
mov [esp+40h+var_28], 0AAAAh
movsd [esp+40h+var_20], xmm0
push offset aHelloWorld ; "Hello World!"
push 10h
push eax
call sub_403A3F ; strcpy函數
movsd xmm0, [esp+4Ch+var_20]
lea eax, [esp+4Ch+var_18]
add esp, 0Ch
push eax
sub esp, 8 ; 空出8字節空間保存double
movsd [esp+4Ch+var_4C], xmm0
push [esp+4Ch+var_28]
push offset aXFS ; "%X %f %s"
call sub_401090
數組是一組同類型的被連續保存的數據,而結構體也有可能與數組一樣。結構體的反匯編特征與數組一致。我理解為兩者都是內存裏開辟了一串連續的存儲空間,然後把數據根據數據類型大小存放。
【黑客免殺攻防】讀書筆記12 - 指針與數組